C#使用Gmail SMTP发送邮件的完整指南
1. 为什么选择Gmail的SMTP服务发送邮件在C#项目中集成邮件发送功能时Gmail的SMTP服务器是个不错的选择。首先它完全免费当然前提是你有Gmail账号其次它提供了稳定的邮件投递服务最重要的是它支持SSL/TLS加密能确保邮件传输的安全性。不过要注意Gmail对SMTP服务的使用有一些限制每天最多发送500封邮件每个用户每分钟最多发送60-100封邮件必须开启低安全性应用访问或使用应用专用密码这些限制对于个人开发者或中小型应用来说完全够用。如果你需要更高配额可以考虑G Suite的企业邮箱方案。2. 准备工作配置Gmail账户2.1 启用两步验证在开始编码前我们需要先配置Gmail账户以允许通过SMTP发送邮件。步骤如下登录你的Gmail账户访问 https://myaccount.google.com/security找到两步验证选项并启用它注意启用两步验证后你需要使用应用专用密码而不是常规密码来连接SMTP服务器。这是Google的安全策略要求。2.2 生成应用专用密码启用两步验证后在同一安全页面找到应用密码选项选择邮件作为应用类型选择设备类型可以选其他设备为这个密码命名比如MyCSharpApp点击生成按钮复制生成的16位密码注意这个密码只显示一次这个专用密码将用于我们的C#代码中而不是你的Gmail账户密码。3. C#实现SMTP邮件发送3.1 基本实现代码下面是一个完整的C#控制台应用程序示例演示如何使用Gmail SMTP发送邮件using System; using System.Net; using System.Net.Mail; class Program { static void Main(string[] args) { try { // 配置SMTP客户端 using (SmtpClient client new SmtpClient(smtp.gmail.com, 587)) { client.EnableSsl true; client.UseDefaultCredentials false; client.Credentials new NetworkCredential(your_emailgmail.com, your_app_specific_password); // 创建邮件消息 MailMessage message new MailMessage(); message.From new MailAddress(your_emailgmail.com, Your Name); message.To.Add(recipientexample.com); message.Subject Test Email from C#; message.Body This is a test email sent from a C# application using Gmail SMTP.; message.IsBodyHtml false; // 设置为true可以发送HTML格式邮件 // 发送邮件 client.Send(message); Console.WriteLine(Email sent successfully!); } } catch (Exception ex) { Console.WriteLine($Error sending email: {ex.Message}); } } }3.2 关键参数解析这段代码中有几个关键点需要注意SMTP服务器地址smtp.gmail.com端口号587这是Gmail推荐的TLS端口EnableSsl必须设置为trueUseDefaultCredentials必须设置为falseCredentials使用你的Gmail邮箱和应用专用密码3.3 发送HTML格式邮件如果你想发送格式更丰富的邮件可以将邮件内容设置为HTML格式message.IsBodyHtml true; message.Body html body h1 stylecolor:blue;Hello!/h1 pThis is an strongHTML/strong email sent from C#./p pCurrent time: DateTime.Now.ToString() /p /body /html;4. 进阶功能实现4.1 添加附件在MailMessage对象上可以轻松添加附件// 添加单个附件 message.Attachments.Add(new Attachment(C:\\path\\to\\file.pdf)); // 添加多个附件 string[] attachments { file1.pdf, file2.jpg, file3.docx }; foreach (string file in attachments) { message.Attachments.Add(new Attachment(file)); }4.2 抄送和密送// 添加抄送 message.CC.Add(cc1example.com); message.CC.Add(cc2example.com); // 添加密送 message.Bcc.Add(bccexample.com);4.3 异步发送邮件为了避免阻塞主线程可以使用异步方式发送邮件async Task SendEmailAsync() { using (SmtpClient client new SmtpClient(smtp.gmail.com, 587)) { client.EnableSsl true; client.UseDefaultCredentials false; client.Credentials new NetworkCredential(your_emailgmail.com, your_app_specific_password); MailMessage message new MailMessage(); message.From new MailAddress(your_emailgmail.com); message.To.Add(recipientexample.com); message.Subject Async Test Email; message.Body This email was sent asynchronously.; await client.SendMailAsync(message); } }5. 常见问题与解决方案5.1 认证失败错误错误信息The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Authentication Required解决方案确保已按照前面的步骤生成了应用专用密码确认UseDefaultCredentials设置为false检查是否启用了SSL确保Gmail账户已开启允许不够安全的应用虽然不建议长期使用此选项5.2 连接超时问题错误信息A connection attempt failed because the connected party did not properly respond after a period of time解决方案检查防火墙设置确保允许出站连接到smtp.gmail.com:587尝试使用不同的网络环境某些公司网络可能屏蔽SMTP端口考虑增加超时时间client.Timeout 30000; // 30秒超时5.3 邮件被标记为垃圾邮件如果收件人发现你的邮件进入了垃圾邮件箱可以尝试以下方法设置合理的发件人名称而不仅仅是邮箱地址避免使用可疑的主题行如大量感叹号、全大写等在邮件正文中添加退订链接确保邮件内容不是纯图片而缺少文本内容6. 最佳实践与性能优化6.1 重用SmtpClient实例如果需要发送大量邮件不要为每封邮件都创建新的SmtpClient实例。相反创建一个实例并重复使用它// 在应用程序启动时创建 SmtpClient client new SmtpClient(smtp.gmail.com, 587); client.EnableSsl true; client.UseDefaultCredentials false; client.Credentials new NetworkCredential(your_emailgmail.com, your_app_specific_password); // 在需要发送邮件时使用这个实例 for (int i 0; i 100; i) { MailMessage message new MailMessage(); // 配置message... client.Send(message); message.Dispose(); // 记得释放MailMessage资源 } // 在应用程序关闭时释放 client.Dispose();6.2 使用配置文件和依赖注入在生产环境中建议将SMTP配置放在配置文件中并使用依赖注入appsettings.json:{ EmailSettings: { SmtpServer: smtp.gmail.com, Port: 587, Username: your_emailgmail.com, Password: your_app_specific_password, FromName: Your Application } }C#代码:// 在Startup.cs或类似位置配置服务 services.ConfigureEmailSettings(Configuration.GetSection(EmailSettings)); services.AddTransientIEmailService, EmailService(); // EmailService实现 public class EmailService : IEmailService { private readonly EmailSettings _emailSettings; public EmailService(IOptionsEmailSettings emailSettings) { _emailSettings emailSettings.Value; } public async Task SendEmailAsync(string to, string subject, string body) { using (var client new SmtpClient(_emailSettings.SmtpServer, _emailSettings.Port)) { client.EnableSsl true; client.UseDefaultCredentials false; client.Credentials new NetworkCredential( _emailSettings.Username, _emailSettings.Password); var message new MailMessage { From new MailAddress(_emailSettings.Username, _emailSettings.FromName), Subject subject, Body body, IsBodyHtml true }; message.To.Add(to); await client.SendMailAsync(message); } } }6.3 处理批量邮件发送当需要发送大量邮件时要注意Gmail的发送限制并实现适当的延迟public async Task SendBulkEmails(Liststring recipients, string subject, string body) { using (var client new SmtpClient(smtp.gmail.com, 587)) { client.EnableSsl true; client.UseDefaultCredentials false; client.Credentials new NetworkCredential(your_emailgmail.com, your_app_specific_password); int sentCount 0; foreach (var email in recipients) { try { var message new MailMessage(); message.From new MailAddress(your_emailgmail.com); message.To.Add(email); message.Subject subject; message.Body body; message.IsBodyHtml true; await client.SendMailAsync(message); sentCount; // 每发送50封邮件后暂停1分钟 if (sentCount % 50 0) { await Task.Delay(60000); } } catch (Exception ex) { // 记录错误但继续发送下一封 Console.WriteLine($Error sending to {email}: {ex.Message}); } } } }7. 安全注意事项7.1 保护应用专用密码应用专用密码应该被妥善保管不要硬编码在源代码中不要提交到版本控制系统最好存储在安全的配置系统或密钥管理服务中7.2 使用环境变量存储敏感信息一种更安全的方式是使用环境变量存储SMTP凭证string email Environment.GetEnvironmentVariable(SMTP_EMAIL); string password Environment.GetEnvironmentVariable(SMTP_PASSWORD); client.Credentials new NetworkCredential(email, password);7.3 定期轮换应用密码为了安全起见应该定期在Google账户中撤销旧的应用密码并生成新的。8. 替代方案与扩展8.1 使用MailKit替代SmtpClientMicrosoft官方建议考虑使用MailKit等第三方库替代.NET内置的SmtpClient。MailKit提供了更现代、更强大的邮件处理能力。using MailKit.Net.Smtp; using MimeKit; var message new MimeMessage(); message.From.Add(new MailboxAddress(Your Name, your_emailgmail.com)); message.To.Add(new MailboxAddress(Recipient Name, recipientexample.com)); message.Subject Test Email using MailKit; message.Body new TextPart(plain) { Text This is a test email sent using MailKit. }; using (var client new SmtpClient()) { client.Connect(smtp.gmail.com, 587, false); client.Authenticate(your_emailgmail.com, your_app_specific_password); client.Send(message); client.Disconnect(true); }8.2 实现邮件模板系统对于需要发送格式化邮件的应用可以实现一个模板系统public string RenderEmailTemplate(string templateName, object model) { string template File.ReadAllText($Templates/{templateName}.html); // 简单替换实际项目中可以使用Razor引擎等更强大的模板引擎 foreach (var prop in model.GetType().GetProperties()) { template template.Replace(${{{{ {prop.Name} }}}}, prop.GetValue(model)?.ToString()); } return template; } // 使用示例 var model new { UserName John Doe, ActivationLink https://example.com/activate/123 }; string body RenderEmailTemplate(WelcomeEmail, model);8.3 添加邮件发送日志为了调试和审计目的应该记录邮件发送日志public class EmailLogger { public async Task LogEmail(string to, string subject, bool success, string error null) { string logEntry ${DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} | To: {to} | Subject: {subject} | Status: {(success ? Success : Failed)}; if (!success) { logEntry $ | Error: {error}; } await File.AppendAllTextAsync(email_log.txt, logEntry Environment.NewLine); } }9. 实际项目中的集成建议在实际项目中邮件发送通常不是独立功能而是与其他业务逻辑结合。以下是一些常见场景的实现建议9.1 用户注册验证邮件public async Task SendVerificationEmail(string email, string verificationToken) { string verificationUrl $https://yourapp.com/verify?token{verificationToken}; string emailBody $ html body h2Welcome to Our Service!/h2 pPlease click the following link to verify your email address:/p pa href{verificationUrl}{verificationUrl}/a/p pIf you didnt request this, please ignore this email./p /body /html; await _emailService.SendEmailAsync(email, Verify Your Email, emailBody); }9.2 密码重置邮件public async Task SendPasswordResetEmail(string email, string resetToken) { string resetUrl $https://yourapp.com/reset-password?token{resetToken}; string emailBody $ html body h2Password Reset Request/h2 pWe received a request to reset your password. Click the link below to proceed:/p pa href{resetUrl}{resetUrl}/a/p pThis link will expire in 24 hours. If you didnt request a password reset, please ignore this email./p /body /html; await _emailService.SendEmailAsync(email, Password Reset Instructions, emailBody); }9.3 系统通知邮件public async Task SendSystemNotification(string subject, string message) { string adminEmail adminyourapp.com; string emailBody $ html body h2System Notification/h2 h3{subject}/h3 div stylebackground-color:#f5f5f5; padding:15px; border-left:4px solid #ff6a00; {message} /div pThis is an automated message. Please do not reply directly to this email./p /body /html; await _emailService.SendEmailAsync(adminEmail, $[System] {subject}, emailBody); }10. 测试与调试技巧10.1 使用测试收件箱在开发阶段建议使用测试邮箱如Mailinator或临时邮箱服务而不是真实邮箱进行测试。10.2 捕获并分析SMTP通信可以使用如Papercut这样的SMTP测试工具来捕获和分析应用程序发送的邮件而不需要实际发送出去。10.3 单元测试邮件发送虽然测试实际邮件发送比较困难但可以测试邮件生成逻辑[Test] public void TestWelcomeEmailGeneration() { var service new EmailService(); string email service.GenerateWelcomeEmail(John); Assert.IsTrue(email.Contains(Welcome John)); Assert.IsTrue(email.Contains(html)); }10.4 处理各种异常情况确保你的代码能够优雅地处理各种异常情况try { await _emailService.SendEmailAsync(email, subject, body); } catch (SmtpFailedRecipientException ex) { // 处理特定收件人失败的情况 _logger.LogError($Failed to send to {ex.FailedRecipient}: {ex.Message}); } catch (SmtpException ex) { // 处理SMTP协议错误 _logger.LogError($SMTP error: {ex.StatusCode} - {ex.Message}); } catch (Exception ex) { // 处理其他所有错误 _logger.LogError($Unexpected error sending email: {ex.Message}); }11. 性能监控与优化11.1 记录邮件发送指标public class EmailMetrics { private readonly ConcurrentDictionarystring, int _counters new ConcurrentDictionarystring, int(); public void Increment(string metricName) { _counters.AddOrUpdate(metricName, 1, (_, count) count 1); } public IDictionarystring, int GetMetrics() { return _counters.ToDictionary(kvp kvp.Key, kvp kvp.Value); } } // 使用示例 _metrics.Increment(emails.sent); _metrics.Increment($emails.sent.{status});11.2 实现邮件队列对于高负载系统考虑实现邮件队列以避免阻塞主业务流程public class EmailQueue { private readonly BlockingCollectionEmailTask _queue new BlockingCollectionEmailTask(); private readonly IEmailService _emailService; public EmailQueue(IEmailService emailService) { _emailService emailService; // 启动后台处理线程 Task.Run(ProcessQueue); } public void Enqueue(EmailTask task) { _queue.Add(task); } private async Task ProcessQueue() { foreach (var task in _queue.GetConsumingEnumerable()) { try { await _emailService.SendEmailAsync(task.To, task.Subject, task.Body); task.OnSuccess?.Invoke(); } catch (Exception ex) { task.OnFailure?.Invoke(ex); } } } } public class EmailTask { public string To { get; set; } public string Subject { get; set; } public string Body { get; set; } public Action OnSuccess { get; set; } public ActionException OnFailure { get; set; } }11.3 监控Gmail发送限制为了避免达到Gmail的发送限制可以跟踪发送量public class EmailQuotaTracker { private readonly int _dailyLimit; private readonly int _minuteLimit; private int _dailyCount; private int _minuteCount; private DateTime _lastReset; public EmailQuotaTracker(int dailyLimit 500, int minuteLimit 60) { _dailyLimit dailyLimit; _minuteLimit minuteLimit; _lastReset DateTime.UtcNow; } public bool CanSend() { // 如果新的一天开始了重置计数器 if (DateTime.UtcNow.Date _lastReset.Date) { _dailyCount 0; _minuteCount 0; _lastReset DateTime.UtcNow; } // 如果新的一分钟开始了重置分钟计数器 else if (DateTime.UtcNow.Minute _lastReset.Minute) { _minuteCount 0; _lastReset DateTime.UtcNow; } return _dailyCount _dailyLimit _minuteCount _minuteLimit; } public void RecordSend() { _dailyCount; _minuteCount; } }12. 部署注意事项12.1 不同环境配置确保为开发、测试和生产环境使用不同的配置开发环境 appsettings.Development.json:{ EmailSettings: { SmtpServer: smtp.gmail.com, Port: 587, Username: devexample.com, Password: dev_app_password, FromName: DEV Environment } }生产环境 appsettings.Production.json:{ EmailSettings: { SmtpServer: smtp.gmail.com, Port: 587, Username: noreplyyourdomain.com, Password: prod_app_password, FromName: Your Application } }12.2 Docker容器中的配置如果在Docker容器中运行可以通过环境变量注入配置Dockerfile:FROM mcr.microsoft.com/dotnet/aspnet:6.0 ... ENV SMTP_EMAILnoreplyyourdomain.com ENV SMTP_PASSWORDyour_app_password ...12.3 云服务部署在Azure、AWS等云平台部署时使用平台提供的密钥管理服务存储SMTP凭证Azure Key Vault示例:var secretClient new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential()); KeyVaultSecret smtpPassword await secretClient.GetSecretAsync(SmtpPassword); var emailSettings new EmailSettings { Password smtpPassword.Value // 其他设置... };13. 维护与更新策略13.1 定期检查SMTP配置Google可能会更新其SMTP服务要求建议每季度检查一次SMTP设置是否仍然有效订阅Google Workspace更新通知定期测试邮件发送功能13.2 备用SMTP服务器配置为了防止Gmail SMTP服务不可用可以配置备用SMTP服务器public async Task SendEmailWithFallback(string to, string subject, string body) { var smtpServers new[] { new { Host smtp.gmail.com, Port 587 }, new { Host smtp.mail.yahoo.com, Port 587 }, new { Host smtp.sendgrid.net, Port 587 } }; foreach (var server in smtpServers) { try { using (var client new SmtpClient(server.Host, server.Port)) { client.EnableSsl true; client.UseDefaultCredentials false; client.Credentials new NetworkCredential(your_email, your_password); var message new MailMessage(your_email, to, subject, body); await client.SendMailAsync(message); return; // 发送成功则退出 } } catch { // 记录错误并尝试下一个服务器 continue; } } throw new Exception(All SMTP servers failed); }13.3 依赖库更新策略定期更新相关NuGet包如MailKit并测试兼容性订阅库的更新通知在非生产环境先测试新版本保留回滚方案14. 扩展阅读与资源14.1 官方文档参考Gmail SMTP设置官方指南.NET SmtpClient文档MailKit GitHub仓库14.2 相关工具推荐Papercut SMTP测试工具MailHog - 本地邮件测试服务器FluentEmail - .NET邮件发送库14.3 进阶主题实现DKIM和SPF认证提高邮件送达率使用SendGrid或Mailgun等专业邮件服务构建分布式邮件发送系统邮件模板引擎设计与实现15. 总结与个人经验分享在实际项目中使用Gmail SMTP服务发送邮件已经多年这里分享一些个人经验关于应用专用密码我习惯为每个环境开发、测试、生产创建不同的应用密码这样如果某个密码泄露可以单独撤销而不影响其他环境。错误处理早期项目中没有充分处理SMTP异常导致一些重要邮件静默失败。现在我总是实现完善的错误处理和重试逻辑。性能考虑在需要发送大量邮件的系统中我发现重用SmtpClient实例可以显著提高性能但要注意正确释放资源。测试策略建立自动化测试验证邮件发送功能非常重要可以使用Mock对象来避免实际发送测试邮件。监控在生产环境中实施邮件发送监控跟踪成功率、延迟等指标及时发现并解决问题。最后提醒一点虽然Gmail SMTP方便免费但对于商业应用或高流量场景建议考虑专业的邮件发送服务它们通常提供更好的送达率、分析工具和更高的发送限额。

