轉:【專題十】實現簡單的郵件收發器

引言:html

在咱們的日常工做中,郵件的發送和接收應該是咱們常常要使用到的功能的。所以知道電子郵件的應用程序的原理也是很是有必要的,在這一個專題中將介紹電子郵件應用程序的原理、電子郵件應用程序中涉及的協議和實現一個簡答的電子郵件收發器程序。web

 

1、郵件應用程序基本知識編程

1.1 電子郵件原理及相關協議瀏覽器

  說到電子郵件的原理,其實和咱們現實生活中寄郵件和寄包裹是同樣的原理的。就讓咱們先回顧下現實生活中寄郵件的流程吧——首先,咱們先寫好信,信封上面寫好收信人的地址,寫信人的地址,而後把信放到寄信箱中,而後郵局的人會某個時候去這個信箱中的信取出來,而後郵局的人根據信封上寫的收信人地址進行轉發到當地的郵局,當地郵局而後把信寄到收信人的信箱中(寄包裹的話可能會電話聯繫,像咱們在淘寶,京東買的東西的,收貨人就是經過電話聯繫同樣),最後收信人會到本身的信箱中收取信件。上面大體是咱們平時生活中寄信的一個流程的。前面已經講過電子郵件的原理和這個差很少的,下面就介紹了本專題中電子郵件的原理,你們能夠和現實生活中的寄信過程進行對比下的,這樣能夠更加容易理解和掌握:服務器

  咱們經過電子郵件應用(例如 基於客戶端的Outlook電子郵件軟件 和一些基於Web的電子郵件系統——新浪郵箱、谷歌郵箱、QQ郵箱等都屬於電子郵件應用)將一封寫好的郵件(至關於現實生活中的信,固然郵件也要寫明收件人地址,郵件內容等信息的)經過電子郵件協議(SMTP,在後面的電子郵件相關協議中會介紹)發送到SMTP服務器(就是存儲郵件的地方,至關於生活中的郵局同樣),而後SMTP服務器根據收件人的地址經過SMTP協議轉發到相應SMTP接收服務器上,(SMTP服務器進行轉發至關於現實生活中郵局的人配送信的過程,配送到收件人當地的郵局,然而現實生活中郵局都是一家,因此能夠相互識別——意思就是發送到當地郵局,當地郵局會接收,而且幫助你發送到指定人的信箱中,在網上上就是經過SMTP協議來規定這樣的一個過程的,發送到別人的SMTP服務器上別人的服務器必需要認識發送來的郵件並接收)結束,接收端郵件服務器(POP3服務器)把郵件存放到接受者的電子信箱內(至關於當地郵局的人把信放到收信人的郵箱中),最後收件人能夠登陸本身的電子信箱,再與POP3服務器進行鏈接,從POP3服務器上下載發送來的郵件,這樣在收件人的電子信箱中就能夠看到發送來的電子郵件了(這就是現實生活中收信人從本身的信箱中取信的一個過程)。網絡

  注:括號中都是我的的理解,若是有什麼不對的地方還望你們指出來,我好及時更正。tcp

 上面已經把電子郵件的原理和現實生活中寄信的過程進行對比,相信你們能夠更加清楚電子郵件的原理和發送接收過程的,其實網絡上的不少應用均可以以現實生活的例子去理解,這樣的話我認爲能夠加深對知識的理解。下面就介紹下電子郵件中的相關協議的內容:ide

  網絡上的應用的核心就是協議,由於協議讓網絡上的客戶端相互認識發生來的數據,因此電子郵件應用也不例外,也有相關的電子郵件協議來完成發送電子郵件和接收電子郵件的過程,這些協議主要是:SMTP(簡單郵件傳輸協議,Simple Mail Transfer Protocol)、POP3(郵局協議,Post Office Protocol)和IMAP(網絡郵件訪問協議,Internet Message Access Protocol)。ui

  •  SMTP——SMTP 主要負責將郵件從一臺機器轉發至另外一臺機器(能夠對照上面電子郵件的過程來理解SMTP的做用)
  •  POP3——3表示POP協議的版本,主要負責將郵件從郵箱中(POP3服務器)傳輸到本地計算機。
  •  IMAP——如今經常使用的版本爲第四版本,即IMAP4,主要負責郵件的檢索和處理功能,客戶端不須要下載郵件到本地計算機,可直接從郵件客戶端軟件對服務器上的信件和文                      件目錄進行操做,它是POP3的替代協議的。

