2012-03-30 116 views
3

在我看來,MAPI(Windows Mail API)與UTF8有問題(或者我做錯了什麼)。WIndows MAPI unicode問題

代碼示例:

HMODULE m_hLib = LoadLibraryA("MAPI32.DLL"); 
if (m_hLib == NULL) 
    return SEND_MAIL_CANCELED; 
LPMAPISENDMAIL SendMail; 
SendMail = (LPMAPISENDMAIL) GetProcAddress(m_hLib, "MAPISendMail"); 
if (!SendMail) 
    return; 

MapiFileDesc fileDesc; 
ZeroMemory(&fileDesc, sizeof(fileDesc)); 
fileDesc.nPosition = (ULONG) -1; 
fileDesc.lpszPathName = (LPSTR) filePath.toUtf8(); 
fileDesc.lpszFileName = (LPSTR) fileName.toUtf8(); 

MapiRecipDesc recipientData; 
ZeroMemory(&recipientData, sizeof(recipientData)); 
recipientData.lpszName = (LPSTR) recipient.toUtf8(); 
recipientData.ulRecipClass = MAPI_TO; 

MapiMessage message; 
ZeroMemory(&message, sizeof(message)); 
message.ulReserved = CP_UTF8; 
message.lpszSubject = (LPSTR) title.toUtf8(); 
message.nFileCount = 1; 
message.lpFiles = &fileDesc; 
message.nRecipCount = 1; 
message.lpRecips = &recipientData; 

int nError = SendMail(0, NULL, &message, MAPI_LOGON_UI | MAPI_DIALOG, 0); 

titlefilePathfileNamerecipient都是std::string秒。據我所知,UTF8兼容ASCII(也是NULL終止),所以它的字符串可以保存這些值沒有任何問題。

我轉換爲UTF8從這樣wstring的:

int requiredSize = WideCharToMultiByte(CP_UTF8, 0, data.c_str(), -1, 0, 0, 0, 0); 
if(requiredSize > 0) 
{ 
    std::vector<char> buffer(requiredSize); 
    WideCharToMultiByte(CP_UTF8, 0, data.c_str(), -1, &buffer[0], requiredSize, 0, 0); 
    this->container.append(buffer.begin(), buffer.end() - 1); 
} 

containerstd::string對象。

+0

這裏的實際問題是什麼?你期望發生什麼,你會得到什麼? – 2012-03-30 15:08:56

回答

8

MAPISendMail()不支持UTF-8,只支持Ansi。如果您需要發送Unicode數據,則必須在Windows 7及更早版本上使用MAPISendMailHelper(),或者在Windows 8及更高版本上使用MAPISendMailW()。這在MAPISendMail() documentation中有明確說明。

在附註中,當您將cchWideChar參數設置爲-1時,WideCharToMultiByte()包含空終止符。因此,您正在編碼並在您的container數據中包含空終止符。而應該設置cchWideChar字符串的實際長度完全避免空終止:

int requiredSize = WideCharToMultiByte(CP_UTF8, 0, data.c_str(), data.length(), 0, 0, 0, 0); 
if (requiredSize > 0) 
{ 
    std::vector<char> buffer(requiredSize); 
    WideCharToMultiByte(CP_UTF8, 0, data.c_str(), data.length(), &buffer[0], requiredSize, 0, 0); 
    container.append(buffer.begin(), buffer.end()); 
} 

http://msdn.microsoft.com/en-us/library/windows/desktop/dd296721.aspx它指出:「在Windows 7及更早版本:使用MAPISendMailHelper發送消息」,但在http://msdn.microsoft.com/en-us/library/windows/desktop/hh802867.aspx底部它聲稱「最低支持」是Windows 8.似乎是矛盾的信息,因此目前還不清楚MAPISendMailHelper是否真的適用於Windows 7及更早版本。

+1

MAPISendMailHelper在Windows 7 Service Pack 1上不存在。爲了檢索mapi32.dll的導出函數,我使用了depend.exe。 MAPIeMailHelper不被mapi32.dll導出。 – 2012-04-02 09:55:57

+4

MAPISendMailHelper不從任何dll導出;它作爲最新的Windows SDK中的代碼提供。它在文件「MapiUnicodeHelp.h」中。 – Swythan 2013-06-20 14:53:02

+0

在Win7和更低版本下,MAPISendMailHelper()只是將Unicode結構轉換爲ANSI結構,並調用MapiSendMail()而不是MapiSendMailW()。換句話說,它不支持Unicode MAPI,除非底層MAPI提供者確實(即,Win8 MAPI)。它的唯一目的是簡化客戶端代碼 - 您不必構建不同的結構並根據Windows版本調用不同的功能。 – chrisd 2014-05-04 16:33:30