相关新闻

TI高速USB主机子系统寄存器配置与OHCI驱动实战解析

TI高速USB主机子系统寄存器配置与OHCI驱动实战解析

1. 从寄存器手册到实战:TI高速USB主机子系统深度解析在嵌入式系统开发中,USB主机控制器(USB Host Controller)是连接外部世界的关键桥梁。无论是消费电子设备上的U盘读取、工业控制中的传感器数据采集,还是汽车电子里的…

2026/9/25 20:10:25 阅读更多 →
Codex 与 Claude:同一思路的不同实现

Codex 与 Claude:同一思路的不同实现

不同 Agent 的记忆机制形式不同,但底层思路很接近:从历史任务里提炼经验,存成本地可读文件,再在相关任务里召回。 对比维度 Codex 类机制 Claude 类机制 触发方式 更偏后台自动从历史会话里提炼 更偏在项目执行中主动整理 组织形态…

2026/9/21 18:47:46 阅读更多 →
DAZ角色表情映射ARKit全流程:从Morph到BlendShape的实战指南

DAZ角色表情映射ARKit全流程:从Morph到BlendShape的实战指南

1. 项目概述:为什么我们需要从DAZ到ARKit的表情映射?如果你正在尝试将DAZ Studio里那些精美、富有表现力的3D角色,通过ARKit驱动,变成一个能在iPhone或iPad上实时互动的虚拟形象,那你一定遇到过这个核心难题&#xff1…

