mapi java_使用 MAPI 实现邮件发送
使用 MAPI 實現郵件發送
原 作:deltacat
創 建:2004.09.16
最后更新:2004.11.01
版權聲明:作者保留版權。轉載時敬請保持文檔及說明的完整性。
關鍵字: Visual C++ 郵件發送 Simple MAPI
一、問題提出
我們經常需要在自己的應用程序中添加郵件支持,主要是發送郵件。目前,常用的方法有調用外部程序,直接對SMTP協議編程,或者使用 MAPI 接口。MAPI 是微軟提供的一套用于郵件收發的接口。打開 MSDN Library,你可以在 Messaging and Collaboration Services 下面找到它。
MAPI 使用比較復雜,于是微軟提供了幾個比較簡單的解決方案,這里包括 CMC(Common Messaging Calls)和 Simple MAPI。
本文主要闡述使用 Simple MAPI 進行開發一個簡單的,用于發送一個帶附件的郵件的功能實現。文章后面有一小塊簡單講述了使用完整 MAPI 的開發,出于某些原因,并不推薦使用,如果需要更復雜的功能,我認為還是老老實實封裝SMTP和POP3比較好。
二、Simple MAPI 介紹
Simple MAPI 包括一組很容易使用的函數以及相關的數據結構,可以在C/C++、VB等多種語言中使用。本文是基于VC設計的。
實現一個完整的郵件發送過程,實際上只需要一個函數“MAPISendMail()”,完整函數表及相關介紹參查閱MSDN Library->Platform SDK->Messaging and Collaboration Services。
MAPI 與郵件系統關系密切,要能夠使用MAPI的功能,系統必須安裝有支持 MAPI 的郵件系統,比如Outlook、Outlook Express、Eudora、Netscape等. 在這里不得不提一下,使用非常廣泛的 FoxMail (5.0版本)似乎并不支持 MAPI,不過并沒有深入研究,如果有哪位高手發現實際上是支持的,麻煩告知我如何做。
Windows提供了一個文件 MAPI.H,包含所有的相關數據類型的定義。
三、功能的設計
我需要實現如下功能:可定制一封郵件,包括至少一個收件人,可選項目有標題、正文、若干抄送人、密件抄送人、附件。能夠根據需要選擇自動發送(無用戶干預),或彈出郵件編寫窗口。
為了便于使用和擴展,我用了一個class來實現。
1、MAPI庫的初始化
包括兩個步驟:裝載MAPI庫、得到函數入口地址。
//-------------------------------------------------------------------------------------
m_hLibrary = ::LoadLibrary(_T("MAPI32.DLL"));
if(NULL == m_hLibrary)
{
return ::GetLastError();
}
// LPMAPISENDMAIL 等均定義在
m_lpfnMAPISendMail = (LPMAPISENDMAIL)::GetProcAddress(m_hLibrary, _T("MAPISendMail"));
// 可以根據需要添加其他函數入口。我的做法是用了一個 InitMapi() 函數,一次性將所有函數入口得出,作為類的成員變量保存。隨時可以使用
//-------------------------------------------------------------------------------------
2、發送郵件 MAPISendMail()
發送郵件功能就是對MAPISendMail()的封裝。下面解釋這個API函數的參數定義。
ULONG FAR PASCAL MAPISendMail(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage, FLAGS flFlags, ULONG ulReserved);
ulUIParam 可以為 0,如果設置了 MAPI_DIALOG 標志,則最好傳給它父窗口句柄。
lhSession和ulReserved這兩個參數,簡單地設置為0就可以了。
flFlags有三個有效位,分別是 MAPI_DIALOG,MAPI_LOGON_UI,MAPI_NEW_SESSION。如果希望程序彈出一個標準的郵件撰寫對話框,請設置 MAPI_DIALOG,建議不要設置 MAPI_LOGON_UI 和 MAPI_NEW_SESSION。
重點是 lpMessage 這個參數,它指向一個MapiMessage類型的結構,詳細地定義了一個郵件的全部信息。
3、結構 MapiMessage
使用時首先定義一個MapiMessage類型的變量,將其清零。現在我們只要簡單地設定lpszSubject(標題)、lpszNoteText(正文)、lpOriginator(發件人)、nRecipCount(收件人計數,包含TO、CC、GCC),lpRecips(一個包含全部收件人的數組),nFileCount(附件計數)、lpFiles(包含每個附件信息的數組)。
nRecipCount 和 nFileCount 的值一定要與實際的收件人和附件數目相符。
4、結構 MapiRecipDesc
必須設置 ulRecipClass、lpszName、lpszAddress
5、結構 MapiFileDesc
必須設置的有 lpszPathName、nPosiotion 兩個參數
這里有個地方需要特別注意。我在實際編碼過程中,有幾次 Outlook 不能正確彈出窗口(自動發送也不行),但是同樣的過程,將郵件客戶設為 OutlookExpress 就沒有問題。十分頭痛。經過反復檢查,發現 nPosiotion 這個參數十分重要。它指示附件在郵件中的位置。
對于一些郵件客戶端,比如OutlookExpress,也許忽略了這個參數,由客戶端自動安排。所以沒有問題。對于另一些客戶端,比如Outlook,總是按照這個值的指示來安排的。如果附件數多于一個,這個值如果相同,那么就會造成錯誤。但是自行計算挺麻煩而且沒什么意義。解決的方法是,將其設為 -1,指示客戶軟件自行安排。:)
四、如何工作?
MAPISendMail() 會調用系統默認的郵件客戶程序來發送郵件。對于彈出編輯窗的方式,它的行為和另一個函數? MAPISendDocuments() 差不多,但是可以定制標題、收件人等等。而 MAPISendDocuments() 只是簡單地準備一個空白的郵件(包含附件),有關 MAPISendDocuments() 的介紹參見 MSDN。
對于自動發送。需要在 Outlook Express 的安全設置中,取消“當有其他應用程序試圖發送郵件時警告”這個選項。對于 Outlook,似乎使用 Simple MAPI 還沒有禁止安全警告的方法。
我設計的類包括三個接口函數,Send(), AddFiles(), AddRecips(),其中只有 Send() 是必須的。使用時聲明一個對象,然后就直接調用 Send() 函數發送郵件。兩個 Add 函數只要根據需要在 Send() 之前調用即可。
五、遺留問題
我的開發環境是 Windows Xp Sp2 CHS,有如下幾個問題,希望有高手可以解決。
1、自動發送時的警告問題。使用 Simple MAPI 能否解決?
2、默認Outlook Express為系統郵件客戶端,可以立即發送,如果是Outlook,是先放到Outlook的發送隊列了,這時如果Outlook未運行,就一直不會發送。怎樣可以保證無論郵件客戶軟件是否在運行,我的程序都可以立即將郵件發送出去呢?
3、對于默認是“Hotmail”的情況,只有以 @hotmail.com 結尾的帳號可以正常發送,而 @msn.com 的則不行。同時,在發送時,hotmail會將硬盤上的附件改名(末尾添加“^”符號)并將文件屬性改為只讀,不過如果它正常上傳了附件,會將文件復原。
六、使用 MAPI
之所以使用 MAPI,起初是為了取得系統的地址本以及結局上面第五節的問題2。
MAPI 相對于 Simple MAPI 要復雜的多。具體的使用方法可以參考 MSDN 文檔“Handling an Outgoing Message”、“Handling the Address Book”以及“Sending or Receiving a Message on Demand”。這里只對幾個關鍵的問題加以說明。
1、僅 Microsoft Outloook 比較好地支持了 MAPI,包括 Microsoft Outlook Express 均不支持 MAPI 調用。
2、MAPI 看似復雜,實際上,他的幾乎所有數據存儲和訪問,都是一個關鍵的接口:IMAPITable。也就是說,所有的數據存儲都是類似表的結構。搞清楚了這個,再編碼就很順了,不管是發送接收郵件還是操作地址本,存取數據流程都是搞表格。:P
3、上面的問題2仍然不能解決。根據“Sending or Receiving a Message on Demand”的說明,關鍵的是 FlushQueues() 函數,但是我嘗試了各種方法,均無法使它生效。若干天對自己的痛苦反思之后,終于懷疑微軟有問題。于是我在網上翻出了一篇問答,中間有這么一段話:
“The IMAPIStatus::FlushQueues method appears not to work at all any more. Call it and you'll get a successful return code but nothing happens as a result. ” --Pete Maclean.
于是我徹底放棄。:(
七、結束語
本文是在給應用程序中添加郵件發送功能的心得。過程中遇到了很多問題,將他寫出來,主要是給自己一個記錄,也是我第一次將自己的編程過程整理成文檔。
若本文還能幫到有同樣需要的朋友,會令我很開心。也希望有這方面經驗的朋友可以解決我的遺留問題。
歡迎發送郵件至 catking@163.com 共同探討編程中的各種問題,分享樂趣。
總結
以上是生活随笔為你收集整理的mapi java_使用 MAPI 实现邮件发送的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Geforce 错误代码 ERROR C
- 下一篇: 云酷科技UWB人员定位解决方案介绍
