程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 用C++ Builder實現電子郵件群發

用C++ Builder實現電子郵件群發

編輯:關於C++

摘 要:本文簡單闡述了發送電子郵件的原理,提出了一種基於C++ Builder和Access2000數據庫來實現電子郵件群發的方法,詳細介紹了C++ Builder 中TIdSMTP組件的使用,並給出了用TIdSMTP組件實現群發的核心示例代碼。

關鍵詞:電子郵件群發;認證;TIdSMTP;TIdMessage;ADO

引言

郵件群發這一手段被廣泛應用於電子商務、網絡營銷中,例如我們現在能夠通過chnia-pub.com(互動出版網)的書訊群發郵件了解到當前新書的資訊,據統計在美國有超過70%的Internet用戶的在線購物行為要歸功於Email營銷,另外那些建設了局域網的單位也可以通過郵件群發來發送通知或傳達文件,這樣能夠節省大量的人力物力而且方便迅速。本文簡單介紹了發送電子郵件的原理,提出了一種基於C++Builder和Access2000數據庫實現電子郵件群發的方法,詳細介紹了C++Builder 中TIdSMTP組件的使用,並給出了用TIdSMTP組件實現群發的核心示例代碼。

發送電子郵件的原理

1、SMTP協議

SMTP協議是IETF(Internet Engineering Task Force)制訂的有關電子郵件系統的標准協議組中的一員,它的目的就是實現有效(efficiently)和可靠的(reliably)郵件傳輸,主要對怎樣將電子郵件從發送方地址傳送到接收方地址,也就是對傳輸的規則做了規定。SMTP協議中的主要角色是SMTP發信機和SMTP收信機,但是一個SMTP服務器可能兼有兩種角色。SMTP協議采用了一組簡單的命令來建立連接並在主機之間傳送命令和數據。SMTP發信機向SMTP收信機發出SMTP命令,如:"MAIL FROM: <[email protected]&gt;"就是告知SMTP收信機郵件的來源,待收到命令後SMTP收信機則會響應應答SMTP命令,即會返回一個應答碼,應答碼一般為一個三位的十進制數,而且每一個數都有特定含義的,例如返回"250"表示要求的郵件操作完成。其他的SMTP命令和應答碼在RFC821中有詳細的描述,此處不再贅述。

2、ESMTP協議

目前,為了防止網絡上垃圾郵件的泛濫,幾乎所有的郵件服務提供商都在原來的SMTP服務器上追加了認證功能,但實際上SMTP協議本身並不具有認證的功能,在1999年3月出台的SMTP服務認證功能擴展(SMTP Service Extension for Authentication,RFC2544),即ESMTP中才定義了怎樣在SMTP客戶端與服務器之間來建立一種認證機制,執行認證協議的交換,同時擴展也為以後的協議交互進行了安全層的協商。該擴展是簡單認證和安全層(Simple Authentication and Security Layer,SASL)的一個方面。

SMTP認證功能的擴展實際實際上是增加了AUTH命令,AUTH命令的認證方式主要有LOGIN、CRAM-MD5和PLAIN等幾種,我國目前使用得比較多的是LOGIN方式認證。SMTP認證一般是在發送郵件之前進行一次,采用口令-應答(Challenge-Response)方式,即由服務器發送命令要求客戶端回答,客戶端根據服務器發送信息進行回答,如果應答通過了,則認證成功,即可繼續下一步處理。

用C++Builder實現郵件群發

1、總體設計

要實現郵件群發,我們首先需要實現與SMTP服務器連接,然後才能通過SMTP服務器發送郵件,由於SMTP服務器可能需要身份認證所以我們要編寫實用的郵件群發軟件還必須使其具有SMTP認證的功能。我們可以通過C++Builder中的TIdSMTP組件來實現與SMTP服務器的認證、連接和郵件的發送。通過編寫代碼循環讀取郵件地址列表(Mail List)中的郵件地址並發送郵件從而實現群發。考慮到管理和獲取郵件地址的方便性,地址列表存儲的安全性以及基於該郵件地址列表的其他相關應用程序的開發我們可以采用Access2000數據庫來存儲郵件地址列表,利用C++Builder中的TADOTable組件我們可以使用ADO方式輕松的實現對Access2000數據庫的直接訪問和各種操作。

