C# 调用邮箱应用发送带附件的邮件

C# 调用邮箱应用发送带附件的邮件

大家好,我是你们的技术博主。今天咱们来聊聊一个非常实用的技能:用 C# 代码发送带附件的邮件 。很多业务场景都会用到这个功能,比如系统自动把报表发到邮箱、把日志打包发给管理员、或者给用户发送电子发票等等。虽然听起来"发邮件"挺简单,但里面有不少细节,尤其是附件处理SMTP 配置 ,稍不注意就会踩坑。咱们今天就用通俗易懂的方式,把这个功能彻底讲明白。---### 1. 准备工作:你需要什么?在写代码之前,你得先明确一个概念:C# 本身不会发邮件,它只是"指挥"一个邮件服务器(SMTP 服务器)去发 。所以你需要:- 一个可用的 SMTP 服务器地址和端口(比如公司邮箱的 SMTP,或者 QQ邮箱、163邮箱、Gmail 等)。- 一个邮箱账号和密码(或者授权码,很多邮箱现在要求用授权码而不是密码)。- 你的项目需要引用 System.Net.Mail 命名空间(这是 .NET 内置的,不需要额外安装 NuGet 包)。> 小贴士 :如果你用的是 .NET Core / .NET 5+,用 System.Net.Mail 依然没问题,但更推荐用 MailKit 这个第三方库,功能更强大,支持异步。不过我们今天先讲内置的,因为它简单直接,适合大部分场景。---### 2. 最简单的发送邮件代码(不带附件)我们先从最基础的开始:发一封纯文本邮件。这样你能快速跑通流程,再一步步加上附件。csharpusing System;using System.Net;using System.Net.Mail;class Program{ static void Main(string[] args) { // 1. 配置 SMTP 服务器信息 string smtpHost = "smtp.qq.com"; // 例如 QQ 邮箱的 SMTP 地址 int smtpPort = 587; // QQ 邮箱的 SMTP 端口(SSL 用 465,TLS 用 587) string senderEmail = "your_email@qq.com"; string senderPassword = "你的授权码"; // 注意:不是登录密码,是邮箱设置的授权码 // 2. 创建邮件对象 MailMessage mail = new MailMessage(); mail.From = new MailAddress(senderEmail, "发件人显示名"); mail.To.Add("recipient@example.com"); // 收件人 mail.Subject = "测试邮件"; mail.Body = "你好,这是一封测试邮件!"; mail.IsBodyHtml = false; // 如果邮件内容包含 HTML,就设为 true // 3. 创建 SMTP 客户端并发送 using (SmtpClient client = new SmtpClient(smtpHost, smtpPort)) { client.EnableSsl = true; // 启用 SSL 加密 client.Credentials = new NetworkCredential(senderEmail, senderPassword); client.Send(mail); // 同步发送 } Console.WriteLine("邮件发送成功!"); }}代码解释 :- MailMessage 是邮件内容的载体,包括发件人、收件人、主题、正文。- SmtpClient 负责与 SMTP 服务器通信,EnableSsl 很重要,很多邮箱强制要求加密。- NetworkCredential 用来验证身份,这里的"密码"必须是授权码 ,不是你的邮箱登录密码(尤其是 QQ、163 等邮箱)。---### 3. 发送带附件的邮件(核心重点)现在进入今天的主题------附件 。附件可以是本地文件路径,也可以是从内存中生成的字节流。我们分两种方式讲。#### 3.1 从本地文件添加附件这是最常见的方式。比如你要把 C:\Reports\sales.xlsx 发给收件人。csharpusing System;using System.Net;using System.Net.Mail;class Program{ static void Main(string[] args) { // 1. 基础配置(同上) string smtpHost = "smtp.163.com"; int smtpPort = 465; // 163 邮箱 SSL 端口 string senderEmail = "your_email@163.com"; string senderPassword = "你的授权码"; // 2. 创建邮件 MailMessage mail = new MailMessage(); mail.From = new MailAddress(senderEmail); mail.To.Add("boss@company.com"); mail.Subject = "月度销售报表"; mail.Body = "老板,这是本月销售数据,请查收。"; mail.IsBodyHtml = false; // 3. 添加附件(核心!) string filePath = @"C:\Reports\sales.xlsx"; // 文件路径 if (System.IO.File.Exists(filePath)) // 判断文件是否存在 { Attachment attachment = new Attachment(filePath); mail.Attachments.Add(attachment); } else { Console.WriteLine("附件文件不存在:" + filePath); return; // 如果文件不存在,直接退出 } // 4. 发送 using (SmtpClient client = new SmtpClient(smtpHost, smtpPort)) { client.EnableSsl = true; client.Credentials = new NetworkCredential(senderEmail, senderPassword); client.Send(mail); } // 释放资源(Attachment 实现了 IDisposable) foreach (Attachment att in mail.Attachments) { att.Dispose(); } Console.WriteLine("带附件的邮件发送成功!"); }}注意点 :- Attachment 需要 using 或者手动 Dispose(),否则可能占用文件句柄。- 如果文件路径包含中文或空格,Attachment 会自动处理,但最好不要在文件名里加奇怪字符 ,避免邮件客户端乱码。- 如果附件大于 SMTP 服务器的限制(一般 20MB 左右),会发送失败,需要压缩或拆分。#### 3.2 从内存字节流添加附件(高级玩法)有时候文件不在本地磁盘,而是程序生成的(比如从数据库读取的 PDF、动态生成的 Excel)。这时候可以用 MemoryStream 来创建附件,避免临时生成临时文件。csharpusing System;using System.IO;using System.Net;using System.Net.Mail;using System.Text;class Program{ static void Main(string[] args) { // 1. 基础配置 string smtpHost = "smtp.gmail.com"; int smtpPort = 587; string senderEmail = "your@gmail.com"; string senderPassword = "你的应用专用密码"; // Gmail 需要开启两步验证并生成应用密码 // 2. 创建邮件 MailMessage mail = new MailMessage(); mail.From = new MailAddress(senderEmail); mail.To.Add("recipient@example.com"); mail.Subject = "内存生成的附件"; mail.Body = "这个附件是程序直接生成的,没有经过磁盘。"; // 3. 在内存中生成一个文本文件内容(模拟生成文件) string content = "这是一个测试内容,可以换成任意数据。"; byte[] bytes = Encoding.UTF8.GetBytes(content); // 转成字节数组 using (MemoryStream ms = new MemoryStream(bytes)) { // 从流创建附件,并指定文件名 Attachment attachment = new Attachment(ms, "test.txt", "text/plain"); mail.Attachments.Add(attachment); // 4. 发送(注意:要在 using 块内发送,因为流不能提前释放) using (SmtpClient client = new SmtpClient(smtpHost, smtpPort)) { client.EnableSsl = true; client.Credentials = new NetworkCredential(senderEmail, senderPassword); client.Send(mail); } } // 这里 MemoryStream 会被释放,附件也会随之释放 Console.WriteLine("内存附件发送成功!"); }}代码亮点 :- 用 MemoryStream 代替文件路径,附件数据完全在内存中,适合动态生成内容。- Attachment 构造函数接受 StreamnamecontentType 三个参数,这里用 text/plain 表示文本类型,如果是 PDF 就用 application/pdf。- 注意作用域MemoryStream 必须在发送完成后才能释放,否则附件数据会丢失。所以发送逻辑写在 using 块内。---### 4. 常见问题与踩坑指南#### 4.1 授权码 vs 密码- 很多邮箱(QQ、163、Gmail)不允许直接用账号密码通过 SMTP 验证,必须去邮箱设置里生成"授权码"或"应用专用密码"。如果你用密码登录失败,第一反应就是去生成授权码。#### 4.2 SSL/端口配置- 不同邮箱端口不同,常见组合: - QQ:465(SSL)或 587(TLS) - 163:465(SSL) - Gmail:465(SSL)或 587(TLS)- 如果你不确定,直接查邮箱官方的 SMTP 设置文档。#### 4.3 附件大小限制- 企业邮箱一般限制 10~20MB,超过会报错。你可以先压缩文件或分割附件。#### 4.4 异步发送- 上面的代码是同步的,如果邮件比较大,可能会卡住 UI(如果是在 WinForm 里用)。建议用 client.SendMailAsync(mail) 并配合 async/await,不过要注意线程安全。---### 5. 总结今天我们学习了用 C# 发送带附件的邮件,核心要点有三条:1. SMTP 配置 :服务器地址、端口、授权码,一个都不能少。2. 附件添加 :本地文件用 Attachment(filePath),内存数据用 MemoryStream + Attachment(stream, name, contentType)。3. 资源管理SmtpClientAttachment 都实现了 IDisposable,最好用 using 包裹,避免文件句柄泄漏。另外,如果你要开发生产级应用,建议考虑:- 异步发送避免阻塞。- 用 MailKit 库处理更复杂的场景(比如 IMAP 接收、更灵活的加密协议)。- 邮件发送失败时要捕获异常并重试,比如 SmtpException。希望这篇文章能帮你少踩点坑,让你的邮件功能"飞"起来!如果你有更具体的需求(比如附件是 Excel 自动生成的),欢迎在评论区留言,我们下期见!