1.2 郵件系統的分類this

  郵件系統主要分爲兩類的——基於客戶端的郵件系統和基於Web瀏覽器的郵件系統。Office OutLook就是基於客戶端的郵件客戶端系統,而像咱們常用的QQ郵箱、新浪、網易郵箱等都是屬於基於Web瀏覽器的郵件系統,基於客戶端的郵件系統的收發過程,經過下面的圖片來描述(圖片從網上摘下的):

發送方經過郵件客戶端,將編輯好的郵件向郵件服務(SMTP服務器,在發送過程當中也叫發送端郵件服務器)發送,發送端郵件服務器根據收件人的地址來識別接收端郵件服務器(POP3服務器),而後向POP3服務器發送郵件信息,接收端郵件服務器將郵件存放在接收者的電子信箱中,並告知接收者有新郵件,接收者經過郵件客戶端與POP3服務器鏈接後,就能夠查看新郵件。

  然而,基於Web瀏覽器的郵件系統與基於客戶端的郵件系統不一樣的地方有:

  • 基於Web瀏覽器郵件系統用戶代理(代理的概念也就是用戶不是直接與服務器進行通訊,而是經過代理的方式,讓代理去與服務器通訊,而後用戶在從代理中獲的服務器的信息,代理也就是中間人的做用,至關於生活中中介,在.net中不少技術都用到了代理,例如委託的概念其實也就是代理的一個概念的)是Web瀏覽器,基於客戶端的郵件系統而是郵件客戶端應用程序,通常是Windows Form程序。
  • 瀏覽器發送郵件到SMTP服務器和從POP3服務器中得到郵件的方式都是經過HTTP協議來實現,與基於客戶端的郵件系統不一樣(基於客戶端的郵件系統發送經過SMTP協議或ESMTP(Extended SMTP),得到經過POP3或IMAP協議)。

1.3 目前主要的電子郵件服務系統

  電子郵件服務系統——就是向你們提供郵箱服務的服務系統,這樣的系統固然是由專門的公司進行研發的,咱們通常叫這樣的公司爲郵件服務商,咱們日常使用的網易郵箱,新、Gmail郵箱等都是創建在電子郵件服務系統(這裏個人理解是——咱們使用的新浪,網易等郵箱至關於現實生活中每一個人的信箱,經過信箱能夠得到郵局來的信,一樣道理經過郵箱能夠得到郵件服務系統的郵件,這樣電子郵件系統至關於郵局) 。如今主要電子郵件服務系統主要有下面幾種:

  • 基於Postfix/Qmail的郵件系統。例如,雅虎郵箱基於Qmail系統
  • 微軟Exchange 郵件系統
  • IBM Lotus Domino郵件系統
  • Scalix郵件系統
  • Zimbra郵件系統
  • MDeamon郵件系統

 

2、.Net 平臺對郵件發送功能的支持

   在.NET類庫中,在System.Net.Mail命名空間下定義了對郵件處理的類,這樣使郵件的發送更加方便(這些類也就是對SMTP協議的封裝,使咱們更好地區編程,只須要使用類中的方法和屬性等去完成郵件的發送,避免寫複雜的SMTP協議的命令),下面是一張在System.Net.Mail命名空間下對郵件發送的支持的類截圖:

  從圖片中類的名字中也能夠看出每一個類的做用的,在這裏我就不一個介紹的, 你們能夠參考MSDN去看每一個類的使用,而且我在後面程序的實現部分也會有詳細的註釋去介紹程序中使用到類的使用。從圖中還能夠i看出一點——就是隻有SMTP的字樣,卻沒有POP3這樣的字樣的,這說明.Net類庫自己中並無提供對POP3協議的封裝類,可是咱們可使用Jmail組件來完成從POP3服務器中收取郵件的功能,具體的使用將在後面的郵件收發器程序中郵件的接收部分介紹的。

 