2、郵件地址數據庫ADO方式訪問示例

C++Builder在數據庫處理方面向來是具有自己的優勢,一般我們都采用Borland的強大的BDE數據庫引擎來訪問和維護數據庫,但是使用BDE引擎有一個非常不方便的地方就是不能在程序運行階段動態指定數據源,而采用ADO(ActiveX Data Objects)方式具有高性能、高兼容性和高靈活性的特點。采用ADO方式我們既可以在程序設計階段指定數據源也可以在運行時動態修改數據源,而在實際應用中用戶可能會要動態的指定存儲郵件地址的數據庫,為了使編寫的群發程序具有更好得實用性,所以我選擇使用C++Builder中的ADO組件TADOTable來訪問和操作Access2000數據庫,具體示例代碼如下:

Void __fast call TForm1: N_OpenClick (TObject *Sender)
{
 AnsiString ConnStr;
 Try {ADOTable1->Active = false;
 OpenDialog1->InitialDir =".\\" ; //初始化打開對話框
 OpenDialog1->Filter = "MDB郵件列表文件 (*.mdb)|*.mdb|所有文件 (*.*)|*.*";
 OpenDialog1->DefaultExt = String("mdb");
 if(OpenDialog1->Execute ())//動態指定數據源
 {
  ConnStr=" Provider=Microsoft.Jet.OLEDB.4.0; Jet OLEDB: Database Password =" + MaskEdit1->Text. Trim () + "; Data Source = " + OpenDialog1-> Filename. Trim () +"; Persist Security Info=True";
  ADOTable1->Connection String =ConnStr.Trim ();
  ADOTable1->Active=true;
 }
 Catch (Exception &exception)
 {
  Application->Show Exception (&exception);
 }
}

注意代碼中加粗的部分是必須的,在訪問有密碼保護的Access2000數據庫時必須以獨占方式打開,如果沒有加粗部分的代碼,則連接數據庫時會提示錯誤。

3、使用TIdSMTP組件實現群發

在C++Builder6.0中新增加了一套INDY組件,這是一套開放源代碼、功能強大的Internet組件,目前該套組件的最新版本是INDY10, 雖然在6.0以前的C++Builder版本中未集成這套組件,但是可以到INDY的網站http://www.indyproject.org/ 上下載源代碼進行安裝。INDY中的TIdSMTP組件符合RFC821、RFC1869和RFC2544的規范,利用TIdSMTP組件我們能夠輕松的實現與SMTP服務器的認證連接、郵件的發送和回執請求。下表是要實現郵件群發,將使用到TIdSMTP組件的基本屬性和方法:

表1 TIdSMTP組件的基本屬性和方法

方法名 功能描述 Connect () 連接SMTP服務器 Disconnect () 關閉SMTP會話 Send (Amsg: IdMessage) 發送郵件 Connected () 判斷是否與SMTP服務器連接 Disconnected () 判斷是否與SMTP服務器斷開連接 屬性名 功能描述 Host SMTP服務器地址,可以使用IP地址或域名,如:Smtp.sohu.com Port 與SMTP服務器建立TCP連接使用的端口,一般為25 Authentication Type 與SMTP服務器認證的類型,目前版本只提供LOGIN方式 UserID 郵箱用戶名 Password 郵箱密碼

在TIdSMTP中執行郵件發送的是Send()方法,它的參數是一個TIdMessage類的實例,所以要實現完整的郵件發送TIdSMTP組件還必須配合INDY中的TIdMessage組件使用。 TIdMessage組件封裝了一個完整的符合RFC822和RFC1036規范的Internet消息,實際上TIdSMTP組件是用來實現連接SMTP服務器、認證及郵件的發送,而TIdMessage則負責創建郵件的內容(如:主題、正文、收件人等),以下是TIdMessage組件與實現郵件群發相關的基本屬性列表:

表2 TIdMessage組件與實現郵件群發相關的基本屬性

屬性名 功能描述 Content Type 郵件內容的類型,如:text/html等 Subject 郵件主題 ody B郵件正文 From->Name 發件人姓名 Recipients->Email Addresses 收件人EMAIL地址

需要說明的是在實際編寫代碼時對TIdMessage組件的Content Type屬性需要賦值,指明消息正文的類型,例如我們群發郵件時,郵件的正文一般為文本,那麼我們就必須將Content Type屬性賦值為text/html,否則郵件的正文在接收浏覽郵件時將會變為郵件附件的形式。下面給出實現郵件群發的示例代碼:

Void __fast call TForm1: SEND_BTNClick (TObject *Sender)
{
 Int recnum, k; AnsiString addr;
 IdSMTP1->Host = ComboBoxaddr->Text. Trim ();//設定SMTP服務器地址和端口號
 IdSMTP1->Port =25;
 if(CheckBox_AUTH->Checked ==true) //判斷並設置SMTP服務器是否需要認證
 {
  IdSMTP1->Authentication Type = at Login;
  IdSMTP1->UserId = Edit name->Text. Trim ();
  IdSMTP1->Password=MaskEdit_pass->Text. Trim ();}
  IdMessage1->Content Type = "text/html"; //根據用戶填寫的信息創建郵件
  IdMessage1->Subject =Edit3->Text. Trim ();0
  … …
  ADOTable1->First(); //循環讀取郵件地址並發送實現群發
  Recnum= ADOTable1->Record Count;
  For (k=0;k<=recnum-1; k++)
  {
   Addr=Trim (ADOTable1->Field Byname ("Email")->AsString) ;
   IdMessage1->Recipients->Email Addresses =addr
   If (! IdSMTP1->Connected ())
   {
    Try
     {IdSMTP1->Connect ();}
    Catch (Exception &e)
     {Application->Message Box(e.Message, "連接SMTP服務器失敗", MB_ICONWARNING); }
   }
   If (IdSMTP1->Connected ())
   {
    Try
     {IdSMTP1->Send (IdMessage1);}
    Catch (Exception &e)
     {Application->Message Box(e.Message, "發送失敗", MB_ICONWARNING); }
   }
   ADOTable1->Next ();}
   Application->Message Box ("發送完成!","郵件系統",MB_OK);
  …
 }

結束語

雖然以上的示例代碼基本實現了郵件群發功能,我們實現的是LOGIN認證方式,LOGIN方式對用戶名和密碼的BASE64編碼是一種公共的編碼標准,其實並不安全。同時並不是所有的郵件服務器都只支持LOGIN方式,例如新浪還支持CRAM-MD5認證方式,如果我們要實現其他的認證方式我們可以到http://www.ararat.cz/synapse/ 這個網站上下載一套synapse的TCP/IP類庫利用它可以實現SMTP的多種認證方式。另外,根據RFC821描述,實際上我們郵件的轉發路徑(forward-path)可以包含多個郵箱地址,所以當需群發的郵箱地址不是太多的情況下,就不必在郵箱地址列表每取得一個地址就發送一次,而是可以將多個郵件地址連接起來(每個郵箱之間用逗號分隔)作為一個地址發送,同樣能夠實現群發郵件,例如:IdMessage1 ->Recipients -> Email Addresses ="mailbox1,mailbox2" 但是如果需群發的郵箱地址比較多的情況下,作者建議分多次來發送,因為如果郵件的轉寄路徑包含郵箱地址過多的話會使郵件變得過大,增加郵件發送時延。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved