当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的邮箱,用这个方法还是不行,于是就没有深究

http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/470ee417-082b-4298-8402-62227a0f2057

这个在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发送的时候附带上,我的主机上再验证下,这样安全性就会高一些。

posted on 2010-08-12 20:42  ice6  阅读(1640)  评论(2)    收藏  举报

导航