程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 利用JMail組件快速構建郵件程序(上)

利用JMail組件快速構建郵件程序(上)

編輯:關於VC++

當你需要在VC程序中提供郵件支持功能的時候,你有許多種選擇:

1)根據SMTP,POP3,MIME等協議從零開始實現。這要求熟悉RFC 821,RFC 822,RFC 1123, RFC 1652, RFC 1939, RFC2045-2049等一系列協議, 您可以實現一切可能實現的功能,但同時需要花大量的時間。

2)利用一些免費的封裝類,比如CSMTP,CPOP3。雖然可以達到快速實現的目的,但功能非常有限。

3)利用MAPI調用支持MAPI的郵件發送程序( 例如:Outlook )發送郵件,這種實現方式需要客戶端安裝指定的郵件發送程序,不夠靈活

4)利用現成的組件例如:w3 JMail組件來構建您的系統,JMail組件功能強大,可以輕松完成郵件發送、接收、加密、集群傳輸等工作。

雖然JMail用得最多的是ASP下的應用,但它在其它語言中都能夠很好地工作,本文將針對w3 JMail 4.3在VC中的使用展開討論。

一、准備篇

1.1 組件的安裝

因為JMail4.3與以前的版本相比接口有了變動,所以推薦您使用4.3版本,您可以到以下網址下載JMail 4.3

DIMAC公司 http://www.dimac.net/

VC知識庫 http://www.vckbase.com/tools

1.2 快速郵件發送程序MINI版

我們從這個小例子大致了解一下JMail組件的工作過程

#import "jmail.dll" // 導入jmail.dll, 假如jmail.dll不在工程目錄下,您需要寫上完整路徑
void main()
{
  CoInitialize(NULL); // COM的初始化
  {
    // 創建SpeedMailer實例
    jmail::ISpeedMailerPtr pSpeedMailer("JMail.SpeedMailer");
    
    // 發送郵件
    pSpeedMailer->SendMail("[email protected]",    // 發件人郵箱
          "[email protected]",    // 收件人郵箱
          "主題:你好!",        // 主題
          "正文:大家好才是真的好!",  // 正文
          "smtp.163.com"); // SMTP服務器
  }
  CoUninitialize();
}

看了上述代碼您肯定會說真的很容易,這個例子是利用了ISpeedMailer接口來發送簡單的郵件,我想大家一看就清楚。

為了使這個流程看起來不至於令人生畏,我把異常捕捉省略了,在實際使用中應該加入異常捕捉,具體方法請見下文。

1.3 異常捕捉

這裡的異常捕捉與我們所使用的捕獲COM異常沒有兩樣,在這裡稍加描述只是提高本文的完整性,請看如下代碼:

try
{
  ...
  ... 發送代碼
  ...
}
catch( _com_error & e)
{
  cerr << "錯誤號: 0x" << hex << e.Error() << endl;
  cerr << "錯誤信息: " << e.ErrorMessage() << endl;
  cerr << "錯誤描述: " << e.Description() << endl;
}

二、郵件發送篇

下圖是本文附帶的郵件發送程序運行效果圖:

 

2.1 利用IMessage接口發送帶附件的郵件

在前面我們用ISpeedMailer接口來發送郵件,但功能有限,IMessage接口為我們提供了功能完備的發送功能,請看下面的例子:

jmail::IMessagePtr pMessage("JMail.Message");
// 發件人郵箱
pMessage->From = "[email protected]";
// 發件人姓名
pMessage->FromName = "我的名字";
// 添加收件人1, 無收件人姓名與PGP KEY
pMessage->AddRecipient("[email protected]","","");
// 添加收件人2, 無PGP KEY
pMessage->AddRecipient("[email protected]","收件人名字","");
// 添加收件人3,這裡的PGP KEY只是作為示例,實際中需要用PGP軟件生成
pMessage->AddRecipient("[email protected]","收件人名字","R9Rb7decrQWINuce3uFc0xDG");
// 優先級設置,1-5逐次降低, 3為中級
pMessage->Priority = 3;
// 編碼方式設置, 默認是iso-8859-1
pMessage->Charset = "GB2312";
// 主題
pMessage->Subject = "郵件主題";
// 正文
pMessage->Body = "郵件正文\r\n";
// 如有必要,可以再添加一些正文
pMessage->AppendText("VC知識庫www.VCKBASE.com歡迎您! 祝您身體健康!");
// 添加附件
pMessage->AddAttachment("C:\\CONFIG.SYS", VARIANT_FALSE, "application/octet-stream");
pMessage->AddAttachment("C:\\test.gif", VARIANT_TRUE, "image/gif");
// 開始發送
pMessage->Send("mailserver.com", VARIANT_FALSE);

2.2 發送HTML格式的郵件

在這裡我們需要完成的功能是發送一封帶圖像的HTML郵件,圖像存儲在本地郵件附件裡,而不是通過遠地鏈接,實現的關鍵是如何引用

附件中的圖像:

