前一阵子做项目的时候遇到一个功能需求:当程序异常或者重大事件时候,发送邮件通知管理员。按理说这是一个很简单的需求,但是在开发当中遇到了一个问题:因为客户那里的网络拓扑是一个需要设置代理才可以访问外网smtp服务器的网络环境,所以程序在直连外网时候好使,拿到内网就不能用了。于是我在网上找了很多关于使用C#程序发邮件的例子,但很少有关于使用代理方式,特别是支持审核代理方式发送的案例,我分别使用了SMTPClient对象,CDO对象来进行开发,发现.net framework提供的smtpclient对象不支持代理方式发送,cdo里面有些关于代理的设置,但是没有关于访问代理时候的用户名、密码、端口设置的地方,于是问题被搁置下来。后来也请求过微软方面的支持,也没有给出什么好的方案【想让我用webservice,因为那个支持代理的审核,但是既然我能在内网使用foxmail,outlook通过设置代理属性后正常的收发邮件,那为什么还要使用什么webservice呢?看来微软的这些所谓的专家也有很菜的方面】。既然高级的方式使用不了,于是考虑回到原点——使用socket方式发送邮件。废话少说吧,先把代码贴出来大家分享:
1.先声明一个TCPClient对象,用于Socket发送
- private TcpClient sendTcp = null;
2.写几个方法用于与SMTP服务器的交互
- private void MailSocketAlternation(string[] mailto,string subject, string msg, string attachpath)
- {
- bool check = false;
- NetworkStream stream = sendTcp.GetStream();
- #region 发送Hello握手
- string hostName = Dns.GetHostName();
- check = SendCommand(ref stream, "EHLO " + hostName, "EHLO", "250");
- int round = 0;
- //失败重试
- while (!check && round < 5)
- {
- round++;
- check = SendCommand(ref stream, "EHLO " + hostName, "EHLO", "250");
- }
- #endregion
- #region 请求审核登录
- check = SendCommand(ref stream, "AUTH LOGIN ", "AUTH LOGIN", "334");
- round = 0;
- while (!check && round < 5)
- {
- round++;
- check = SendCommand(ref stream, "AUTH LOGIN ", "AUTH LOGIN", "334");
- }
- #endregion
- #region 身份验证
- check = SendCommand(ref stream, Convert.ToBase64String(Encoding.Default.GetBytes(clsParam.Param.SendMailAccount)), "用户名", "334");
- round = 0;
- while (!check && round < 5)
- {
- round++;
- check = SendCommand(ref stream, Convert.ToBase64String(Encoding.Default.GetBytes(clsParam.Param.SendMailAccount)), "用户名", "334");
- }
- if (!check)
- {
- throw new Exception("邮件帐户身份验证失败!");
- }
- check = SendCommand(ref stream, Convert.ToBase64String(Encoding.Default.GetBytes(clsParam.Param.SendMailPWD)), "密码", "235");
- round = 0;
- while (!check && round < 5)
- {
- round++;
- check = SendCommand(ref stream, "EHLO " + hostName, "EHLO", "250");
- int round0 = 0;
- while (!check && round0 < 5)
- {
- round0++;
- check = SendCommand(ref stream, "EHLO " + hostName, "EHLO", "250");
- }
- check = SendCommand(ref stream, "AUTH LOGIN ", "AUTH LOGIN", "334");
- check = SendCommand(ref stream, Convert.ToBase64String(Encoding.Default.GetBytes(clsParam.Param.SendMailAccount)), "用户名", "334");
- check = SendCommand(ref stream, Convert.ToBase64String(Encoding.Default.GetBytes(clsParam.Param.SendMailPWD)), "密码", "235");
- }
- if (!check)
- {
- throw new Exception("邮件帐户身份验证失败!");
- }
- #endregion
- #region 发件人
- check = SendCommand(ref stream, "MAIL FROM:<" + clsParam.Param.SendMailAccount + ">", "MAIL FROM", "250");
- round = 0;
- while (!check && round < 5)
- {
- round++;
- check = SendCommand(ref stream, "MAIL FROM:<" + clsParam.Param.SendMailAccount + ">", "MAIL FROM", "250");
- }
- #endregion