相关推荐
TunerT_TQ1 小时前
GitHub深度工程评测:Cline 源码级工程评测|65k Star 开源AI编程助手的工程全景
typescript·开源·github·vs code·ai编程助手·开源供应链安全·静态源码审计
m4Rk_2 小时前
【论文阅读】Agent 记忆机制(26):Infini Memory——将长期记忆维护成可读写的主题文档
论文阅读·人工智能·学习·开源·github
BuHuaX2 小时前
U3D抖微小游戏开发流程 (一)
unity·c#·游戏引擎·游戏策划
qetfw2 小时前
Debian 配置 AIDE 文件完整性检测:基线初始化、变更检查与数据库更新
linux·网络·数据库·debian
脚踏实地皮皮晨2 小时前
003003002_WPF Grid 基类官方类定义逐行深度解析
开发语言·windows·算法·c#·wpf·visual studio
zhbcddxr2 小时前
北京企业GEO防御风控能力测评:投毒监测与偏差修正排行
网络·人工智能·安全
星恒讯工业路由器9 小时前
AGV集群通信架构:从单点到百台级调度的挑战与对策
网络·物联网·信息与通信·工业物联网·通信架构·agv集群·实时调度
夜月yeyue10 小时前
AUTOSAR CP 从上电到 Runnable
c语言·网络·tcp/ip·车载系统