2026/9/25 2:06:28 阅读更多 →

最新新闻

Atlas 300V推理加速卡实战:从环境配置到YOLO模型部署全解析

Atlas 300V推理加速卡实战:从环境配置到YOLO模型部署全解析

先把结论放到最前面:Atlas 300V系列毫无疑问是运算加速卡,但它的"加速"和大多数人熟悉的GPU加速完全是两码事。我见过不少朋友把这张卡买回来,插上服务器,装好驱动,然后对着npu-smi里那一串输出发呆——接下…

2026/9/26 8:51:37 阅读更多 →
Cosine学习率调度器原理与实战调优指南

Cosine学习率调度器原理与实战调优指南

1. 为什么你调不出SOTA模型?——学习率调度器不是“开关”,而是“油门刹车方向盘”的协同系统我带过三届AI方向的毕业设计,每年都有学生拿着同样的ResNet50架构、同样的数据集、同样的优化器,最后指标差了3~5个点。追问原因&#…

2026/9/26 8:51:37 阅读更多 →
WorkBuddy Enterprise企业级AI平台与Agent生态架构设计及落地实践

WorkBuddy Enterprise企业级AI平台与Agent生态架构设计及落地实践

1. 从WorkBuddy Enterprise看企业级AI平台的真实需求第一次看到“WorkBuddy Enterprise 企业级AI平台与Agent生态产品概要”这个标题,我脑子里蹦出来的第一个念头是:又一个企业级AI平台?但仔细琢磨“Agent生态”这四个字,事情就没…

