日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

利用MAPI实现邮件收发(VC++)

發(fā)布時間:2023/12/20 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用MAPI实现邮件收发(VC++) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

今天看windows mobile的document關于MAPI這部分,在網(wǎng)上google了下,結果找到這篇,它不是winmobile的,而是普通的PC,不過MAPI的東西在這兩個環(huán)境下思路大體相同,轉了下面充數(shù)。原文發(fā)在csdn上。

一、概述

---- 本文主要講述如何使用Visual C++用MAPI編寫E-mail程序。MAPI是包含在Windows之中的,因此不需要安裝其他額外的部件。MAPI有以下三種形式:

·???????SMAPI,Simple MAPI,簡單的MAPI

·???????CMC,Common Messaging Calls,一般通訊調用

·???????完整的MAPI

---- SMAPI和CMC都包含在完整的MAPI中,當用戶想執(zhí)行一些高級操作,比如編寫自己的E-mail服務器的時候,必須使用完整的MAPI。本文主要闡述如何編寫能夠收發(fā)電子郵件的程序,因此使用SMAPI就足夠了。

二、編寫電子郵件程序

3-1?初始化MAPI

---- 要使用MAPI,必須首先對它進行初始化。初始化包括以下三個步驟:

1.????裝載MAPI32.DLL動態(tài)鏈接庫

2.????找到想要調用的MAPI函數(shù)地址

3.????登錄到電子郵件對象

3-1-1?裝載MAPI32.DLL

---- 要裝載MAPI,用戶必須程序運行時動態(tài)的裝載一個動態(tài)鏈接庫。LoadLibrary函數(shù)提供了此功能,它定位一個動態(tài)鏈接庫,并返回HINSTANCE局柄(需要保存該句柄)。

LoadLibrary的語法如下:

LoadLibrary ( lpLibFileName );

其中l(wèi)pLibFileName為LPCTSTR結構變量,

是所要調用的庫的路徑和名稱。

?

程序示例:

// 調用MAPI32.DLL并計算函數(shù)地址

HINSTANCE hInstMail;

hInstMail = ::LoadLibrary ( “MAPI32.DLL” );

if ( hInstMail == NULL )

{

????????// 錯誤處理

????????// 受篇幅限制,下面的錯誤處理部分省略

}

3-1-2?確定函數(shù)地址

---- 由于MAPI32.DLL是被動態(tài)裝載的,因此不知道所要調用的函數(shù)地址,也就不能一開始就調用它們,而要通過函數(shù)名獲得函數(shù)的地址,并在動態(tài)鏈接庫中查找每一個函數(shù)并核實。因此首先必須為這些函數(shù)聲明指針

程序示例:

// 為MAPI32.DLL中的函數(shù)聲明函數(shù)指針

ULONG (PASCAL *lpfnMAPISendMail) (LHANDLE lhSession,ULONG ulUIParam, lpMapiMessage lpMessage,FLAGS flFlags, ULONG ulReserved);

ULONG (PASCAL *lpfnMAPIResolveName) (LHANDLE lhSession,ULONG ulUIParam, LPTSTR lpszName,FLAGS ulFlags, ULONG ulReserved,

lpMapiRecipDesc FAR *lppRecip);

ULONG (FAR PASCAL *lpfnMAPILogon)(ULONG ulUIParam,PSTR lpszProfileName, LPSTR lpszPassword,FLAGS flFlags, ULONG ulReserved,

LPLHANDLE lplhSession);

ULONG (FAR PASCAL *lpfnMAPILogoff)(LHANDLE lhSession,ULONG ulUIParam, FLAGS flFlags,ULONG ulReserved);

ULONG (FAR PASCAL *lpfnMAPIFreeBuffer)(LPVOID lpBuffer);

ULONG (FAR PASCAL *lpfnMAPIAddress)(LHANDLE lhSession,ULONG ulUIParam, LPSTR lpszCaption,ULONG nEditFields, LPSTR lpszLabels,

ULONG nRecips, lpMapiRecipDesc lpRecips,FLAGS flFlags, ULONG ulReserved,LPULONG lpnNewRecips,lpMapiRecipDesc FAR *lppNewRecips);

