幾年前我做的一個項目,日發郵件最高峰時幾十萬。自以為對郵件發送方面已經有了一定認識,所以近期機緣巧合之下,又有項目需要發送郵件,不禁自信滿滿,暗自慶幸能不手到擒來乎?
不想老革命遇到新問題。我原先的郵件發送機制,是生成eml文件,然后扔到windows自帶的smtp服務器的pickup目錄下,系統即自動發送(見拙作:郵件發送一點心得)。
但今時今日,這些好像都是老皇歷了。IIS7默認並沒有SMTP,如果操作系統是server,還可以通過添加功能加上去,但WIN7就不行了。偏偏,我們的系統就部署在WIN7下。
我第一個應對之道是看WIN7能不能裝那個自帶的SMTP,結果是不行,死活沒找到。
第二個辦法是裝個第三方的SMTP,找來找去,找到一個叫做什么FREE SMTP的,裝上去以后,打開看,好像忒簡單了點。根本沒有啥PICK目錄的,應該是只能通過代碼,搞什么幾次握手之類的方法來進行調用。我很煩這個東西。
最后,決定還是直接使用smtp.163.com。網上例子比比皆是。
public interface IEmail
{
bool Send(EmailParam param);
string Mess { get; }
}
public class EmailParam
{
public string From { get; set; }
public string To { get; set; }//接收人;多個郵箱用分號隔開
public string CC { get; set; }//抄送;多個郵箱用分號隔開
public string Subject { get; set; }//標題
public string Body { get; set; }//郵件正文
}
public class Sender : IEmail
{
SmtpClient client;
public Sender()
{
// <add key="eml_host" value="smtp.163.com"/>
// <add key="eml_account" value="chendaqu"/>
// <add key="eml_pwd" value="1234abcd"/>
string host = ConfigurationManager.AppSettings["eml_host"];
string account = ConfigurationManager.AppSettings["eml_account"];
string pwd = ConfigurationManager.AppSettings["eml_pwd"];
client = new SmtpClient();
client.Host = host;
client.UseDefaultCredentials = false;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Credentials = new System.Net.NetworkCredential(account,pwd);
client.Port = 25;
}
public string Mess { get; set; }
public bool Send(EmailParam param)
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress(param.From);
getCollection(mail.To,param.To);
getCollection(mail.CC, param.CC);
mail.Subject = param.Subject;
mail.Body = param.Body;
mail.SubjectEncoding = Encoding.UTF8;
mail.BodyEncoding = Encoding.UTF8;
mail.Priority = MailPriority.Normal;
mail.IsBodyHtml = true;
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
try
{
client.Send(mail);
}
catch(Exception ex)
{
Mess = ex.Message;
return false;
}
return true;
}
MailAddressCollection getCollection(MailAddressCollection collection,string arstring)
{
if (!String.IsNullOrEmpty(arstring))
{
string[] ar = arstring.Split(';');
foreach (string item in ar)
{
if (String.IsNullOrEmpty(item)) continue;
collection.Add(item);
}
}
return collection;
}
}
使用單元測試進行調用:
[TestMethod()]
public void SendTest()
{
IEmail sender = new Sender();
bool ok = sender.Send(new EmailParam()
{
Subject = "郵件測試7",
Body = "Hello World!",
From = "chendaqu@163.com",
To = "178879771@qq.com;461198190@qq.com",
});
Assert.AreEqual(true, ok);
}
結果剛開始非常順利,都能收到郵件;但該單元測試運行了幾次以后,就發送失敗了。提示:
錯誤:郵件:事務失敗。 服務器響應為:DT:SPM 163 smtp11,D8CowACXNqusR1pYQe3vGA--.16469S2 1482311598,please see http://mail.163.com/help/help_spam_16.htm?ip=219.136.75.223&hostid=smtp11&time=1482311598
開始時以為是因為163郵箱的反垃圾郵件機制,猛查資料,結果一無所獲。焦慮攻心之下,我第二天居然感冒了。后來才知道是QQ郵箱的發垃圾郵件機制所致。同一個發送請求中,有一個地址失敗,其他的都失敗了,所以稱為“事務”?
后來就是莫名其妙地好了,可能是郵件內容有所變化,QQ又認為它不是垃圾了。靠。
注:
我這個163郵箱,開啟了客戶端授權,未清楚對應對反垃圾機制是否有用,好像不開啟這個客戶端授權也能發送。開啟了這個客戶端授權后,代碼中的密碼要使用這個客戶端授權密碼,而不是登錄郵箱的密碼。
==================================
以上就是垃圾。這個問題等於沒解決。163的SMTP一言不合就將你的郵件當成垃圾郵件,直到第二天才解封。但是很奇怪,采用foxmail作為客戶端來發送同樣的郵件,卻沒有問題,說到底還是代碼的問題?(outlook沒試過,估計也不會有問題)