Проблема Unicode в Windows MAPI - PullRequest
3 голосов
/ 30 марта 2012

Мне кажется, что MAPI (Windows Mail API) имеет проблемы с UTF8 (или, возможно, я что-то сделал не так).

Пример кода:

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);

title, filePath, fileName и recipient - все 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);
}

container - это объект std::string.

1 Ответ

8 голосов
/ 30 марта 2012

MAPISendMail() не поддерживает UTF-8, только Ansi. Если вам нужно отправить данные Unicode, вы должны использовать MAPISendMailHelper() в Windows 7 и более ранних версиях или MAPISendMailW() в Windows 8 и более поздних версиях. Это четко указано в MAPISendMail() документации .

Что касается примечания, WideCharToMultiByte() включает нулевой терминатор, когда для параметра cchWideChar установлено значение -1. Таким образом, вы кодируете и включаете этот нулевой терминатор в свои 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 и более ранних версий.

...