ULONG (FAR PASCAL *lpfnMAPIFindNext)(LHANDLE lhSession,ULONG ulUIParam, LPSTR lpszMessageType,

LPSTR lpszSeedMessageID, FLAGS flFlags,ULONG ulReserved, LPSTR lpszMessageID);

ULONG (FAR PASCAL *lpfnMAPIReadMail)(LHANDLE lhSession,ULONG ulUIParam, LPSTR lpszMessageID,

FLAGS flFlags, ULONG ulReserved,lpMapiMessage FAR *lppMessage);

---- 為了決定每一個函數(shù)的地址,必須為每一個函數(shù)調用GetProcAddress。

GetProcAddress的語法為:

????????GetProcAddress (hModule, lpProcName);

其中,hModule為HMODULE結構,是所調用DLL模塊的句柄;

lpProcName為LPCSTR結構,是函數(shù)名稱。

?

程序示例:

// 找到MAPI32.DLL函數(shù)的地址,并將它們保存在函數(shù)指針變量里

(FARPROC&) lpfnMAPISendMail = GetProcAddress(hInstMail,

“MAPISendMail”);

(FARPROC&) lpfnMAPIResolveName = GetProcAddress(

hInstMail, “MAPIResolveName”);

(FARPROC&) lpfnMAPILogon = GetProcAddress(hInstMail,

“MAPILogon”);

(FARPROC&) lpfnMAPILogoff = GetProcAddress(hInstMail,

“MAPILogoff”);

(FARPROC&) lpfnMAPIFreeBuffer = GetProcAddress(

hInstMail, “MAPIFreeBuffer”);

(FARPROC&) lpfnMAPIAddress = GetProcAddress(hInstMail,

“MAPIAddress”);

(FARPROC&) lpfnMAPIFindNext = GetProcAddress(hInstMail,

“MAPIFindNext”);

(FARPROC&) lpfnMAPIReadMail = GetProcAddress(hInstMail,

“MAPIReadMail”);

?

3-1-3?登錄到電子郵件對象

---- 用戶必須在電子郵件系統(tǒng)中登錄,才能實現(xiàn)MAPI的各種功能。MAPI提供了登錄的三種選擇:

·???????登錄到一個已經(jīng)存在的對象。

·???????登錄到一個新對象,用編程的方法確定解釋新信息。

·???????使用對話框提示用戶登錄。

---- 我們通常選擇登錄到一個已經(jīng)存在的電子郵件對象,因為網(wǎng)絡合作用戶通常會保持自己的電子郵件程序處于激活狀態(tài)。登錄通常使用MAPI提供的函數(shù)lpfnMAPILogon。

lpfnMAPILogon的語法為:

lpfnMAPILogon (lpszProfileName, lpszPassword, flFlags,

ulReserved, lplhSession );

---- 其中,lpszProfileName指向一個256字符以內(nèi)的登錄名稱,lpszPassword指向密碼,它們均為LPTSTR結構。flFlags 為FLAGS結構,其值詳見表1。ulReserved必須為0。lplhSession為輸出SMAPI的句柄。

表1:lpfnMAPILogon函數(shù)中flFlags的值

值??????意義

MAPI_FORCE_DOWNLOAD ???在函數(shù)調用返回之前下載用戶的所有郵件。

如果MAPI_FORCE_DOWNLOAD沒有被設置,

那么信件能夠在函數(shù)調用返回后在后臺被下載。

MAPI_NEW_SESSION ??????建立一個新會話,

而不是獲得環(huán)境的共享會話。如果MAPI_NEW_SESSION沒有被設置,

MAPILogon使用現(xiàn)有的共享會話。

MAPI_LOGON_UI 顯示一個登錄對話框來提示用戶輸入登錄信息。

例如Outlook檢查用戶電子郵件時便是如此。

MAPI_PASSWORD_UI ??????MAPILogon只允許用戶輸入電子郵件的密碼,

而不許改動賬號。

?

程序示例:

LHANDLE lhSession;

