【C#】C#對電子郵件的收發操作
目錄結構:
contents structure [+]1.簡介
郵件傳輸常用的協議有,SMTP、POP3、IMAP4。他們都屬於TCP/IP協議,預設狀態下分別通過TCP埠25,110,和143建立連結。
SMTP協議
SMTP的全稱是“Simple Mail Transfer Protocol”,即簡單郵件傳輸協議。它是一組用於從源地址到目的地址傳輸郵件的規範,通過它來控制郵件的中轉方式。SMTP 協議屬於TCP/IP協議簇,它幫助每臺計算機在傳送或中轉信件時找到下一個目的地。SMTP 伺服器就是遵循SMTP協議的傳送郵件伺服器。SMTP認證,簡單地說就是要求必須在提供了賬戶名和密碼之後才可以登入 SMTP 伺服器,這就使得那些垃圾郵件的散播者無可乘之機。增加 SMTP 認證的目的是為了使使用者避免受到垃圾郵件的侵擾。
POP協議
POP郵局協議負責從郵件伺服器中檢索電子郵件。它要求郵件伺服器完成下面幾種任務之一:從郵件伺服器中檢索郵件並從伺服器中刪除這個郵件;從郵件伺服器中檢索郵件但不刪除它;不檢索郵件,只是詢問是否有新郵件到達。POP協議支援多使用者網際網路郵件擴充套件,後者允許使用者在電子郵件上附帶二進位制檔案,如文書處理檔案和電子表格檔案等,實際上這樣就可以傳輸任何格式的檔案了,包括圖片和聲音檔案等。在使用者閱讀郵件時,POP命令所有的郵件資訊立即下載到使用者的計算機上,不在伺服器上保留。
IMAP協議
網際網路資訊訪問協議(IMAP)是一種優於POP的新協議。和POP一樣,IMAP也能下載郵件、從伺服器中刪除郵件或詢問是否有新郵件,但IMAP克服了POP的一些缺點。例如,它可以決定客戶機請求郵件伺服器提交所收到郵件的方式,請求郵件伺服器只下載所選中的郵件而不是全部郵件。客戶機可先閱讀郵件資訊的標題和傳送者的名字再決定是否下載這個郵件。通過使用者的客戶機電子郵件程式,IMAP可讓使用者在伺服器上建立並管理郵件資料夾或郵箱、刪除郵件、查詢某封信的一部分或全部內容,完成所有這些工作時都不需要把郵件從伺服器下載到使用者的個人計算機上。
簡單來說,SMTP協議主要是用於發郵件,POP和IMAP協議用於讀取、刪除、下載郵件。結合QQ郵箱和網易郵箱,筆者認為,QQ郵箱更注重POP協議方面,網易郵箱比較注重SMTP協議方面,下面筆者將會對其原由進行闡述,希望對讀者有所幫助。
在利用第三方對QQ郵箱和網易郵箱進行郵件操作之前,需要在各自的後臺開啟POP/SMTP服務,並且獲取到授權碼(網易郵箱若關閉客戶端授權碼,則可以直接用登入密碼)。
2.傳送郵件
傳送郵件應該使用SMTP協議。有關SMTP協議的具體內容,這裡筆者就不再闡述了。
C#對傳送郵件的庫封裝得已經比較好了,開發人員可以很方便的完成傳送郵件的操作。在System.Net.Mail名稱空間中封裝了對傳送郵件的操作,下面是使用QQ郵箱傳送的案例:
MailMessage message = new MailMessage(); //設定發件人,發件人需要與設定的郵件傳送伺服器的郵箱一致 MailAddress fromAddr = new MailAddress("[email protected]"); message.From = fromAddr; //設定收件人,可新增多個,新增方法與下面的一樣 message.To.Add("[email protected]"); //設定抄送人 message.CC.Add("[email protected]"); //設定郵件標題 message.Subject = "通知"; //設定郵件內容 message.Body = "Hello world"; //設定郵件傳送伺服器,伺服器根據你使用的郵箱而不同,可以到相應的 郵箱管理後臺檢視 SmtpClient client = new SmtpClient("smtp.qq.com", 25); //設定傳送人的郵箱賬號和授權碼 client.Credentials = new NetworkCredential("[email protected]", "授權碼"); //啟用ssl,也就是安全傳送 client.EnableSsl = true; //傳送郵件 client.Send(message); Console.WriteLine("傳送成功"); Console.ReadLine();
上面傳送的是文字格式,接下來介紹如何傳送HTML格式的檔案。如何想要傳送HTML格式的郵件,那麼只需要指定IsBodyHtml為true即可。
message.Body="<h1>Hello World</h1>"; message.IsBodyHtml=true;
如果想要傳送附件的話,那麼應該往Message例項中的Attachments 屬性中新增一個Attachment(附件)例項。
關於QQ郵件的傳送就討論到這裡,接下來討論一下網易郵件的傳送。網易郵件的傳送較為麻煩,這和網易郵箱的反垃圾郵件機制有關。網易為了希望使用者能夠得到純淨的電子郵件網路環境,減少垃圾郵件,系統對會對傳送的信件做判定,並限制對垃圾的郵件的傳送。
下面是網易傳送郵件的程式碼,筆者測試能夠成功傳送郵件:
MailMessage message = new MailMessage(); //設定發件人,發件人需要與設定的郵件傳送伺服器的郵箱一致 MailAddress fromAddr = new MailAddress("[email protected]"); message.From = fromAddr; message.To.Add("[email protected]");//自己接收 //設定郵件標題 message.Subject = "通知"; //設定郵件內容 message.Body = "Hello world"; //設定郵件傳送伺服器,伺服器根據你使用的郵箱而不同,可以到相應的 郵箱管理後臺檢視 SmtpClient client = new SmtpClient("smtp.163.com", 25); //設定傳送人的郵箱賬號和授權碼 client.Credentials = new NetworkCredential("[email protected]", "授權碼"); //傳送郵件 client.Send(message); Console.WriteLine("傳送成功"); Console.ReadLine();
筆者只在自己給自己發郵件中測試成功過,在給別的郵箱中發郵件時總是被判定為垃圾郵件。如果讀者測試時並不能夠成功傳送郵件,可按照如下幾部步驟檢查:1.檢查客戶端授權碼是否開啟,授權碼是否停用2.檢查是否開啟POP3/SMTP服務3.將發件人新增到白名單中4.取消智慧收信分類5.不要設定抄送人從上面可以看出,在SMTP服務中網易郵箱比QQ郵箱的判斷要更加嚴格。
3.讀取郵件
讀取郵件要用到的協議為POP3協議。然而C#的類庫中,並沒有對POP3協議進行封裝。QQ郵箱在POP3協議的建立中,使用了SSL,這使得資料的傳輸更加的安全。然而網易郵箱並沒有使用SSL協議。
如果是電腦客戶端通過CMD命令與POP伺服器建立連結的話,網易郵箱的操作(telnet)沒什麼難度。但是QQ郵箱的操作(openssl)就相對比較複雜了,在使用openssl命令與主機建立連線時,必需傳入證書。C#對SSL已經有過包裝,通過C#可以輕鬆的與QQ郵箱和網易郵箱POP協議主機建立連線。在開始之前,讀者可能需要先了解一些POP3協議的知識,關於POP3文件讀者可以自行度娘。這裡筆者列舉出,POP3協議中的命令碼:
命令 | 描述 |
USER [username] | 使用者名稱 |
PASS [password] | 密碼 |
APOP [Name,Digest] | 認可Digest是MD5訊息摘要 |
STAT | 處理請求伺服器發回關於郵箱的統計資料,如郵件總數和總位元組數 |
UIDL [Msg#] | 處理返回郵件的唯一識別符號,POP3會話的每個識別符號都將是唯一的 |
LIST [Msg#] | 處理返回郵件數量和每個郵件的大小 |
RETR [Msg#] | 處理返回由引數標識的郵件的全部文字 |
DELE [Msg#] | 處理伺服器將由引數標識的郵件標記為刪除,由quit命令執行 |
RSET | 處理伺服器將重置所有標記為刪除的郵件,用於撤消DELE命令 |
TOP [Msg# n] | 處理伺服器將返回由引數標識的郵件前n行內容,n必須是正整數 |
NOOP | 處理伺服器返回一個肯定的響應 |
QUIT | 終止會話 |
接下來筆者連線QQ郵箱POP服務主機,展示一些常見的命令使用:
TcpClient clientSocket = new TcpClient(); clientSocket.Connect("pop.qq.com", 995);//連線到QQ郵箱POP伺服器 //建立SSL連線 SslStream stream = new SslStream( clientSocket.GetStream(), false, (object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) => { return true;//接收所有的遠端SSL連結 }); stream.AuthenticateAsClient("pop.qq.com");//驗證 //得到輸入流 StreamReader reader = new StreamReader(stream, Encoding.Default, true); //得到輸出流 StreamWriter writer = new StreamWriter(stream); Console.WriteLine(reader.ReadLine());//以+Ok開頭,表示連線成功 writer.WriteLine("USER [email protected]"); writer.Flush(); Console.WriteLine(reader.ReadLine());//+Ok 表示使用者名稱正確 writer.WriteLine("PASS 授權碼"); writer.Flush(); Console.WriteLine(reader.ReadLine());//+Ok 表示密碼正確 writer.WriteLine("STAT"); writer.Flush(); Console.WriteLine(reader.ReadLine());//獲得郵件數 +OK 189 1058197 表示 189封郵件,1058197b writer.WriteLine("RETR 1"); writer.Flush(); String result = null;//獲得第1封郵件的內容 while ((result = reader.ReadLine()) != null) { Console.WriteLine(reader.ReadLine()); } Console.ReadLine();
讀者也可以測試連線網易郵箱POP伺服器,1.網易郵箱POP伺服器的遠端地址是:pop.163.com:995。2.無需建立SSL連結