2026/9/26 8:51:36 阅读更多 →
Atlas 300V 24G部署YOLO全指南:环境搭建、模型转换与性能调优

Atlas 300V 24G部署YOLO全指南:环境搭建、模型转换与性能调优

如果你最近在搜索框里敲下“atlas部署yolo”,又顺手翻了翻“atlas 300v 24g 是运算加速卡吗”,我猜你多半是刚拿到一块昇腾Atlas板卡,正琢磨怎么把它用起来。先直接回答那个朴素的疑问:是的,Atlas 300V 24G就是一张运算…

2026/9/26 8:51:36 阅读更多 →
DeskcommCRM实战:从客户全生命周期到私有化部署的完整指南

DeskcommCRM实战:从客户全生命周期到私有化部署的完整指南

做业务的人最头疼的往往不是拿到不客户,而是客户信息全散在Excel表、微信聊天、售后记录和一堆名片里。团队一旦超过几个人,这种“个人通讯录式”的客户管理方式就会慢慢变成黑洞:销售跟到哪一步了没人知道,老客户谁在跟进搞不清楚…

2026/9/26 8:51:36 阅读更多 →
数智码力:普通人学Python,不必追求独立开发项目,会“改造脚本”就够用

数智码力:普通人学Python,不必追求独立开发项目,会“改造脚本”就够用