ULONG lResult = lpfnMAPILogon(0, NULL, NULL, 0, 0,

&lhSession);

if (lResult != SUCCESS_SUCCESS)

//SUCCESS_SUCCESS在MAPI.H中被定義

{

????????// 錯誤處理

}

?

3-2?閱讀電子郵件

---- MAPIFindNext和MAPIReadMail使用與閱讀E-mail的兩個基本函數(shù)。MAPIFindNext用于定位第一封或下一封電子郵件并返回標識號,MAPIReadMail返回以該標識號為基礎的電子郵件的內(nèi)容。另外,一個常用的函數(shù)是MAPIFreeBuffer,用于釋放內(nèi)存。

3-2-1?定位到第一封信

---- 要找到第一封信,需要使用MAPIFindNext函數(shù),其函數(shù)聲明如下:

ULONG FAR PASCAL MAPIFindNext(LHANDLE lhSession,

ULONG ulUIParam, LPTSTR lpszMessageType,

LPTSTR lpszSeedMessageID, FLAGS flFlags,

ULONG ulReserved, LPTSTR lpszMessageID )

---- 其中,lhSession為提交SMAPI的會話句柄;ulUIParam為父窗體的句柄;lpszMessageType指向一個字符串,用來鑒別郵件類型,并加以查找; lpszSeedMessageID為指向起始信息ID的指針,其值為0時,MAPIFindNext獲得第一封電子郵件;flFlags的值見表2; ulReserved必須為0;lpszMessageID為輸出值,它是指向信息ID地址的指針。

---- 表2:MAPIFindNext函數(shù)中flFlags的值

值??????意義

MAPI_GUARANTEE_FIFO????按郵件發(fā)送的時間順序接受電子郵件。

MAPI_LONG_MSGID 返回信件標識符可達512字符。

MAPI_UNREAD_ONLY???????只列舉沒有閱讀過的電子郵件。

?

程序示例:

// 找到第一條沒有閱讀的電子郵件

char pMessageID [513];

ULONG lResult = lpfnMAPIFindNext(lhSession, NULL, NULL,

NULL, MAPI_LONG_MSGID | MAPI_UNREAD_ONLY,

0, pMessageID);

3-2-2 閱讀信息

當信件ID被獲取后,就可以調用MAPIReadMail

閱讀實際的E-mail信息了。MAPIReadMail的函數(shù)聲明如下:

ULONG FAR PASCAL MAPIReadMail(LHANDLE lhSession,

ULONG ulUIParam, LPTSTR lpszMessageID,

FLAGS flFlags, ULONG ulReserved,

lpMapiMessage FAR * lppMessage);

其中,lppMessage為指向MapiMessage的指針;

除flFlags外的其他參數(shù)與lpfnFindNext函數(shù)的同名參數(shù)意義相同,

flFlags參數(shù)的值見表3:

?

表3:MAPIReadMail函數(shù)中flFlags的值:

值??????意義

MAPI_BODY_AS_FILE??????將郵件信息寫到一個臨時文件中,

并且將它作為第一個附件添加到附件列表中。

MAPI_ENVELOPE_ONLY?????只讀取郵件標題。

MAPI_PEEK??????讀完郵件之后不把它標記為“已讀”。

MAPI_SUPPRESS_ATTACH???MAPIReadMail函數(shù)不拷貝附件,

但是將郵件文本寫入MapiMessage結構中。

?

程序示例:

// 讀取電子郵件

long nFlags = MAPI_SUPPRESS_ATTACH;

if (!bMarkAsRead)

????????nFlags = nFlags | MAPI_PEEK;

lResult = lpfnMAPIReadMail(lhSession, NULL, pMessageID,

nFlags, 0, &pMessage);

if (lResult != SUCCESS_SUCCESS);

????????return false;

?

如果調用成功,就可以訪問MapiMessage結構了(使用pMessage):

pMessage- >ulReserved:0

pMessage- >lpszSubject:郵件標題

pMessage- >lpszNoteText:郵件信息

pMessage- >lpszMessageType:郵件類型

pMessage- >DateReceived:接收時間

pMessage- >lpszConversationID:郵件所屬的會話線程ID