3、郵件收發器程序的實現

 3.1 郵件發送功能的實現

  3.1.1 SMTP協議

  SMTP 協議是用於電子郵件的傳輸的協議,電子郵件是經過SMTP服務器進行發送的,SMTP服務器的默認端口爲25,一般發送郵件有兩種方式——一種是不使用客戶端認證,即客戶端可使用匿名發送郵件(這種方式叫作SMTP);另外一種是客戶端必須提供用戶名和密碼認證(這種方式叫作ESMTP,Extended SMTP)目前大部分郵件服務器採用用戶名和密碼認證的方式。

  客戶端發送郵件過程爲——先經過客戶端軟件(本程序中的郵件收發器)將郵件發送到SMTP服務器,而後再由SMTP服務器發送到目標SMTP服務器。下面介紹SMTP協議的內容:

  SMTP協議總共定義了14個命令,命令由命令碼和睦候的參數域組成, 不區別大小寫的(經過前面專題的講述能夠得出各個協議的命令組成都差很少的),下面就簡單介紹下5個經常使用的命令碼

名稱  

解釋

HELO或EHLO

發送鏈接到服務器的命令,EHLO主要用於與ESMTP服務器創建鏈接時發送的命令

MAIL FROM

指定發件人的郵件地址

Rcpt to

指定收件人的郵件地址

Data

指定郵件正文內容,郵件內容以單獨一行   」.」 表示接觸

Quit

關閉與服務器的鏈接,而後退出

  電子郵件由信封、首部、正文和結束符號4部分組成,下面就具體介紹下這4個部分的內容:

  1. 信封

  信封包括髮信人的郵件地址和接收人的郵件地址,具體對應兩條SMTP命令——Mail from: mytest1989@sina.cn(發信人的地址)和Rcpt to:  794170314@qq.com

  2. 首部

  首部中經常使用的命令有:

  •   Subject:<郵件主題>——表示郵件的主題
  •   Date:<時間>——表示發郵件的時間
  •   reply-to:<郵件地址>——表示郵件的回覆地址
  •   Content-Type:<郵件類型>——表示郵件包含文本、HTML超文本和附件的類型。
  •       X-Priority:<郵件優先級>——表示郵件發送的優先級,優先級爲3表示爲普通郵件;如 X-Priority:3

  3. 正文

  正文固然指的就是郵件的內容了, 用Data命令指定,首部以一個空行結束,下面就是正文部分

  4. 結束符號

  郵件以「."結束,

  接收方收到SMTP命令以後,會給出一個響應碼,每一個命令都只有一個響應碼,SMTP響應碼也是由3位數字組成,後面附加一些文本信息,響應信息的格式爲:

     響應碼<空格>文本信息<回車換行>

  客戶端發出一條命令後,服務器端返回一個響應,發送者在發送下一條命令前必須等待服務器的響應,成功接收到響應碼後才繼續發送命令。

    附:SMTP經常使用的響應碼:

響應碼

解釋

響應碼

解釋

211

系統狀態或系統幫助響應

421

服務未就緒,關閉了傳輸通道

214

幫助信息

501

參數格式錯誤

220

服務就緒

502

命令不可實現

221

服務關閉傳輸通道

535

用戶驗證失敗

235

用戶驗證成功

553

郵箱名不可用,要求的操做未執行

334

等待用戶輸入驗證

554

操做失敗

354

開始郵件輸入

 

 

 

3.1.2 郵件的發送過程

  第一步:客戶端與服務器創建鏈接(該步中客戶端首先發送EHLO local 鏈接命令,服務器若是返回「220」響應碼錶示服務器準備就緒了,客戶端再繼續發送「Auto login」命令,請求登陸,服務器收到命令後返回「334」響應碼,表示要輸入用戶名,以後客戶端發送用戶名命令,等到響應後再發送密碼命令,具體在程序的實現中也會有註釋。)

  第二步:客戶端發送郵件的信封

  第三步:開始發送郵件數據,(包括郵件首部,正文和結束符號,注:結束符號要單獨佔一行,表示郵件發送結束)

  第四步: 客戶端與服務器斷開鏈接。

 

3.1.3 發送功能的實現代碼

