.NET 6+ 中 SmtpClient 发带附件邮件已过时且默认禁用 SSL/TLS 协商,需手动配置 EnableSsl、Credentials 和正确端口,并推荐改用 MailKit 替代。

直接说结论:用 SmtpClient 发带附件的邮件在 .NET 6+ 已被标记为过时,且默认禁用 SSL/TLS 协商,不配好会直接报错或静默失败。
为什么 SmtpClient 发附件经常“没反应”或报 AuthenticationFailed
这不是代码写错了,而是底层行为变了:SmtpClient 在 .NET Core 2.1 后不再自动启用 STARTTLS,也不再信任自签名证书;很多邮箱(如 QQ、163)强制要求 TLS 1.2+ + 显式凭据 + 正确端口,缺一不可。
- 常见错误现象:
SmtpException: The SMTP server requires a secure connection or the client was not authenticated - QQ 邮箱必须用 POP3/SMTP 开启后的“授权码”,不是登录密码
- 163 邮箱要求 SMTP 端口为
465(SSL)或587(STARTTLS),但SmtpClient对465的处理有兼容问题 - 附件路径含中文或空格时,
Attachment构造器不报错但实际发送失败——得用new Attachment(filePath, MediaTypeNames.Application.Octet)显式指定类型
怎么让 SmtpClient 在 .NET 6 中真正发出去
必须手动补全三个关键配置,缺一不可:
- 设置
EnableSsl = true(对应端口 465)或EnableSsl = false+DeliveryMethod = SmtpDeliveryMethod.Network+ 手动调client.SendAsync()前确保服务端支持 STARTTLS(端口 587) - 显式指定
Credentials = new NetworkCredential("xxx@163.com", "授权码"),不能靠UseDefaultCredentials = true - 附件添加后,务必检查
MailMessage.Attachments.Count是否为预期值——Attachments.Add()不抛异常,但传入 null 或非法路径会静默丢弃
示例关键片段:
var msg = new MailMessage();
msg.From = new MailAddress("a@163.com");
msg.To.Add("b@qq.com");
msg.Subject = "测试";
msg.Body = "正文";
var attachment = new Attachment(@"C:\test\报告.pdf", MediaTypeNames.Application.Octet);
msg.Attachments.Add(attachment);
using var client = new SmtpClient("smtp.163.com") {
Port = 465,
EnableSsl = true,
Credentials = new NetworkCredential("a@163.com", "xxxxxx")
};
await client.SendMailAsync(msg);
更稳的替代方案:用 MailKit 替掉 SmtpClient
SmtpClient 的设计已无法适配现代 SMTP 服务的认证和加密策略,MailKit 是目前最成熟的跨平台替代,它把 SSL/TLS 模式、认证方式、证书验证都暴露为可选项。
- 发附件不用手动设 MIME 类型,
builder.Attachments.Add("path.pdf")自动识别 - 明确区分
SecureSocketOptions.SslOnConnect(端口 465)和StartTlsWhenAvailable(端口 587) - 支持 OAuth2(Gmail / Outlook),而
SmtpClient完全不支持 - 错误信息具体到协议层,比如
AuthenticationException: Invalid credentials而不是笼统的SmtpException
最小可用示例:
var message = new MimeMessage();
message.From.Add(new MailboxAddress("发件人", "a@163.com"));
message.To.Add(new MailboxAddress("收件人", "b@qq.com"));
message.Subject = "带附件";
var builder = new BodyBuilder();
builder.TextBody = "正文";
builder.Attachments.Add(@"C:\test\截图.png");
message.Body = builder.ToMessageBody();
using var client = new SmtpClient();
await client.ConnectAsync("smtp.163.com", 465, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync("a@163.com", "授权码");
await client.SendAsync(message);
await client.DisconnectAsync(true);
真正麻烦的从来不是“怎么加附件”,而是 SMTP 服务端对 TLS 版本、证书链、认证方式的隐性要求——这些细节不会出现在异常堆栈里,只会在你反复试端口和开关 EnableSsl 时悄悄消耗时间。


