pMessage- >flFlags:其值見表4

?

表4:MapiMessage結構中的flFlags

值??????意義

MAPI_RECEIPT_REQUESTED 接收通知被申請。

客戶端應用程序在發(fā)送消息時設置該項。

MAPI_SENT??????郵件已被發(fā)送。

MAPI_UNREAD????郵件是“未讀”狀態(tài)。

?

pMessage- >lpOriginator:指向MapiRecipDesc結構,包含發(fā)件人信息。

pMessage- >nRecipCount:信件者數(shù)目。

pMessage- >lpRecips:指向MapiRecipDesc結構數(shù)組,包含接收者信息。

pMessage- >nFileCount:附件數(shù)量。

pMessage- >lpFiles:指向MapiFileDesc結構數(shù)組,

每一個結構包含一個文件附件。

?

3-2-3?釋放內(nèi)存

---- 在訪問另一條信件以前應當釋放內(nèi)存,否則會出現(xiàn)內(nèi)存泄漏。

程序示例:

?

// 釋放內(nèi)存

lpfnMAPIFreeBuffer(pMessage);

3-2-4 定位到下一條信件

定位到下一條信件依然使用MAPIFindNext函數(shù),

該函數(shù)聲明及參數(shù)意義詳見3-2-1節(jié)。下面示范如何定位到下一條信件。

?

程序示例:

// 定位到下一條沒有閱讀的信件

ULONG lResult = lpfnMAPIFindNext(lhSession, NULL, NULL,

pMessageID, MAPI_LONG_MSGID|MAPI_UNREAD_ONLY,

0, pMessageID);

?

3-3?發(fā)送電子郵件

---- 發(fā)送電子郵件的一般步驟:

---- 1. 建立MapiMessage結構對象

---- 2. 調用MAPIResolveName使發(fā)送者名稱合法

---- 3. 添加附件

---- 4. 調用MAPISendMail發(fā)送電子郵件

---- 5. 調用MAPIFreeBuffer釋放內(nèi)存

---- 下面詳細分別詳細闡述。

3-3-1?建立MapiMessage結構對象

---- 對于MapiMessage結構,3-2-2節(jié)已經(jīng)做過介紹,下面一步步介紹如何設置其中的值:

---- 1. 為MapiMessage對象分配內(nèi)存:

???????????????MapiMessage message;

???????????????Memset(&message, 0, sizeof(message));

---- 2. 將ulReserved設置為0:

???????????????message.ulReserved = 0;

---- 3. 設置信息類型指針lpszMessageType,可以為NULL:

???????????????message.lpszMessageType = NULL;

---- 4. 設置信件標題(lpszSubject):

???????????????char subject[512];

???????????????strcpy(subject, sSubject);

???????????????message.lpszSubject = subject;

---- 5. 設置信件內(nèi)容:

???????????????char text[5000];

???????????????strcpy(text, sMessage);

???????????????message.lpszNoteText = text;

---- 6. 設置flFlags標識,詳見3-2-2節(jié)中表4:

???????????????message.flFlags = MAPI_SENT;

---- 7. 用一個指向MapiRecipDesc結構的指針設置發(fā)送者信息(lpOriginator),或將其設置為NULL:

???????????????message.lpOriginator = NULL;

---- 8. 設置接收者數(shù)目(nRecipCount),可以是1或更多:

???????????????message.nRecipCount = 1;

---- 9. 設置接收者信息(lpRecips),詳見3-3-2節(jié)

---- 10. 設置附件數(shù)量(nFileCount)

---- 11. 設置附件信息,詳見3-3-3節(jié)

b3-3-2?正確設置接收者信息

---- 設置接收者信息時,應當使用MAPIResolveName函數(shù)來為MapiRecipDesc結構對象分配內(nèi)存,并返回一個指針,該指針將被保存在MapiMessage結構的lpRecips中。MAPIResolveName的函數(shù)聲明如下:

ULONG FAR PASCAL MAPIResolveName(LHANDLE lhSession,

ULONG ulUIParam, LPTSTR lpszName,

FLAGS flFlags, ULONG ulReserved,

lpMapiRecipDesc FAR * lppRecip )

