MailKit发送多语言邮件投递失败但System.Net.Mail正常如何解决
问题根因
该问题是旧版IIS SMTP服务与MailKit默认使用的现代MIME编码规范不兼容导致的,和业务逻辑没有直接关系:
- System.Net.Mail作为老旧类库,默认会自动适配旧SMTP服务器的能力,自动将非ASCII字符编码为旧服务器兼容的格式,不会使用新版MIME特性,因此不会被拒收,也不容易被判定为垃圾邮件。
- MailKit默认遵循最新的邮件标准,默认使用UTF-8编码、8位传输等特性,而旧版IIS SMTP已经停止维护多年,对这些特性支持不完善,遇到带重音、日文等非ASCII字符的内容时就会识别失败拒收,编码不符合旧规范也会触发垃圾邮件规则。
可行解决方案
按以下步骤修改代码即可在保留MailKit的前提下解决问题:
1. 手动构造邮件正文,显式指定兼容编码
不要直接用BodyBuilder自动生成正文,手动构造TextPart/HtmlPart,强制指定编码为UTF-8同时使用旧服务器兼容的可打印编码(Quoted-Printable),修改FormatTextEncoding方法如下:
private MimeEntity FormatTextEncoding(EmailBodyType emailBodyType, string messageBody) { switch (emailBodyType) { case EmailBodyType.HTML: return new TextPart("html") { Text = messageBody, ContentTransferEncoding = ContentEncoding.QuotedPrintable, // 显式指定UTF-8编码 ContentType = { Charset = Encoding.UTF8.WebName } }; case EmailBodyType.TEXT: default: if (emailBodyType != EmailBodyType.TEXT) { _logger.LogWarning("new content type:{contentType}", emailBodyType); } return new TextPart("plain") { Text = messageBody, ContentTransferEncoding = ContentEncoding.QuotedPrintable, ContentType = { Charset = Encoding.UTF8.WebName } }; } }
对应设置正文的代码也需要同步修改为:
// set the message body emailMessage.Body = FormatTextEncoding(emailBody.contentType, emailBody.messageBody);
2. 显式设置邮件主题的编码规则
强制主题使用兼容旧规范的RFC2047编码,在设置Subject后添加以下代码:
emailMessage.Subject = msg.detail.subject; // 新增以下两行 emailMessage.SubjectEncoding = Encoding.UTF8; emailMessage.EncodeSubjectHeaders = true;
3. 连接SMTP服务器时禁用8BITMIME扩展
旧IIS SMTP不支持8位MIME传输,连接后主动禁用该特性,修改SendMessageAsync方法:
public async Task SendMessageAsync(EmailConfiguration config, EmailNotificationMessage message, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); using (var client = _smtpClientFactory() ) { await client.ConnectAsync(config.SMTPServer, config.Port, false, cancellationToken); // 新增:禁用8位MIME传输特性,兼容旧服务器 client.Capabilities &= ~SmtpCapabilities.EightBitMime; await client.SendAsync(message.Message, cancellationToken); await client.DisconnectAsync(true, cancellationToken); } }
4. (可选)如果仍被判定为垃圾邮件,对齐System.Net.Mail的头信息
可以导出System.Net.Mail生成的邮件原始源码,对比MailKit生成的邮件头,去掉MailKit多出来的自定义头,或者补充缺失的标准头即可。
内容的提问来源于stack exchange,提问作者Saher Ahwal
相关产品推荐
相关产品推荐