相信有了上面的理論解釋郵件發送的過程後,實現郵件發送的功能並不難的,而且.net類庫中SMTPClient類幫咱們封裝了SMTP協議,使得咱們實現郵件發送功能就不要記住那些具體的命令了, 只須要使用該類中提供的方法來完成郵件的發送(固然你也能夠經過發送命令的方式實現,SMTPClient類的方法也是幫咱們完成發送命令功能而已的),下面是郵件發送功能的核心代碼:

       #region 郵件發送功能代碼
        // 添加附件
        private void btnAddFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.CheckFileExists = true;
            // 只接受有效的文件名
            openFileDialog.ValidateNames = true;
            // 容許一次選擇多個文件做爲附件
            openFileDialog.Multiselect = true;
            openFileDialog.Filter = "全部文件(*.*)|*.*";
            if (openFileDialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            if (openFileDialog.FileNames.Length > 0)
            {
                // 由於這裏容許選擇多個文件,因此這裏用AddRange而沒有用Add方法
                cmbAttachment.Items.AddRange(openFileDialog.FileNames);
            }
        }

        // 刪除附件
        private void btnDeleteFile_Click(object sender, EventArgs e)
        {
            int index = cmbAttachment.SelectedIndex;
            if (index == -1)
            {
                MessageBox.Show("請選擇要刪除的附件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            else
            {
                cmbAttachment.Items.RemoveAt(index);
            }
        }

        // 發送郵件
        private void btnSend_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            // 實例化一個發送的郵件
            // 至關於與現實生活中先寫信,程序中把信(郵件)抽象爲郵件類了
            MailMessage mailMessage = new MailMessage();
            // 指明郵件發送的地址,主題,內容等信息
            // 發信人的地址爲登陸收發器的地址,這個收發器至關於咱們平時Web版的郵箱或者是OutLook中配置的郵箱
            mailMessage.From = new MailAddress(tbxUserMail.Text);
            mailMessage.To.Add(txbSendTo.Text);
            mailMessage.Subject = txbSubject.Text;
            mailMessage.SubjectEncoding = Encoding.Default;
            mailMessage.Body = richtbxBody.Text;
            mailMessage.BodyEncoding = Encoding.Default;
            // 設置郵件正文不是Html格式的內容
            mailMessage.IsBodyHtml = false;
            // 設置郵件的優先級爲普通優先級
            mailMessage.Priority = MailPriority.Normal;
            //mailMessage.ReplyTo = new MailAddress(tbxUserMail.Text);

            // 封裝發送的附件
            System.Net.Mail.Attachment attachment = null;
            if (cmbAttachment.Items.Count > 0)
            {
                for (int i = 0; i < cmbAttachment.Items.Count; i++)
                {
                    string fileNamePath = cmbAttachment.Items[i].ToString();
                    string extName = Path.GetExtension(fileNamePath).ToLower();
                    if (extName == ".rar" || extName == ".zip")
                    {
                        attachment = new System.Net.Mail.Attachment(fileNamePath, MediaTypeNames.Application.Zip);
                    }
                    else
                    {
                        attachment = new System.Net.Mail.Attachment(fileNamePath,MediaTypeNames.Application.Octet);
                    }

                    // 表示MIMEContent-Disposition標頭信息
                    // 對於ContentDisposition具體類的解釋你們能夠參考MSDN
                    // 這裏我就不重複貼出來了,給個地址: http://msdn.microsoft.com/zh-cn/library/System.Net.Mime.ContentDisposition.aspx (着重看備註部分)
                    ContentDisposition cd = attachment.ContentDisposition;
                    cd.CreationDate = File.GetCreationTime(fileNamePath);
                    cd.ModificationDate = File.GetLastWriteTime(fileNamePath);
                    cd.ReadDate = File.GetLastAccessTime(fileNamePath);
                    // 把附件對象加入到郵件附件集合中
                    mailMessage.Attachments.Add(attachment);
                }
            }

            // 發送寫好的郵件
            try
            {
                // SmtpClient類用於將郵件發送到SMTP服務器
                // 該類封裝了SMTP協議的實現,
                // 經過該類能夠簡化發送郵件的過程,只須要調用該類的Send方法就能夠發送郵件到SMTP服務器了。
                smtpClient.Send(mailMessage);
                MessageBox.Show("郵件發送成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }
            catch(SmtpException smtpError)
            {
                MessageBox.Show("郵件發送失敗:[" + smtpError.StatusCode + "];[" 
                    + smtpError.Message+"];\r\n["+smtpError.StackTrace+"]."
                    ,"錯誤",MessageBoxButtons.RetryCancel,MessageBoxIcon.Error);
            }
            finally
            {
                mailMessage.Dispose();
                this.Cursor = Cursors.Default;
            }
        }

        #endregion
郵件發送代碼

3.2 郵件接收功能的實現

3.2.1 POP3協議

   前面介紹了郵件的發送,固然接收者須要登陸郵箱來查看收到的郵件了,此時就必有有一個協議去讀取服務器上郵件,POP3就是這樣的一個協議。還有兩外一種協議也是用來接收郵件的——IMAP協議,它與POP3協議區別有:1. IMAP使用的端口號是143而POP3郵件服務器經過監聽110端口來提供POP3服務;

                       2 . IMAP 容許客戶端在郵件服務器上創建文件夾來保持郵件,而不用把郵件下載到本地。而POP3須要把郵件下載到本地。

  和SMTP協議同樣,客戶端要經過POP3協議從POP3服務器上獲取郵件,也須要先與POP3服務器創建TCP鏈接,等待服務器向客戶端發送確認信息代表鏈接成功時,客戶端才能夠繼續發送命令給服務器來獲取郵件,在POP3協議中,規定的命令也是幾十條的,每條命令由命令和參數兩部分組成都是以回車換行結束,而且命令和參數之間由空格分隔,命令一般也是由3-4個字母組成,參數最多能夠爲40個字符的長度,而服務器的響應信息是由一個狀態碼和可能附加信息的字符組成,全部的響應信息也是以回車換行結束的。狀態碼和其餘協議定義的狀態碼有點不同,POP3服務器響應的狀態碼有兩種——「+OK」(肯定)和"-ERR"(失敗)。這樣客戶端能夠經過檢查響應的狀態碼所包含的字符來判斷服務器是否響應客戶端發送的命令,即響應信息中包含「+OK」表示成功響應,包含「-ERR」表示服務器未響應。同時在程序的實現中你們能夠經過Debug來查看響應消息的組成,這樣能夠加深理解。

3.2.2 郵件接收的過程

 客戶端從服務器接收郵件的過程主要經歷3個狀態:受權狀態、操做狀態和更新狀態

(1)受權狀態——客戶端發送與POP3服務器的TCP鏈接請求,服務器接收後發送一個響應確認信息以後,此時客戶端須要發送正確的用戶名和密碼進行確認,由於在郵件服務器上有不少用戶郵箱,只有提供正確的用戶名和密碼纔有權限訪問本身的郵箱,就像現實生活中咱們郵箱的鑰匙同樣的。

   發送用戶名命令: USER mytest1989@sina.cn

 發送密碼命令: PASS ******(這兩個命令都在代碼中有給出的,你們能夠參考代碼來理解郵件的接收過程)

(2) 操做狀態——若是客戶端提供了正確的用戶名和密碼,則受權狀態也就經過了,就至關於打開了在服務器上本身的郵箱,如今用戶就有權限進去下載,查看和刪除郵件等操做的,而後在現實生活中的取郵件和刪除郵件都很簡單(只要打開了郵箱門,用手去拿就能夠了),而後在網絡應用上,這些操做都須要發送POP3命令給服務器,服務器接收到命令後再給出響應。操做中經常使用的命令有:

  •  STAT 命令——該命令從服務器中獲取郵件總數和總字節數,服務器響應命令返回郵件總數和總字節數

 如:

?
客戶端發送POP3命令: STAT
服務器響應命令: +OK 2 1340<BR>服務器響應命令:

 

  • LIST 命令——該命令從服務器中得到郵件列表和大小,服務器響應命令返回列出郵件列表和大小。   

如: 

?
客戶端發送POP3命令:LIST
服務器響應命令: +OK 2 message(1430 octect)
服務器響應命令:1    700
服務器響應命令:2    730
服務器響應命令:<一個空行>
  • RETR 命令—— 該命令從服務器中得到一個郵件,格式爲 RETR <郵件編號>

如:

?
客戶端發送POP3命令:RETR 1
服務器響應命令: 700 octets
服務器響應命令:<郵件頭和內容>
服務器響應命令: <空行>
  • DELETE 命令——該命令告訴服務器將郵件標記爲刪除。(此時只是邏輯刪除) 

 (3)更新狀態——客戶端發送QUIT命令後,此時就進入更新狀態,POP3服務器釋放在操做狀態中取得的資源,並將邏輯刪除的郵件進行物理刪除,而後關閉與客戶端的TCP鏈接。這樣整個郵件處理的過程就結束了。                            

3.2.3 接收功能的實現代碼

 有了前面接收郵件過程的介紹,再參考代碼的實現,相信你們能夠更好的理解客戶端從POP3服務器中獲取郵件的過程的,因爲.net類庫並無幫咱們封裝POP3協議的實現類,要實現郵件的獲取能夠採用發送命令的方式,也可使用Jmail組件,這個組件其實就是POP3協議的封裝類,既然微軟沒有幫咱們作,其餘公司幫咱們作好後來幫助咱們簡單的實現郵件的接收的一個類庫罷了。而後在使用這個組件的過程當中出現了好幾個問題的,在源碼中我都解釋,你們能夠下載源代碼後查看的。

實現郵件接收的核心代碼以下:

        // 登陸郵箱(這裏是本程序——郵件收發器)
        private void btnLogin_Click_1(object sender, EventArgs e)
        {
            // 與POP3服務器創建TCP鏈接
            // 創建鏈接後把服務器上的郵件下載到本地
            // 設置當前界面的光標爲等待光標(就是咱們看到的一個動的圓形)
            Cursor.Current = Cursors.WaitCursor;

            lsttbxStatus.Items.Clear();
            try
            {
                // POP3服務器經過監聽TCP110端口來提供POP3服務的
                // 向POP3服務器發出tcp請求
                tcpClient = new TcpClient(tbxPOP3Server.Text, 110);
                lsttbxStatus.Items.Add("正在鏈接...");
            }
            catch
            {
                MessageBox.Show("鏈接失敗", "錯誤", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                lsttbxStatus.Items.Add("鏈接失敗!");
                return;
            }

            // 鏈接成功的狀況
            networkStream = tcpClient.GetStream();
            streamReader = new StreamReader(networkStream, Encoding.Default);
            streamWriter = new StreamWriter(networkStream, Encoding.Default);
            streamWriter.AutoFlush = true;
            string str;
            // 讀取服務器返回的響應鏈接信息
            str = GetResponse();
            if (CheckResponse(str) == false)
            {
                lsttbxStatus.Items.Add("服務器拒接了鏈接請求");
                return;
            }
            // 若是服務器接收請求
            // 向服務器發送憑證——用戶名和密碼

            // 向服務器發送用戶名,請求確認
            lsttbxStatus.Items.Add("覈實用戶名階段...");
            SendToServer("USER " + tbxUserMail.Text);
            str = GetResponse();
            if (CheckResponse(str) == false)
            {
                lsttbxStatus.Items.Add("用戶名錯誤.");
                return;
            }

            // 用戶名審覈經過後再發送密碼等待確認
            // 向服務器發送密碼,請求確認
            SendToServer("PASS "+txbPassword.Text);
            str = GetResponse();
            if (CheckResponse(str) == false)
            {
                lsttbxStatus.Items.Add("密碼錯誤!");
                return;
            }

            lsttbxStatus.Items.Add("身份驗證成功,能夠開始會話");
            // 向服務器發送LIST 命令,請求得到郵件列表和大小
            lsttbxStatus.Items.Add("獲取郵件....");
            SendToServer("LIST");
            str = GetResponse();
            if (CheckResponse(str) == false)
            {
                lsttbxStatus.Items.Add("獲取郵件列表失敗");
                return;
            }

            lsttbxStatus.Items.Add("郵件獲取成功");

            // 窗口控件控制
            tabControlMyMailbox.Enabled = true;
            btnReadMail.Enabled = false;
            btnDownLoad.Enabled = false;
            btnDeleteMail.Enabled = false;

            // 登錄成功後實例化郵件發送對象,以便後面完成發送郵件的操做
            // 實例化郵件發送類(SmtpClient)對象
            if (smtpClient == null)
            {
                smtpClient = new SmtpClient();
                smtpClient.Host = tbxSmtpServer.Text;
                smtpClient.Port = 25;
                    
                // 不使用默認憑證,即須要認證登錄
                smtpClient.UseDefaultCredentials = false;
                smtpClient.Credentials = new NetworkCredential(tbxUserMail.Text, txbPassword.Text);
                smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
            }

            // 登錄成功後,自動接收新郵件
            // 開始接收郵件
            try
            {
                btnRefreshMailList.PerformClick();
            }
            catch
            {
                MessageBox.Show("讀取郵件列表失敗!", "錯誤", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
            }

            lsttbxStatus.Items.Add("登錄成功!");
            lsttbxStatus.TopIndex = lsttbxStatus.Items.Count - 1;
            Cursor.Current = Cursors.Default;

            // 窗口控件控制
            richtbxMailContentReview.Enabled = true;
            tbxUserMail.Enabled = false;
            txbPassword.Enabled = false;
            btnLogin.Enabled = false;
            btnLogout.Enabled = true;
            tbxSmtpServer.Enabled = false;
            tbxPOP3Server.Enabled = false;
            btnReadMail.Enabled = true;
            btnDownLoad.Enabled = true;
            btnDeleteMail.Enabled = true;
            tabControlMyMailbox.Focus();
        }

        #region 處理與POP3服務器交互事件
        // 獲取服務器響應的信息
        private string GetResponse()
        {
            string str = null;
            try
            {
                str = streamReader.ReadLine();
                if (str == null)
                {
                    lsttbxStatus.Items.Add("鏈接失敗——服務器沒有響應");
                }
                else
                {
                    lsttbxStatus.Items.Add("收到:[" + str + "]");
                    if (str.StartsWith("-ERR"))
                    {
                        str = null;
                    }
                }
            }
            catch(Exception err)
            {
                lsttbxStatus.Items.Add("鏈接失敗:[" + err.Message + "]");
            }

            return str;
        }

        // 檢查響應信息
        private bool CheckResponse(string responseString)
        {
            if (responseString == null)
            {
                return false;
            }
            else
            {
                if (responseString.StartsWith("+OK"))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        // 向服務器發送命令
        private bool SendToServer(string str)
        {
            try
            {
                // 這裏必須使用WriteLine方法的,由於POP3協議中定義的命令是以回車換行結束的
                // 若是客戶端發送的命令沒有以回車換行結束,POP3服務器就不能識別,也就不能響應客戶端的請求了
                // 若是想用Write方法,則str輸入的參數字符中必須包含「\r\n」,也就是回車換行字符串。
                streamWriter.WriteLine(str);
                streamWriter.Flush();
                lsttbxStatus.Items.Add("發送:[" + str + "]");
                return true;
            }
            catch(Exception ex)
            {
                lsttbxStatus.Items.Add("發送失敗:[" + ex.Message + "]");
                return false;
            }
        }

        #endregion
郵件接收代碼

3.3 程序運行結果演示

 首先輸入郵箱名和密碼登陸到POP3服務器來獲取郵件列表的演示:

 

而後在郵件列表中選中一個郵件進行閱讀,而後進行回覆郵件的操做演示(郵件的發送均可以附加附件發送出去):

閱讀郵件的界面:

回覆郵件的界面:

同時點擊發送按鈕後,就能夠把郵件發送到sina的SMTP服務器上,再由新浪的SMTP服務器轉發到QQ的SMTP服務器,QQ的POP3服務器中QQ的SMTP服務器獲取收到的郵件,當QQ用戶輸入正確的郵箱名和密碼後就能夠從QQ的POP3服務器上獲取收到的郵件。

點擊發送按鈕後成功發送郵件的圖片:

4、總結

 介紹到這裏,本專題的內容就已經介紹完了,但願經過本專題可讓你們明白郵件發送和接收的原理,而且能夠自定義一個簡單郵件收發器的功能的,在後面一專題將介紹FTP協議(文件傳輸協議),並實現一個簡單的文件上傳和下載的程序。

 

源代碼下載地址: http://files.cnblogs.com/zhili/MailSendAndReceive.zip ,若是以爲有幫助的話,還望你們推薦下,謝謝你們的支持

 來自:http://www.cnblogs.com/zhili/archive/2012/09/24/MailSend_POP3_SMTP.html 

做者: Learning Hard
提示:本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。
 
若是對文章有任何問題,均可以再評論中留言,我會盡量的答覆您,謝謝你的閱讀
相關文章
相關標籤/搜索