---- 其中l(wèi)ppRecip即為前面提到的返回的指針。除flFlags外其余參數(shù)與前幾個函數(shù)意義相同。flFlags的值詳見表5。

表5:MAPIResolveName中flFlags的值

值??????意義

MAPI_AB_NOMODIFY???????對話框為只讀。如果MAPI_DIALOG被設置,

那么該項將被忽略。

MAPI_DIALOG????顯示一個名稱解決方案的對話框

MAPI_LOGON_UI??如果需要的話,將會顯示儀個對話框讓用戶登錄

MAPI_NEW_SESSION???????新建一個會話

?

程序示例:

char recipient[512];

strcpy(recipient, sTo);

lResult = lpfnMAPIResolveName(lhSession, 0, recipient,

0, 0, &message.lpRecips);

?

3-3-3?添加附件

---- 下面的程序示例將演示如何在電子郵件中包含附件。只有一點需要說明:MapiFileDesc結構中flFlags的值,詳見表6。

表6:MapiFileDesc結構中flFlags的值

值??????意義

MAPI_OLE???????附件是OLE對象。

MAPI_OLE_STATIC 附件是靜態(tài)OLE對象。

0???????附件將被視為數(shù)據(jù)文件

?

程序示例:

// 設置附件信息

CString sPath, sFileName;

MapiFileDesc FileInfo;

char path[512];

char filename[512];

if (sAttachment == “”)

????????message.nFileCount = 0;

else

{

????????int nPos = sAttachment.ReverseFind(‘\\’);

????????if (nPos == -1)

????????{

???????????????sPath = sAttachment;

????????}

????????else

????????{

???????????????sPath = sAttachment;

???????????????sFilename = sAttachment.Mid(nPos +1);

????????}

????????strcpy(path, sPath);

????????strcpy(filename, sFilename);

?

????????message.nFileCount = 1;

????????FileInfo.ulReserved = 0;

?

????????FileInfo.flFlags = 0;

?

????????FileInfo.nPosition = sMessage.GetLength() –1;

????????FileInfo.lpszPathName = path;

????????FileInfo.lpszFileName = filename;

????????FileInfo.lpFileType = NULL;

????????message.lpFiles = & m_FileInfo;

}

?

3-3-4?發(fā)送電子郵件

---- 使用MAPISendMail發(fā)送電子郵件,其聲明如下:

ULONG FAR PASCAL MAPISendMail (LHANDLE lhSession,

ULONG ulUIParam, lpMapiMessage lpMessage,

FLAGS flFlags, ULONG ulReserved )

---- 其中,flFlags的允許值為MAPI_DIALOG、MAPI_LOGON_UI和MAPI_NEW_SESSION,其意義與前幾個函數(shù)中同名標識意義相同。

程序示例:

?

lResult = lpfnMAPISendMail(0, 0, &m_message, 0, 0);

?

3-3-5?釋放內(nèi)存

程序示例:

lpfnMAPIFreeBuffer(m_message.lpRecips);

四、小結

---- 本文比較具體的介紹并演示了編寫一個電子郵件程序的核心部分,如果讀者要編寫電子郵件程序,還需要進行的處理:

---- 1. 加上錯誤處理代碼。受篇幅限制,本文的程序示例中只有兩處為錯誤處理留空,比較它們的異同。電子郵件程序是非常容易出錯的,因此除這兩處外要在主要函數(shù)調用完成后都加上錯誤處理,或使用try throw catch塊處理例外。

---- 2. 加上UI處理。

---- 另外,本文所闡述的方法比較簡單易行,事實上,有關電子郵件的程序遠比這復雜得多,因此讀者若需要編寫一個功能強大的電子郵件程序,需要精通MAPI和 SMTP/POP3等協(xié)議;如果讀者要編寫一個電子郵件服務器,那么不妨在精通MAPI和SMTP/POP3之后,閱讀一些有關Exchange Server的資料

總結

以上是生活随笔為你收集整理的利用MAPI实现邮件收发(VC++)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。