很多新手自学Python,都被错误的学习标准误导:认为学Python的终极目标,是从零独立开发完整项目,写出专属代码。达不到这个标准,就觉得自己没学好、学无用功。其实对于99%的普通人、职场人、学生而言,完全不需…

2026/9/26 8:50:36 阅读更多 →

日新闻

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、…

2026/9/26 0:00:25 阅读更多 →
学校官网模拟全流程实践:从页面布局到后端接口与部署

学校官网模拟全流程实践:从页面布局到后端接口与部署

如果你正在找一门 Web 大作业的题目,或者刚开始接触 Web 前端开发想做点能拿来展示的东西,“学校官网模拟”几乎是最稳的选择。题目看着简单,但要把导航、新闻列表、轮播 Banner、二级页面、后台数据都串起来,其实已经把前端布局、…

2026/9/26 0:00:25 阅读更多 →
超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

简介:这是一份面向游戏开发初学者与C进阶学习者的超级玛丽(超级马里奥)游戏源码,基于C面向对象编程实现,适合想通过经典项目理解游戏主循环、角色类设计、地图关卡加载与物理碰撞检测的读者参考。压缩包共49个文件&…

2026/9/26 0:00:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/25 19:27:14 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/25 20:29:09 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/25 20:29:43 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/25 20:29:31 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/25 19:27:26 阅读更多 →