当GoDaddy碰到SmtpPermission
前两天一个朋友说,她一个网站上有7个比较大的表单,每次浏览者提交表单到后台,她不能第一时间知道。每天快下班的时候,她到后台看下有无新的留言或者报名参加他们培训的信息(中文培训行业),但总是有时间差。
这好办啊,表单提交的时候,同样的信息再Email一份到你msn账号里,不就行了,MSN会第一时间提醒你的,我测试的一般是7秒不到就收到了邮件提醒。于是今天就哗哗啦啦写下如下代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using System.Web.Security;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.ComponentModel;
using System.IO;
/// summary
/// Summary description for Email
/// summary
public class Email
{
public string Subject { get; set; }
public string Body { get; set; }
public string Receiver { get; set; }
private Email()
{
}
public Email(string Subject,NameValueCollection NVC,string Receiver)
{
this.Subject = Subject;
this.Body = this.BuildMailBody(NVC);
this.Receiver = Receiver;
}
private string BuildMailBody(NameValueCollection NVC)
{
//构造邮件内容
StringBuilder sb = new StringBuilder("table border=\"1\" bordercolor=\"#464646\" cellpadding=\"7\" cellspacing=\"0\" style=\"color:#644445;\"");
for (int i = 0; i NVC.Count; i++)
{
if (i % 2 != 0)
{
sb.AppendFormat("<tr><td>{0}</td><td>{1}</td></tr>", NVC.GetKey(i), NVC.Get(i));
}
else
{
sb.AppendFormat("<tr style=\"background:#cecece\"><td>{0}</td><td>{1}</td></tr>", NVC.GetKey(i), NVC.Get(i));
}
}
sb.AppendLine("table");
return sb.ToString();
}
/// summary
/// 随便弄个gmail做中转邮箱
/// summary
/// param name="NVC"param
public void Send()
{
SmtpClient smtp = new SmtpClient("smtp.gmail.com");
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential("sender{replace your own here}@gmail.com", your password");
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
//smtp.Port = 25;
smtp.EnableSsl = true;
MailMessage mail = new MailMessage("sender{replace your own here}@gmail.com", Receiver, Subject, Body);
mail.BodyEncoding = Encoding.UTF8;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;//附件就不写了
try
{
smtp.Send(mail);
}
catch
{
StringBuilder sb = new StringBuilder();
sb.Append("Send Failed! ");
sb.Append("Subject :" +Subject + " ");
sb.Append("Content :" + Body);
sb.Append("Exception :" + e.ToString());
Log.WriteLog(HttpContext.Current.Server.MapPath("~/log"), sb.ToString());
}
}
}
然后在aspx、ashx、asmx..里调用就好了,本想大功告成了,可是每次发送都不报错,也不发送邮件。幸亏前面有Log.LogWrite记录了错误信息,去翻翻日志发现不能连接到通过25端口连接不到smtp主机,呃,在我服务器上就行啊。于是telnet下google,没问题;再telnet godaddy咯,godaddy的问题。SmtpClient的Port改成465嘛,改了以后问题又来了:
Request for the permission of type 'System.Net.Mail.SmtpPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
这些错误信息只有传到godaddy主机上之后再会有,真让人抓狂不是吗?
那就google解决方法呗,很快我找到了很多关于解决方法的帖子,挑两个放在这里:
http://forums.asp.net/t/1193027.aspx Correct Settings for using SMTP on GoDaddy?
主要是利用 relay-hosting.secureserver.net
这个对于我不行
1、因为中转邮箱我用的gmail,因为速度比较快
2、我试了朋友的godaddy的邮箱,用这个方法还是不行,于是就没有深究
这个在mechine级别修改trust level,或者修改PermissionSet
这个更不行了,godaddy主机不是我的,联系他们support,居然没回复我,答应朋友今天弄好的.......
GoDaddy的主机不是我的,但还好我有自己的主机,那就干脆把发邮件的功能转移到我的主机上吧,然后再在GoDaddy上把Request到的Form POST到我的主机上就行了。
思路就是这样了,技术细节可以用Web Service、Restful,那这么麻烦...我的主机上就一个MCmail.ashx文件就解决了嘛:
<%@ WebHandler Language="C#" Class="MCMail" %>
using System;
using System.Web;
using System.Web.Security;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
public class MCMail : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
if (String.IsNullOrEmpty(context.Request.QueryString["subject"]))
{
context.Response.Write(0);
context.Response.End();
}
Email E = new Email(context.Request.QueryString["subject"], context.Request.Form, "我朋友的msn邮箱");
E.Send();
context.Response.Write("1");
}
public bool IsReusable {
get {
return false;
}
}
internal class Email
{
private string Subject;
private string Body;
private string Receiver;
public Email()
{
}
public Email(string Subject,NameValueCollection NVC, string Receiver)
{
this.Subject = Subject;
this.Body = this.BuildMailBody(NVC);
this.Receiver = Receiver;
}
private string BuildMailBody(NameValueCollection NVC)
{
//构造邮件内容
StringBuilder sb = new StringBuilder("<table border=\"1\" bordercolor=\"#464646\" cellpadding=\"7\" cellspacing=\"0\" style=\"color:#644445;\">");
for (int i = 0; i < NVC.Count; i++)
{
if (i % 2 != 0)
{
sb.AppendFormat("<tr><td>{0}</td><td>{1}</td>", NVC.GetKey(i), NVC.Get(i));
}
else
{
sb.AppendFormat("<tr style=\"background:#cecece\"><td>{0}</td><td>{1}</td>", NVC.GetKey(i), NVC.Get(i));
}
}
sb.AppendLine("</table>");
return sb.ToString();
}
/// <summary>
/// 异步发送
/// </summary>
/// <param name="NVC"></param>
public void Send()
{
SmtpClient smtp = new SmtpClient("smtp.gmail.com");
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential("sender{repalce your own}@gmail.com", "#124ice6");
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
//smtp.Port = 465;
smtp.EnableSsl = true;
MailMessage mail = new MailMessage("MCrelaystation@gmail.com", Receiver, Subject, Body);//info@masterchina.com
mail.BodyEncoding = Encoding.UTF8;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;//下面可以发送附件
smtp.Send(mail);
}
}
}
然后修改下Email类,也就是放在GoDaddy上的代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using System.Web.Security;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.ComponentModel;
using System.IO;
/// <summary>
/// Summary description for Email
/// </summary>
public class Email
{
public string Subject { get; set; }
public string Body { get; set; }
public string Receiver { get; set; }
/// <summary>
/// 传入的querystring
/// </summary>
public string Params { get; set; }
private Email()
{
}
public Email(string Subject,NameValueCollection NVC,string Receiver)
{
this.Subject = Subject;
this.Body = this.BuildMailBody(NVC);
this.Receiver = Receiver;
this.Params = this.BuildParams(NVC);
}
private string BuildMailBody(NameValueCollection NVC)
{
//构造邮件内容
StringBuilder sb = new StringBuilder("<table border=\"1\" bordercolor=\"#464646\" cellpadding=\"7\" cellspacing=\"0\" style=\"color:#644445;\">");
for (int i = 0; i < NVC.Count; i++)
{
if (i % 2 != 0)
{
sb.AppendFormat("<tr><td>{0}</td><td>{1}</td>", NVC.GetKey(i), NVC.Get(i));
}
else
{
sb.AppendFormat("<tr style=\"background:#cecece\"><td>{0}</td><td>{1}</td>", NVC.GetKey(i), NVC.Get(i));
}
}
sb.AppendLine("</table>");
return sb.ToString();
}
private string BuildParams(NameValueCollection NVC)
{
StringBuilder sb = new StringBuilder();
foreach (string key in NVC.AllKeys)
{
sb.Append(key);
sb.Append("=");
sb.Append(NVC[key]);
sb.Append("&");
}
return sb.ToString().Trim('&');
}
/// <summary>
/// 先用gmail发送,不行的话启用代理
/// </summary>
/// <param name="NVC"></param>
public void Send()
{
SmtpClient smtp = new SmtpClient("smtp.gmail.com");
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential("sender{repalce your own}@@gmail.com", "{your password}");
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
//smtp.Port = 25;
smtp.EnableSsl = true;
MailMessage mail = new MailMessage("sender{repalce your own}@gmail.com", Receiver, Subject, Body);//info@masterchina.com
mail.BodyEncoding = Encoding.UTF8;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;//下面可以发送附件
try
{
smtp.Send(mail);
}
catch
{
SendByProxyService();
StringBuilder sb = new StringBuilder();
sb.Append("Send Failed! Alter to proxy");
sb.Append("Subject :" + mail.Subject + " ");
sb.Append("Content :" + mail.Body);
//sb.Append("Exception :" + e.ToString());
Log.WriteLog(HttpContext.Current.Server.MapPath("~/log"), sb.ToString());
}
}
public void SendByProxyService()
{
WebRequest req = WebRequest.Create("http://我的主机上的一个网站/mail.ashx?subject=" + Subject + " - " + DateTime.Now.ToString("yyyy-MM-dd"));
req.Method = "POST";
byte[] postData = Encoding.UTF8.GetBytes(Params);
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = postData.Length;
//1、把postData写入到request请求体中
Stream dataStream = req.GetRequestStream();
dataStream.Write(postData, 0, postData.Length);//写入
dataStream.Close();//关闭写入流
//获取请求的服务器返回对象
WebResponse res = req.GetResponse();
dataStream = res.GetResponseStream();
//读取响应流
StreamReader sr = new StreamReader(dataStream);
string resFromServer = sr.ReadToEnd();
sr.Close();
dataStream.Close();
res.Close();
}
}
//smtp.SendCompleted += new SendCompletedEventHandler(smtp_SendCompleted);
//object userState = mail;
//smtp.SendAsync(mail, userState);
//public void smtp_SendCompleted(object sender, AsyncCompletedEventArgs e)
//{
// bool mailSent = true;
// MailMessage mail = (MailMessage)e.UserState;
// string subject = mail.Subject;
// string content = mail.Body;
// if (e.Cancelled)
// {
// mailSent = false;
// }
// if (e.Error != null)
// {
// mailSent = false;
// }
// if (!mailSent)//如果发送失败 可能是godday SmtpPermission有问题,这里直接调用远端服务
// {
// this.SendByProxyService(mail);
// StringBuilder sb = new StringBuilder();
// sb.Append("Send Failed! Alter to proxy");
// sb.Append("Subject :" + subject + " ");
// sb.Append("Content :" + content);
// sb.Append("Exception :" + e.Error.ToString());
// Log.WriteLog(HttpContext.Current.Server.MapPath("~/log"), sb.ToString());
// }
// else
// {
// StringBuilder sb = new StringBuilder();
// sb.Append("Send Success! ");
// sb.Append("Subject :" + subject + " ");
// sb.Append("Content :" + content);
// Log.WriteLog(HttpContext.Current.Server.MapPath("~/log"), sb.ToString());
// }
//}
好了,上面就是我的方案,如果这个方案有人需要而上面的代码不能很好解决你的问题,欢迎你联系我 :)
另外这个是一个很简单的解决方案,如果邮件量很大,那就用MSMQ(消息队列),然后再做个Email异步发送(上面被我注释掉的一大段代码)做个服务,当然在我目前的工作里还碰不到,好想做大型网站哦:(
当然这个方案有严重的安全问题,不过如果上wcf稍显麻烦,貌似可以借用SSO(single sign on)的思路,解决安全问题。如果有朋友知道好的安全解决方案,希望可以留言交流,感激不尽。
安全方面想了下:直接用GUID,双方用一个GUID,然后在GoDaddy发送的时候附带上,我的主机上再验证下,这样安全性就会高一些。
浙公网安备 33010602011771号