用simple mapi 发送一个带附件的邮件
使用 MAPI 實(shí)現(xiàn)郵件發(fā)送
原 作:deltacat,修改中
最后更新:2004.09.16
版權(quán)聲明:隨意轉(zhuǎn)載,敬請(qǐng)保持文檔及說明完整性
關(guān)鍵字: VC 郵件發(fā)送 MAPI
一、簡述
實(shí)際上,本文的設(shè)計(jì),所使用的只是 Simple MAPI,可以把它看作是MAPI(Messaging Application Programming Interface)的一個(gè)子集。不過大多數(shù)時(shí)候,Simple MAPI提供的功能已經(jīng)足夠使用。本文闡述了一個(gè)簡單的,用于發(fā)送一個(gè)帶附件的郵件的功能實(shí)現(xiàn)。如果需要更復(fù)雜的功能,我認(rèn)為還是老老實(shí)實(shí)封裝SMTP和POP3比較好
??
二、Simple MAPI 介紹
Simple MAPI 包括一組很容易使用的函數(shù)以及相關(guān)的數(shù)據(jù)結(jié)構(gòu),可以在C/C++、VB等多種語言中使用。本文是基于VC設(shè)計(jì)的。
實(shí)現(xiàn)一個(gè)完整的郵件發(fā)送過程,只需要一個(gè)函數(shù)“MAPISendMail()”,完整函數(shù)表及相關(guān)介紹參查閱MSDN Library->Platform SDK->Messaging and Collaboration Services。
MAPI 與郵件系統(tǒng)關(guān)系密切,要能夠使用MAPI的功能,系統(tǒng)必須安裝有支持 MAPI 的郵件系統(tǒng),比如Outlook、Outlook Express、Eudora、Netscape等. 在這里不得不提一下,使用非常廣泛的 FoxMail (5.0版本)似乎并不支持 MAPI,不過并沒有深入研究,如果有哪位高手發(fā)現(xiàn)實(shí)際上是支持的,麻煩告知我如何做。
Windows提供了一個(gè)文件 MAPI.H,包含所有的相關(guān)數(shù)據(jù)類型的定義。
三、功能的設(shè)計(jì)
我需要實(shí)現(xiàn)如下功能:可定制一封郵件,包括至少一個(gè)收件人,可選項(xiàng)目有標(biāo)題、正文、若干抄送人、密件抄送人、附件。能夠根據(jù)需要選擇自動(dòng)發(fā)送(無用戶干預(yù)),或彈出郵件編寫窗口。
為了便于使用和擴(kuò)展,我用了一個(gè)class來實(shí)現(xiàn)。
1、MAPI庫的初始化
包括兩個(gè)步驟:裝載MAPI庫、得到函數(shù)入口地址。
?//-------------------------------------------------------------------------------------
?m_hLibrary = ::LoadLibrary(_T("MAPI32.DLL"));
?if(NULL == m_hLibrary)
?{
??return ::GetLastError();
?}
?// LPMAPISENDMAIL 等均定義在 <MAPI.H>
?m_lpfnMAPISendMail = (LPMAPISENDMAIL)::GetProcAddress(m_hLibrary, _T("MAPISendMail"));
?// 可以根據(jù)需要添加其他函數(shù)入口。我的做法是用了一個(gè) InitMapi() 函數(shù),一次性將所有函數(shù)入口得出,作為類的成員變量保存。隨時(shí)可以使用
?//-------------------------------------------------------------------------------------
2、發(fā)送郵件 MAPISendMail()
發(fā)送郵件功能就是對(duì)MAPISendMail()的封裝。下面解釋這個(gè)API函數(shù)的參數(shù)定義。
?ULONG FAR PASCAL MAPISendMail(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage, FLAGS flFlags, ULONG ulReserved);
lhSession、ulUIParam和ulReserved這三個(gè)參數(shù),簡單地設(shè)置為0就可以了。
flFlags有三個(gè)有效位,分別是 MAPI_DIALOG,MAPI_LOGON_UI,MAPI_NEW_SESSION。
重點(diǎn)是 lpMessage 這個(gè)參數(shù),它指向一個(gè)MapiMessage類型的結(jié)構(gòu),詳細(xì)地定義了一個(gè)郵件的全部信息。
3、結(jié)構(gòu) MapiMessage
使用時(shí)首先定義一個(gè)MapiMessage類型的變量,將其清零。現(xiàn)在我們只要簡單地設(shè)定lpszSubject(標(biāo)題)、lpszNoteText(正文)、lpOriginator(發(fā)件人)、nRecipCount(收件人計(jì)數(shù),包含TO、CC、GCC),lpRecips(一個(gè)包含全部收件人的數(shù)組),nFileCount(附件計(jì)數(shù))、lpFiles(包含每個(gè)附件信息的數(shù)組)。
nRecipCount 和 nFileCount 的值一定要與實(shí)際的收件人和附件數(shù)目相符。
4、結(jié)構(gòu) MapiRecipDesc
必須設(shè)置 ulRecipClass、lpszName、lpszAddress
5、結(jié)構(gòu) MapiFileDesc
必須設(shè)置的有l(wèi)pszPathName、nPosiotion兩個(gè)參數(shù)
這里有個(gè)地方需要特別注意。我在實(shí)際編碼過程中,有幾次 Outlook 不能正確彈出窗口(自動(dòng)發(fā)送也不行),但是同樣的過程,將郵件客戶設(shè)為 OutlookExpress 就沒有問題。但是十分頭痛。經(jīng)過發(fā)付查找,發(fā)現(xiàn) nPosiotion 這個(gè)參數(shù)十分重要。它指示附件在郵件中的位置。
對(duì)于一些郵件客戶端,比如OutlookExpress,也許忽略了這個(gè)參數(shù),由客戶端自動(dòng)安排。所以沒有問題。對(duì)于另一些客戶端,比如Outlook,總是按照這個(gè)值的指示來安排的。如果附件數(shù)多于一個(gè),這個(gè)值如果相同,那么就會(huì)造成錯(cuò)誤。但是自行計(jì)算挺麻煩而且沒什么意義。解決的方法是,將其設(shè)為 -1,指示客戶軟件自行安排。:)
四、如何工作?
MAPISendMail() 會(huì)調(diào)用系統(tǒng)默認(rèn)的郵件客戶程序來發(fā)送郵件。對(duì)于彈出編輯窗的方式,它的行為和另一個(gè)函數(shù)MAPISendMail()差不多,只是可以定制標(biāo)題、收件人等等,而MAPISendDocuments()只是簡單地準(zhǔn)備一個(gè)空白的郵件(包含附件),有關(guān)MAPISendDocuments()的介紹參見MSDN。
對(duì)于自動(dòng)發(fā)送。需要在Outlook Express的安全設(shè)置中,取消“當(dāng)有其他應(yīng)用程序試圖發(fā)送郵件時(shí)警告”這個(gè)選項(xiàng)。對(duì)于Outlook,還沒有找到方法。
我設(shè)計(jì)的類包括三個(gè)接口函數(shù),Send(), AddFiles(), AddRecips(),其中只有Send()是必須的。使用時(shí)聲明一個(gè)對(duì)象,然后就直接調(diào)用Send()函數(shù)發(fā)送郵件。兩個(gè)Add函數(shù)只要根據(jù)需要在Send()之前調(diào)用即可。
五、遺留問題
我的開發(fā)環(huán)境是 Windows Xp Sp2 CHS,有如下幾個(gè)問題,希望有高手可以解決。
1、自動(dòng)發(fā)送時(shí)的警告問題。
2、默認(rèn)Outlook Express為系統(tǒng)郵件客戶端,可以立即發(fā)送,如果是Outlook,是先放到Outlook的發(fā)送隊(duì)列了,這時(shí)如果Outlook未運(yùn)行,就一直不會(huì)發(fā)送。怎樣可以保證無論郵件客戶軟件是否在運(yùn)行,我的程序都可以立即將郵件發(fā)送出去呢?
3、對(duì)于默認(rèn)是“Hotmail”的情況,只有以 @hotmail.com 結(jié)尾的帳號(hào)可以正常發(fā)送,而 @msn.com 的則不行。同時(shí),在發(fā)送時(shí),hotmail會(huì)將硬盤上的附件改名(末尾添加“^”符號(hào))并將文件屬性改為只讀。
六、結(jié)束語
本文是在給應(yīng)用程序中添加郵件發(fā)送功能的心得。過程中遇到了很多問題,將他寫出來,主要是給自己一個(gè)記錄,也是我第一次將自己的編程過程整理成文檔。
若本文還能幫到有同樣需要的朋友,會(huì)令我很開心。也希望有這方面經(jīng)驗(yàn)的朋友可以解決我的遺留問題。
后篇?
?在VC中調(diào)用默認(rèn)的電子郵件程序發(fā)送郵件
很多時(shí)候大家需要在程序中發(fā)送郵件,自己編又太麻煩,怎么辦,呵呵,有現(xiàn)成的!?
1、想省事兒的,用ShellExecute函數(shù):?
ShellExecute(NULL,NULL,"mailto:email@263.net",NULL,NULL,SW_SHOW);?
2、如果想自己多處理一些東西的話,比如加上默認(rèn)的帳號(hào)、密碼、附件等,就可以調(diào)用系統(tǒng)的Mapi函數(shù)。具體的用法大家可以去查MSDN都是以MAPI開頭的,如MAPILogon、MAPISendMail等。下面這段代碼演示如何調(diào)用默認(rèn)的郵件程序發(fā)送郵件。?
#include "mapi.h"?
void CTestMapiDlg::OnSendMail()?
{?
HMODULE hMod = LoadLibrary("MAPI32.DLL");?
if (hMod == NULL)?
{?
AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD);?
return;?
}?
ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);?
(FARPROC&)lpfnSendMail = GetProcAddress(hMod, "MAPISendMail");?
if (lpfnSendMail == NULL)?
{?
AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL);?
return;?
}?
ASSERT(lpfnSendMail != NULL);?
TCHAR szPath[_MAX_PATH] = "C:\Winnt\setup.log";?
TCHAR szTitle[_MAX_PATH] = "setup.log";?
// prepare the file description (for the attachment)?
MapiFileDesc fileDesc;?
memset(&fileDesc, 0, sizeof(fileDesc));?
fileDesc.nPosition = (ULONG)-1;?
fileDesc.lpszPathName = szPath;?
fileDesc.lpszFileName = szTitle;?
// prepare the message (empty with 1 attachment)?
MapiMessage message;?
memset(&message, 0, sizeof(message));?
message.nFileCount = 1;?
message.lpFiles = &fileDesc;?
int nError = lpfnSendMail(0, 0,?
&message, MAPI_LOGON_UI¦MAPI_DIALOG, 0);?
// after returning from the MAPISendMail call, the window must?
// be re-enabled and focus returned to the frame to undo the workaround?
// done before the MAPI call.?
if (nError != SUCCESS_SUCCESS &&?
nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE)?
{?
AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);?
}?
}?
【轉(zhuǎn)】MAPI32::MAPISendMail以郵件附件形式發(fā)送文件
MAPISendMail
The MAPISendMail function sends a message, this function differs from the MAPISendDocuments function in that it allows greater flexibility in message generation.
Header file:MAPI.H
ULONG FAR PASCAL MAPISendMail(
LHANDLE?lhSession,
?ULONG?ulUIParam,
lpMapiMessage?lpMessage,
?FLAGS?flFlags,
ULONG?ulReserved?)
Parameters
lhSession
[in] handle to a simple MAPI session or zero.?If the value of? the lhSession parameter is zero, MAPI logs on the user and creates a session that exists only for the duration of the call.?This temporary session can be an existing shared session or a new one. If necessary, the logon dialog box is displayed.
ulUIParam
[in] Parent window handle or?zero.indicating that if a dialog box is displayed, it is application modal. If the ulUIParam contains a parent window handle, it is of type HWND (cast TO A ULONG).?If no dialog box is displayed during the call, ulUIParam is ignored.
lpMessage
[in] pointer to a MapiMessage structure containing the message to be sent.?If the MAPI_DIALOG flag is not set, the nRecipCount and lpRecips members must be valid for sucessful message delivery. Client application can set the flFlags member to MAPI_RECEIPT_REQUESTED to request a read report.?All other members are ignored and unused pointers should be NULL.
flFlags
[in] bitmark of option flags. The following flags can be set:
MAPI_DIALOG
A dialog box should be displayed to prompt the user for recipients and other sending options. When MAPI_DIALOG is not set, at least one recipient must be specified.
MAPI_LOGON_UI
A dialog box should be displayed to prompt the user to log on if required. When the MAPI_LOGON_UI is not set, the client application does not display a logon dialog box and returns an error value if the user is not logged on. MAPISendMail ignores this flag if the lpszMessageID parameter is empty.
MAPI_NEW_SEEEION
An attempt should be made to create a new session rather that acquire the environment's shared session. If the MAPI_SESSION flag is not set, MAPISendMail uses an existing share session.
ulReserved
Reserved; must be zero.
Return Values
MAPI_E_AMBIGUOUS_RECIPIENTRemarks
The MAPISendMail function sends a standard message, with or without any user interface. The profile must be configured so that MAPISendMail can open the default service paroviders without requiring user interface. However, if the flFlags parameter is set to MAPI_NEW_SESSION, disallowing the use of a shared session, and the profile requires a passsword, MAPI_LONON_UI must be set or? the function will fall. Client application can avoid this situation by using an explicit profile without a password or by using the default profile without a password.
Client application can provide a full or partial of recipient names, subject text,file attachments,or message text. If any information is missing, MAPISendMail can prompt the user for it. If no information is missing, either the message can be sent as if or the user can be prompted to verify the information, changing values if necessary.
A successful return form MAPISendMail does not necessarily imply recipient validation. The message might not have been sent to all recipients. Depending on the transport provider, recipient validation can be a lengthy process.
A NULL value for the lpszSubject member of the MapiMessage structure pointed to by the lpMessage parameter indicates that there is not text for the subject of the message.
A NULL value for the lpszNoteText member indicate that there is no message text. Some client application can truncate subject lines that are too long or contain carriage returns, line feeds, or form feeds.
Each paragraph should be terminated with a CR(OXOD), and LF(0X0a), or a CRLF(0X0D0A). MAPISendMail wraps lines as appropriate. If the text exceeds system limits, the function returns the MAPI_E_TEXT_TOO_LARGE values.
The lpszMessageType member of the MapiMessage structure pointed by lpMessage is used only by non_IPM applications. Applications that handle IPM message can set it to NULL or have it point to an empty string.
The number of attachments per message of the MapiMessage structure can be limited in some messaging systems. If the limit is exceeded, the MAPI_E_TOO_MANY_FILES value if returned. If no files are specified, a pointer value of NULL should be assigned to the files do not affect the contents of the message. The files must be closed when they are copied. Do not attempt to display attachments outside the range of the message text.
Some messaging systems can limit the number of recipients per message. A pointer value of NUL? for the lpRecipts member in the MapiMessage structure pointed by the lpMessage indicates no recipients. If the client application passes a non-NUll value indicating a number of recipients exceeding the system limit, MAPISendMail returns the MAPI_E_TOO_MANY_RECIPIENTS value. If the value of the nRecipCount member in the MapiMessage structure is 0, the MAPI_DAILOG flag must be present in the call to MAPISendMail.
Note that the lpRecips member in the MapiMessage structure can include either an entry identifier, the recipient's name, and address, or a name and address pair. The following table show how MAPISendMail handles the variety of information that can be specified:
| Information | Action |
| entry identifier | No name resolution; the name and address are ignored. |
| name | Name resolved using the Simple MAPI resolution rules. |
| address | No name resolution; address is used for both message delivery and for displaying the recipient name. |
| name and address | No name resolution; name used only for displaying the recipient name. |
Client applications that send messages to custom recipients can avoid name resolution. Such clients should set thelpszAddress?member of the?MapiRecipDesc?structure pointed to by the?lpRecips?member of the?MapiMessage?structure pointed to by the?lpMessage?parameter to the custom address.
MAPISendMail?does not require an originator-type recipient to send a message.
MapiMessage (simple MAPI)
A MapiMessage structure contains information about a message.
Header file: MAPI.H
typedef struct {
ULONG ulReserved;
LPTSTR lpszSubject;
LPTSTR lpszNoteText;
LPTSTR lpszMessageType;
LPTSTR lpszDateReceived;
LPTSTR lpszConversationID;
FLAGS flFlags;
lpMapiRecipDesc lpOriginator;
ULONG nRecipCount;
lpMapiRecipDesc lpRecips;
ULONG nFileCount;
lpMapiFileDesc lpFiles;
}MapiMessage, FAR *lpMapiMessage;
Members
ulReserved
Reserved,?must be zero.
lpszSubject
pointer to the text string describing the message subject, typically limited to 256 characters or less. If this member is empty or NULL, the user has not entered subject text.
lpszNoteText
pointer to a string containing the message text. If this member is empty or NULL, there is no message text.
lpszMessageType
Pointer to a string indicating a non-IPM type of message. Client application can select message types for their non_IPM messages.?Clients that only support IPM messages?can ignore the lpszMessageType member when reading messages andset it to empty or NULLwhen sending messages.
lpszDateReceived
Pointer to a string indicating the date when the message was received. The format is YYYY/MM/DD HH:MM, using a 24-hour clock.
lpszConversationID
pointer to a string identifying the conversation thread to which the message belongs. some messaging system can ignore and not return this member.
flFlagsBitmark of message status flags. The following flags can be set:
MAPI_RECEIPT_REQUESTEDlpOriginatorPointer to a?MapiRecipDescstructure containing information about the sender of the message.nRecipCountThe number of message recipient structures in the array pointed to by the?lpRecipsmember. A value of zero indicates no recipients are included.lpRecipsPointer to an array of?MapiRecipDescstructures, each containing information about a message recipient.nFileCountThe number of structures describing file attachments in the array pointed to by the?lpFiles?member. A value of zero indicates no file attachments are included.lpFilesPointer to an array ofMapiFileDesc?structures, each containing information about a file attachment.
?
MapiFileDesc (simple MAPI)
A MapiFileDesc structure contains information about a file containing a message attachment stored as a temporary file. That file can contain a static OLE object, an embedded OLE object, and embedded message, and other types of files.
typedef struct {
ULONG ulReserved;
ULONG flFlags;
ULONG nPosition;
LPTSTR lpszPathName;
LPTSTR lpszFileName;
LPVOID lpFileType;
} MapiFileDesc, FAR *lpMapiFileDesc;
Members
ulReservedIf neither flag is set, the attachment is treated as a data file.
?
?
Remarks
Simple MAPI works with three kinds of embedded attachments:
- Data file attachments
- Editable OLE object file attachments
- Static OLE object file attachments
Data file attachments are simply data files. OLE object file attachments are OLE objects that are displayed in the message text. If the OLE attachment is editable, the recipient can double-click it and its source application will be started to handle the edit session. If the OLE attachment is static, the object cannot be edited. The flag set in the?flFlags?member of the?MapiFileDesc?structure determines the kind of a particular attachment. Embedded messages can be identified by a .MSG extension in the?lpszFileNamemember.
OLE object files are file representations of OLE object streams. The client application can recreate an OLE object from the file by calling the OLE functionOleLoadFromStreamwith an OLESTREAM object that reads the file contents. If an OLE file attachment is included in an outbound message, the OLE object stream should be written directly to the file used as the attachment.
When using the?MapiFileDesc?member?nPosition, the client application should not place two attachments in the same location. Client applications might not display file attachments at positions beyond the end of the message text.
Example
/********************************************************************* * 函數(shù)名稱:CSendEMailDlg::OnSendMapi * 說明: 調(diào)用MAPI函數(shù)發(fā)送郵件。摘自 VC98/MFC/SRC/DOCMAPI.CPP * 作者: Geng * 時(shí)間 : 2003-04-22 20:08:30 *********************************************************************//* m_list 為ListControl的變量 ,程序?qū)istControl中列出的所有item以附近形式發(fā)送,如果你的系統(tǒng)安裝了Outlook發(fā)送郵件器,那么會(huì)啟動(dòng)它來作為郵件發(fā)送默認(rèn)程序*//* code 為非Unicode版本 */ void CSendEMailDlg::OnSendMapi() {UpdateData(true); //加載MAPI32.DLL動(dòng)態(tài)庫 HMODULE hMod = LoadLibrary(_T("MAPI32.DLL")); if (hMod == NULL) //加載動(dòng)態(tài)庫失敗 {AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD);return;} //獲取發(fā)送郵件的函數(shù)地址 ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);(FARPROC&)lpfnSendMail = GetProcAddress(hMod, "MAPISendMail"); if (lpfnSendMail == NULL){AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL);return;} int nFileCount = m_list.GetCount(); //有多少個(gè)附件需要發(fā)送 //分配內(nèi)存保存附件信息 不能使用靜態(tài)數(shù)組,因?yàn)椴恢酪l(fā)送附件的個(gè)數(shù) MapiFileDesc* pFileDesc = (MapiFileDesc*)malloc(sizeof(MapiFileDesc) * nFileCount);memset(pFileDesc,0,sizeof(MapiFileDesc) * nFileCount); //分配內(nèi)存保存附件文件路徑 TCHAR* pTchPath = (TCHAR*)malloc(MAX_PATH * nFileCount); CString szText;for(int i = 0;i < nFileCount;i++){char* p = pTchPath + MAX_PATH * i;m_list.GetText(i,szText);strcpy(p,szText);(pFileDesc + i)->nPosition = (ULONG)-1;(pFileDesc + i)->lpszPathName = p;(pFileDesc + i)->lpszFileName = p;} //收件人結(jié)構(gòu)信息 /*MapiRecipDesc recip;memset(&recip,0,sizeof(MapiRecipDesc));recip.lpszAddress = m_szEmailMAPI.GetBuffer(0);recip.ulRecipClass = MAPI_TO;*/ //郵件結(jié)構(gòu)信息 MapiMessage message;memset(&message, 0, sizeof(message));message.nFileCount = nFileCount; //文件個(gè)數(shù) message.lpFiles = pFileDesc; //文件信息//message.nRecipCount = 0; //收件人個(gè)數(shù)//message.lpRecips = NULL;//&recip; //收件人//message.lpszSubject = NULL; //m_szSubject.GetBuffer(0); //主題//message.lpszNoteText= NULL;//m_szText.GetBuffer(0); //正文內(nèi)容 //保存本程序窗口指針,因?yàn)榘l(fā)完郵件后要返回本程序的窗口 CWnd* pParentWnd = CWnd::GetSafeOwner(NULL, NULL); //發(fā)送郵件 int nError = lpfnSendMail(0, 0,&message, MAPI_LOGON_UI|MAPI_DIALOG, 0); if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE){AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);} //返回程序 pParentWnd->SetActiveWindow(); //不要忘了釋放分配的內(nèi)存 free(pFileDesc);free(pTchPath);FreeLibrary(hMod); } //imapi.h================================ /* * $Header:$ * * $Log:$ */ //#include class CIMapi { public: CIMapi(); ~CIMapi(); enum errorCodes { IMAPI_SUCCESS = 0, IMAPI_LOADFAILED, IMAPI_INVALIDDLL, IMAPI_FAILTO, IMAPI_FAILCC, IMAPI_FAILATTACH }; // Attributes void Subject(LPCTSTR subject) { m_message.lpszSubject = (LPTSTR) subject; } void Text(LPCTSTR text) { m_text = text; } UINT Error(); void From(LPCTSTR from) { m_from.lpszName = (LPTSTR) from; } static BOOL HasEmail(); // Operations BOOL To(LPCTSTR recip); BOOL Cc(LPCTSTR recip); BOOL Attach(LPCTSTR path, LPCTSTR name = NULL); BOOL Send(ULONG flags = 0); private: BOOL AllocNewTo(); MapiMessage m_message; MapiRecipDesc m_from; UINT m_error; CString m_text; ULONG (PASCAL *m_lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG); static HINSTANCE m_hInstMail; static BOOL m_isMailAvail; }; //imapi.cpp================================================== /* * $Header:$ * * $Log:$ */ #include "stdafx.h" #include <MAPI.H> #include "imapi.h" HINSTANCE CIMapi::m_hInstMail = (HINSTANCE) NULL; BOOL CIMapi::m_isMailAvail = (BOOL) -1; CIMapi::CIMapi() { m_error = 0; // Initially error free memset(&m_message, 0, sizeof(MapiMessage)); memset(&m_from, 0, sizeof(MapiRecipDesc)); m_message.lpOriginator = &m_from; m_from.ulRecipClass = MAPI_ORIG; if (m_hInstMail == (HINSTANCE) NULL) // Load the MAPI dll m_hInstMail = ::LoadLibraryA("MAPI32.DLL"); if (m_hInstMail == (HINSTANCE) NULL) { AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD); m_error = IMAPI_LOADFAILED; return; } ASSERT(m_hInstMail != (HINSTANCE) NULL); // Now get the pointer to the send function (FARPROC&) m_lpfnSendMail = GetProcAddress(m_hInstMail, "MAPISendMail"); if (NULL == m_lpfnSendMail) { AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL); m_error = IMAPI_INVALIDDLL; return; } ASSERT(m_lpfnSendMail != NULL); } CIMapi::~CIMapi() { if (m_hInstMail != (HINSTANCE) NULL) ::FreeLibrary(m_hInstMail); m_hInstMail = (HINSTANCE) NULL; free(m_message.lpFiles); free(m_message.lpRecips); } BOOL CIMapi::HasEmail() { if (m_isMailAvail == (BOOL) -1) m_isMailAvail = ::GetProfileInt(_T("MAIL"), _T("MAPI"), 0) != 0 && SearchPath(NULL, _T("MAPI32.DLL"), NULL, 0, NULL, NULL) != 0; return m_isMailAvail; } UINT CIMapi::Error() { UINT temp = m_error; m_error = IMAPI_SUCCESS; return temp; } BOOL CIMapi::AllocNewTo() { // Allocate a new MapiRecipDesc structure and initialise it to all zeros m_message.lpRecips = (MapiRecipDesc *) realloc(m_message.lpRecips, (m_message.nRecipCount + 1) * sizeof(MapiRecipDesc)); memset(&m_message.lpRecips[m_message.nRecipCount], 0, sizeof(MapiRecipDesc)); ASSERT(m_message.lpRecips); return m_message.lpRecips != (MapiRecipDesc *) NULL; } BOOL CIMapi::To(LPCTSTR recip) { if (AllocNewTo()) { // We succeeded in allocating a new recipient record m_message.lpRecips[m_message.nRecipCount].lpszName = (LPTSTR) recip; m_message.lpRecips[m_message.nRecipCount].ulRecipClass = MAPI_TO; m_message.nRecipCount++; return TRUE; } m_error = IMAPI_FAILTO; return FALSE; } BOOL CIMapi::Cc(LPCTSTR recip) { if (AllocNewTo()) { // We succeeded in allocating a new recipient record m_message.lpRecips[m_message.nRecipCount].lpszName = (LPTSTR) recip; m_message.lpRecips[m_message.nRecipCount].ulRecipClass = MAPI_CC; m_message.nRecipCount++; return TRUE; } m_error = IMAPI_FAILCC; return FALSE; } BOOL CIMapi::Attach(LPCTSTR path, LPCTSTR name) { // Add a new attachment record m_message.lpFiles = (MapiFileDesc *) realloc(m_message.lpFiles, (m_message.nFileCount + 1) * sizeof(MapiFileDesc)); memset(&m_message.lpFiles[m_message.nFileCount], 0, sizeof(MapiFileDesc)); ASSERT(m_message.lpFiles); if (m_message.lpFiles == (MapiFileDesc *) NULL) { m_error = IMAPI_FAILATTACH; return FALSE; } m_message.lpFiles[m_message.nFileCount].lpszPathName = (LPTSTR) path; m_message.lpFiles[m_message.nFileCount].lpszFileName = (LPTSTR) name; m_message.nFileCount++; return TRUE; } BOOL CIMapi::Send(ULONG flags) { CWaitCursor wait; int offset = m_text.GetLength(); // Add 1 space per attachment at the end of the body text. m_text += CString(' ', m_message.nFileCount); // Set each attachment to replace one of the added spaces at the end of the body text. for (UINT i = 0; i < m_message.nFileCount; i++) m_message.lpFiles[i].nPosition = offset++; m_message.lpszNoteText = (LPTSTR) (LPCTSTR) m_text; // Set the body text // prepare for modal dialog box AfxGetApp()->EnableModeless(FALSE); HWND hWndTop; CWnd* pParentWnd = CWnd::GetSafeOwner(NULL, &hWndTop); // some extra precautions are required to use MAPISendMail as it // tends to enable the parent window in between dialogs (after // the login dialog, but before the send note dialog). pParentWnd->SetCapture(); ::SetFocus(NULL); pParentWnd->m_nFlags |= WF_STAYDISABLED; int nError = m_lpfnSendMail(0, (ULONG) pParentWnd->GetSafeHwnd(), &m_message, MAPI_LOGON_UI | flags, 0); // after returning from the MAPISendMail call, the window must // be re-enabled and focus returned to the frame to undo the workaround // done before the MAPI call. ::ReleaseCapture(); pParentWnd->m_nFlags &= ~WF_STAYDISABLED; pParentWnd->EnableWindow(TRUE); ::SetActiveWindow(NULL); pParentWnd->SetActiveWindow(); pParentWnd->SetFocus(); if (hWndTop != NULL) ::EnableWindow(hWndTop, TRUE); AfxGetApp()->EnableModeless(TRUE); if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE) { AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND); return FALSE; } return TRUE; } //在你的dlg.cpp #include imapi.h //你的dlg.cpp 的按鈕事件=================================== void 你的DLG::OnBnClickedButton1() { CIMapi mail;mail.To("Tofirst@qq.com"); mail.To("Tosecond@qq.com");mail.Cc("CCfirst@qq.com"); mail.From("aa@qq.com"); mail.Subject("Test Email"); // mail.Attach("somefilename"); // // mail.Attach("someotherfile", "different_name_for_recipient"); mail.Text("Body text for this email"); mail.Send(); }總結(jié)
以上是生活随笔為你收集整理的用simple mapi 发送一个带附件的邮件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式(11)代理模式The Prox
- 下一篇: 临床医学计算机思维的应用情况,【临床医学