需求:
最近項目里遇到了個問題,對方沒有提供直接獲取數據源的api接口,而是通過郵件發數據的。這就需要接收郵件后解析郵件內容獲得數據。
分析:
想在代碼里實時獲取郵件,可以通過郵件的幾個協議來實現,常用的幾個協議有POP3協議,SMTP協議,IAMP協議。
1. pop3:(Post Office Protocal 3),3是版本,是目前使用的主流版本。POP3是客戶-服務器協議,其中電子郵件的接收需要一個收件服務器,郵件下載到本地計算機上所有一次,從而使離線閱讀更輕松,可以指定是否保留副本的郵件在服務器上。
2. SMTP(Simple Mail Transfer Protocal):簡單Mail傳輸協議,是個請求/響應協議,它監聽25號端口,用於接收用戶的Mail請求,並與遠端Mail服務器建立SMTP連接。 獨立於特定的傳輸子系統,它可以是電子郵件從客戶機傳輸到服務器;也可以是從某一個服務器傳輸到另一個服務器;且只需要可靠有序的數據流信道支持。SMTP 重要特性之一是其能跨越網絡傳輸郵件,即SMTP 郵件中繼。通常,一個網絡可以由公用互聯網上 TCP 可相互訪問的主機、防火牆分隔的 TCP/IP 網絡上 TCP 可相互訪問的主機,及其它 LAN/WAN 中的主機利用非 TCP 傳輸層協議組成。使用 SMTP,可實現相同網絡上處理機之間的郵件傳輸,也可通過中繼器或網關實現某處理機與其它網絡之間的郵件傳輸。
3. IMAP ( Internet消息訪問協議)是一種標准協議,用於訪問電子郵件從您的本地服務器。的IMAP (最新版本的IMAP第4版)是一個客戶機/服務器協議在電子郵件收到並為您舉行的由您的因特網服務器。您(或您的電子郵件客戶端)可以查看剛才的標題和發件人的信件,然后決定是否下載該郵件。您還可以創建和操縱多個文件夾或郵箱的服務器上,刪除郵件,或尋找某些地區或整個說明。
imap協議可以實現獲取郵件狀態,並且操作服務器上的郵件,而POP3不能,
程序設計思路是:
1 從郵件服務器上獲取未讀郵件,
2 進行解析操作,
3 標記郵件為已讀。
4 將郵件數據推送到消息隊列中
5 部署多個消息隊列的消費者組件,對郵件內容進行二次處理,進行業務邏輯處理。
郵件接收的組件其實在前三步就已經結束了。 業務處理的服務可以部署多個,但是接收郵件的組件相當於一個客戶端,只作為郵件的接收和轉發數據,這里部署了一個,屬於單點的,鑒於服務暫時沒多少壓力,先只做了異常報警通知,沒有去部署多個。
實現:
.net下有現成的開源組件LumiSoft.Net.IMAP
開源組件下載地址 http://www.lumisoft.ee/lswww/download/downloads/
整理后的主要代碼 public void imapdemo()
{
var mailServer = "imap.exmail.qq.com";//也可以使用其他郵箱服務器
var username = "登錄賬號";
var password = "登錄密碼";
using (IMAP_Client client = new IMAP_Client())
{
client.Connect(mailServer, 993, true);
client.Login(username, password);
client.SelectFolder("INBOX");//打開收件箱
int[] unseen_ids = client.Search(false, Encoding.UTF8, new IMAP_Search_Key_Unseen());
if (unseen_ids.Count() == 0)
{
return;
}
IMAP_t_SeqSet sequence = IMAP_t_SeqSet.Parse(string.Join(",", unseen_ids));
var items = new IMAP_t_Fetch_i[] { new IMAP_t_Fetch_i_Envelope(), new IMAP_t_Fetch_i_Uid(), new IMAP_t_Fetch_i_Flags(), new IMAP_t_Fetch_i_Flags(), new IMAP_t_Fetch_i_InternalDate(), new IMAP_t_Fetch_i_Rfc822(), new IMAP_t_Fetch_i_BodyStructure() };
client.Fetch(false, sequence, items, (s, e) =>
{
try
{
var email = e.Value as IMAP_r_u_Fetch;
if (email.Rfc822 != null)
{
email.Rfc822.Stream.Position = 0;
var mine = Mail_Message.ParseFromStream(email.Rfc822.Stream);
email.Rfc822.Stream.Close();
var files = mine.Attachments;
var fileurls = new List>();
foreach (var item in files)
{
var name = item.ContentType.Param_Name;
using (MemoryStream stream = new MemoryStream(item.DataToByte()))
{
//附件可以上傳到阿里雲上或者其他地方
var key = "";// AliOss.Upload(stream);
fileurls.Add(new KeyValuePair(name, key));//文件名,地址
}
}
//處理自定義業務邏輯
var Title = email.Envelope.Subject;
var CreateTime = email.InternalDate.Date;
var BodyText = mine.BodyText;
var BodyHtmlText = mine.BodyHtmlText;
var File = string.Join(",", fileurls.Select(x => x.Value));
//處理完的郵件標記為已讀
var sequenceSet = new IMAP_SequenceSet();
sequenceSet.Parse(string.Join(",", email.SeqNo));
client.StoreMessageFlags(false, sequenceSet, IMAP_Flags_SetType.Add, IMAP_MessageFlags.Seen);
//-------郵件內容入消息隊列------------
}
}
catch (Exception ex)
{
throw ex;
}
});
}
}
復制代碼
(編輯:雷林鵬 來源:網絡)