翼度科技»论坛 编程开发 .net 查看内容

.Net FrameWork 框架下使用System.Net.Mail封装类 发送邮件失败:服务器响应

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
偶然兴起,想做一个后台监控PLC状态的服务。功能如下:监控到PLC状态值异常后触发邮件推送,状态改变后只推送一次。开始使用的是.net6.0开发框架开发,一切都很顺利,邮件也能正常推送。但由于现场工控机系统不是WIN10 20H2的最新版本,导致系统未安装.Net6.0 Runtime。而我也没有再去安装的打算。我重新使用了.net FrameWork4.7 框架进行开发。开发完成后,我以为能正常运行。但出现了不可预知的错误——服务器响应:5.7.1 Client was not authenticated。下面分别是2个框架下发送邮件的代码:
.Net 6.0框架:
点击查看代码
  1. public bool Send()
  2. {
  3.     try
  4.     {
  5.         SmtpClient smtp = new SmtpClient(this.Host!, (int)this.Port!) { Credentials = new NetworkCredential(this.User!, this.Password!), EnableSsl = true, UseDefaultCredentials = false };
  6.         MailMessage message = new MailMessage(this.SenderAddress!, this.ReciverAddress!, this.Subject, this.Body) { From = new MailAddress(this.SenderAddress!, this.SenderName) };
  7.         ServicePointManager.ServerCertificateValidationCallback = delegate (object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
  8.         {
  9.             return true;
  10.         };
  11.         smtp.Send(message);
  12.         return true;
  13.     }
  14.     catch (Exception)
  15.     {
  16.         return false;
  17.     }
  18. }
复制代码
.Net FrameWork 4.7 框架:
点击查看代码
  1. public bool Send()
  2. {
  3.     try
  4.     {
  5.         SmtpClient smtp = new SmtpClient(this.Host!, (int)this.Port!) { Credentials = new NetworkCredential(this.User!, this.Password!), EnableSsl = true, UseDefaultCredentials = false };
  6.         MailMessage message = new MailMessage(this.SenderAddress!, this.ReciverAddress!, this.Subject, this.Body) { From = new MailAddress(this.SenderAddress!, this.SenderName) };
  7.         ServicePointManager.ServerCertificateValidationCallback = delegate (object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
  8.         {
  9.             return true;
  10.         };
  11.         smtp.Send(message);
  12.         return true;
  13.     }
  14.     catch (Exception)
  15.     {
  16.         return false;
  17.     }
  18. }
复制代码
在不同的开发框架下,使用的代码完全一致。但是在.Net FrameWork 4.7 框架下发送邮件才会出现异常:**5.7.1 Client was not authenticated**,而.Net 6.0 环境下不会。我不得不怀疑是不是微软的封装类System.Net.Mail存在问题。经过断点调试,终于发现了2个环境发送邮件时存在的差异。
.Net 6.0框架下用户传入的凭证(账号密码)SMTP服务器可正常获取到

.Net FrameWork 框架下竟然获取的凭证为空

经过短暂思考,我决定修改下.Net FrameWork框架下的开发代码。如下:
点击查看代码
  1. public bool Send()
  2. {
  3.     try
  4.     {
  5.         smtp = new SmtpClient(this.Host, (int)this.Port);
  6.         smtp.Credentials = new NetworkCredential(this.User,this.Password);
  7.         smtp.EnableSsl = true;
  8.         //smtp.UseDefaultCredentials = false;
  9.         MailMessage message = new MailMessage(this.SenderAddress, this.ReciverAddress, this.Subject, this.Body) { From = new MailAddress(this.SenderAddress, this.SenderName) };
  10.         ServicePointManager.ServerCertificateValidationCallback = delegate (object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
  11.         {
  12.             return true;
  13.         };
  14.         smtp.Send(message);
  15.         return true;
  16.     }
  17.     catch (Exception)
  18.     {
  19.         return false;
  20.     }
  21. }
复制代码
上述代码中,取消了UseDefaultCredentials属性的使用。运行后,邮件发送正常。那么问题来了,为什么使用了UseDefaultCredentials属性就会导致Credentials 凭证为空呢?看下.Net FrameWork框架System.Net.Mail源码:点击查看代码
  1. public bool UseDefaultCredentials
  2. {
  3.     get
  4.     {
  5.         if (!(transport.Credentials is SystemNetworkCredential))
  6.         {
  7.             return false;
  8.         }
  9.         return true;
  10.     }
  11.     set
  12.     {
  13.         if (InCall)
  14.         {
  15.             throw new InvalidOperationException(SR.GetString("SmtpInvalidOperationDuringSend"));
  16.         }
  17.         transport.Credentials = (value ? CredentialCache.DefaultNetworkCredentials : null);
  18.     }
  19. }
复制代码
再对比下.net6.0 框架System.Net.Mail源码:点击查看代码
  1. //
  2. // 摘要:
  3. //     Gets or sets a System.Boolean value that controls whether the System.Net.CredentialCache.DefaultCredentials
  4. //     are sent with requests.
  5. //
  6. // 返回结果:
  7. //     true if the default credentials are used; otherwise false. The default value
  8. //     is false.
  9. //
  10. // 异常:
  11. //   T:System.InvalidOperationException:
  12. //     You cannot change the value of this property when an email is being sent.
  13. public bool UseDefaultCredentials
  14. {
  15.      get;
  16.      set;
  17. }
复制代码
水落石出,微软误我啊!
来源:https://www.cnblogs.com/FlowerFly/Undeclared/17945512
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具