在調用AddAttachment時它會返回一個稱為content id的字串,比如它返回的是"AABBCCDD",則我們用<IMG SRC="cid:AABBCCDD">這種方式

來引用該圖像,請看如下代碼片斷:

......
// 這裡添加Body是為了使郵件浏覽者在沒有切換到HTML時給予提醒
pMessage->Body = "郵件采用HTML格式,請切換到HTML模式。\r\n";
// 添加附件
_bstr_t bstrCID = pMessage->AddAttachment("D:\\logo.gif", VARIANT_TRUE, "image/gif"); // 返回content id
// 根據content id 生成IMG HTML標記
char pImgHTML[200];
strcpy(pImgHTML, "<IMG SRC=''cid:");
strcat(pImgHTML, (char*)bstrCID);
strcat(pImgHTML, "''>");
// 添加HTML正文內容
pMessage->HTMLBody = "<H2>VC知識庫</H2>";
pMessage->AppendHTML("<BR>www.VCKBASE.com ");
pMessage->AppendHTML(pImgHTML);
// 開始發送
pMessage->Send("", VARIANT_FALSE);

關於content id更詳細的內容請閱讀MIME協議

2.3 特殊郵件頭的構造

To,From,Subject,Message-ID,Date,Received等是標准的郵件頭,自定義郵件頭會自動在前面加X, 例如X-Originating-IP

// 標准郵件頭
pMessage->AddNativeHeader("Message-ID", "VCKBASE:ABCDEFG1234567");
pMessage->AddNativeHeader("Date", "1800-1-1");
// 自定義郵件頭
pMessage->AddHeader("Originating-IP", "123.345.567.789"); // 給它個假冒偽劣IP
pMessage->AddHeader("Mailer", "MyMailBox 1.0"); // 郵件發送器名稱
pMessage->AddHeader("Company", "MyCompany"); // 隨便加點定制信息

有時收到郵件的時候會提示:發件人請求一個收條以表示你已經閱讀過這封郵件,您願意發送一個收條嗎?

發送這樣的信,我們只需要:

pMessage->AddNativeHeader("Disposition-Notification-To", "[email protected]");

[email protected]是回復收條的郵箱。

2.4 郵件服務器需要發信認證的處理

一些SMTP服務器需要認證信息,您需要在Send時提供用戶名與密碼,例如:

pMessage->Send("username:[email protected]")

2.5 不通過SMTP中繼服務器發送郵件

在發信時我們一般把信件提交給SMTP中繼服務器,SMTP中繼服務器負責和目標郵局聯系,並最終將信件提交到收件人所在的郵件服務器。

在沒有可利用的SMTP中繼服務器時,我們可以將服務器名設置為空,例如:

pMessage->Send("", VARIANT_FALSE);

這樣,組件會通過DNS查詢目標域(例如:163.com)中的MX記錄,直接將信件提交到MX記錄中所指定的郵件服務器中。

2.6 經代理網關發送郵件

上文所說的SMTP中繼服務器上的郵件傳輸代理程序(MTA),與WINGATE,CPROXY等代理軟件提供的SMTP代理工作原理是一樣的,所以具體的發送過程也一樣,例如:

代理網關地址 192.16.10.11, 要往[email protected]發信,代碼如下:

......
pMessage->AddRecipient("[email protected]","","");
pMessage->Send("192.16.10.11", VARIANT_FALSE);

2.7 關於郵件的加密傳輸與集群發送

JMail的免費版本並沒有提供加密傳輸與集群發送功能,要想使用這些功能,您需要安裝無限制的JMail標准版或專業版。

對於加密傳輸,您還需要安裝PGP軟件,例如:PGPFreeware

集群發送功能在擁有成千上萬個客戶時是非常有用的,定制好模板後,數據庫中的記錄自動填入模板生成信件發送。

由於筆者只有免費版本的JMail,所以這一功能未能嘗試。

雖然免費版未提供集群發送功能,但我們可以只使用IMessage接口結合數據庫來實現集群發送功能.

2.8 郵件發送時的常見錯誤

當所設置的SMTP服務器不存在,錯誤信息:

The message was undeliverable. All servers failed to receive the message

如果沒有設置SMTP服務器時,試圖發送一封錯誤郵件地址的信,

例如:[email protected] 將返回如下錯誤信息:

WSAGetLastError() returned 11001, Host not found

許多SMTP服務器不支持轉發,或支持轉發但不轉發MAIL FROM不是本地帳號的信,錯誤信息:

The message was undeliverable. All servers failed to receive the message

許多SMTP服務器不接收外部的郵件,例如smtp.sohu.com,所以想要向SOHU發信你可以不設郵件服務器, 而是通過

DNS查詢郵件交換服務器,或者直接將郵件服務器設置為sohumx.sohu.com。

像SOHU信箱會對一些發件人信箱進行過濾,例如您將發件人信箱設為[email protected],或者發件人信箱與收件人信箱一致,

發信時將返回:554<[email protected]>:Sender address rejected:Access denied

(未完待續...)

本文配套源碼

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