C#使用SmtpClient调用Gmail发信 向其他邮箱发件无报错失败
C# 调用Gmail SMTP发信给自己正常、外发无报错失败的解决方案
核心原因
Gmail SMTP服务对同账号内的邮件流转、外发邮件执行两套校验规则:同账号发信仅做基础身份校验,即使配置有瑕疵也能投递成功;外发邮件会触发反垃圾、协议版本、账号权限全链路校验,校验不通过时会直接静默丢弃邮件,不向客户端返回错误码,因此程序不会抛出任何异常。
逐项修复方案
- 确认使用合规的Gmail应用专用密码
2022年5月之后Gmail已关闭普通账号密码的SMTP登录权限,你必须先给发信账号开启两步验证,再生成16位的应用专用密码填入Credentials参数。使用普通账号密码、错误的应用密码时,仅同账号发信可临时走通,外发请求会被直接拦截。 - 强制配置高版本TLS协议
旧版.NET框架中SmtpClient的EnableSsl = true默认使用SSL3.0/TLS1.0协议,而Gmail外发要求必须使用TLS1.2及以上版本,协议不匹配时会直接丢信。需要在初始化SMTP客户端前加入如下配置:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; - 规避反垃圾规则拦截
你当前测试用的邮件主题Authorization!、正文body内容过于简短,没有标准的邮件头信息和身份标识,非常容易触发Gmail外发反垃圾策略。正式发信时需要补全合规的邮件内容,不要用全大写、纯链接、极短文本的内容,批量发信前需要给发信域名配置SPF、DKIM解析记录。 - 替换已过时的
SmtpClient实现
微软已在.NET Core 2.1、.NET 5及以上版本中将SmtpClient标记为过时,存在大量协议兼容隐性问题,官方推荐使用开源库MailKit实现SMTP发信,原生适配Gmail的协议要求,出现投递错误时会正常抛出异常便于排查。
修正后的可运行代码示例
// 全局配置TLS版本,放在应用启动逻辑中即可 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; var smtpClient = new SmtpClient("smtp.gmail.com") { Port = 587, UseDefaultCredentials = false, // 替换为真实的发信账号、16位应用专用密码 Credentials = new NetworkCredential("notreply.authservice@gmail.com", "xxxxxxxxxxxxxxxx"), EnableSsl = true, DeliveryMethod = SmtpDeliveryMethod.Network }; // 第二个参数替换为真实的目标收件人邮箱,确认地址无多余空格、标点错误 smtpClient.Send( from: "notreply.authservice@gmail.com", recipients: "targetuser@other-domain.com", subject: "Your site authorization code", body: "Your authorization code is 123456, it will expire in 10 minutes. If you did not request this operation, please ignore this email." );
配置完成后如果仍然外发失败,直接登录发信Gmail账号的安全中心,查看是否有「可疑登录被拦截」的安全提醒,手动确认是本人操作即可解除临时发信限制。
内容的提问来源于stack exchange,提问作者TheBubaProgrammer
相关产品推荐
相关产品推荐

