我正在使用Visual Studio 2008的简单MAPI接口从应用程序发送电子邮件和附件。适用于Thunderbird和Outlook 6,但Outlook 2013给了我各种各样的悲伤。
有两个关键问题:
1)电子邮件发送到Outlook的发件箱,但是当它发送时它会反弹(或者看起来像我认为这是内部的),并显示消息“您的电子邮件帐户都不能发送给此收件人”。
2)Outlook将显示“程序正在尝试代表您发送电子邮件”。
我想知道Outlook 2013是否需要比我提供的数据更多的数据,或者我是否正在做出一些谨慎的假设。
注意:这些测试是在三台不同的机器上 - 我的主要Win 10开发机器上的Thunderbird,XP虚拟机上的Outlook 6和另一台Windows 10机器上的Outlook 2013。
关于代码的注意事项:我使用CPtrArrays来存储调用函数传递的数据。您将在设置收件人时看到GetAt()。
谢谢!
MapiRecipDesc sender[1];
MapiRecipDesc recipient[50];
MapiFileDesc fileDesc[20];
sender[0].ulRecipClass = MAPI_ORIG;
sender[0].lpszAddress = "[email protected]";
sender[0].lpszName = "Me";
sender[0].lpEntryID = 0;
sender[0].ulEIDSize = 0;
sender[0].ulReserved = 0;
iToCount = 0;
iIndex = 0;
while (iIndex < m_paTo.GetCount()) {
recipient[iToCount].ulRecipClass = MAPI_TO;
recipient[iToCount].lpszAddress = (char *) m_paTo.GetAt(iToCount);
recipient[iToCount].lpszName = (char *) m_paTo.GetAt(iToCount);
recipient[iToCount].lpEntryID = 0;
recipient[iToCount].ulEIDSize = 0;
recipient[iToCount].ulReserved = 0;
iIndex++;
iToCount++;
}
iIndex = 0;
while (iIndex < m_paCC.GetCount()) {
recipient[iToCount].ulRecipClass = MAPI_CC;
recipient[iToCount].lpszAddress = (char *) m_paCC.GetAt(iIndex);
recipient[iToCount].lpszName = (char *) m_paCC.GetAt(iIndex);
recipient[iToCount].lpEntryID = 0;
recipient[iToCount].ulEIDSize = 0;
recipient[iToCount].ulReserved = 0;
iIndex++;
iToCount++;
}
iIndex = 0;
while (iIndex < m_paBCC.GetCount()) {
recipient[iToCount].ulRecipClass = MAPI_BCC;
recipient[iToCount].lpszAddress = (char *) m_paBCC.GetAt(iIndex);
recipient[iToCount].lpszName = (char *) m_paBCC.GetAt(iIndex);
recipient[iToCount].lpEntryID = 0;
recipient[iToCount].ulEIDSize = 0;
recipient[iToCount].ulReserved = 0;
iIndex++;
iToCount++;
}
iFileCount = 0;
iIndex = 0;
while (iIndex < m_paAttachments.GetCount()) {
fileDesc[iFileCount].flFlags = 0;
fileDesc[iFileCount].lpFileType = 0;
fileDesc[iFileCount].lpszFileName = (char *) m_paAttachments.GetAt(iIndex);
fileDesc[iFileCount].lpszPathName = (char *) m_paAttachments.GetAt(iIndex);
fileDesc[iFileCount].nPosition = -1;
fileDesc[iFileCount].ulReserved = 0;
iIndex++;
iFileCount++;
}
TCHAR szSubject[_MAX_PATH];
TCHAR szMessage[5001];
::StrCpy(szSubject, m_sSubject);
::StrCpy(szMessage, m_sMessage);
MapiMessage message;
::ZeroMemory(&message, sizeof(message));
message.lpszSubject = szSubject;
message.nRecipCount = iToCount;
message.lpRecips = recipient;
message.nFileCount = iFileCount;
message.lpFiles = fileDesc;
message.lpszNoteText = szMessage;
message.flFlags = MAPI_SENT | MAPI_UNREAD;
message.lpszConversationID = "123";
message.lpOriginator = sender;
//int nError = SendMail(0, (ULONG_PTR)hWndParent, &message, MAPI_LOGON_UI|MAPI_DIALOG, 0);
int nError = SendMail(0, (ULONG_PTR)hWndParent, &message, MAPI_LOGON_UI, 0);
if (nError != SUCCESS_SUCCESS &&
nError != MAPI_USER_ABORT &&
nError != MAPI_E_LOGIN_FAILURE) {
CString sMessage;
CString sTest = recipient[0].lpszAddress;
sMessage.Format("MapiMail:: SendMail Error code %d Recip count %d: first Recip: %s", nError, message.nRecipCount, sTest);
AfxMessageBox(sMessage);
lLog.WriteString(sMessage);
return false;
}
根据Barmak Shemirani的建议,我发表了自己的答案。如果其他人正在寻找这个信息,也许我可以通过在一个地方发布它来节省一些时间。
::StrCpy(szTo, "<[email protected]>");
recipient[iToCount].ulRecipClass = MAPI_TO;
recipient[iToCount].lpszAddress = 0;
recipient[iToCount].lpszName = szTo;
recipient[iToCount].lpEntryID = 0;
recipient[iToCount].ulEIDSize = 0;
recipient[iToCount].ulReserved = 0;
我已经使用Outlook 2013和2016以及Outlook 6,Thunderbird和EM Client对此进行了测试,他们对此感到满意。显然你可以把名字和PersonName <[email protected]>
,但我没有测试过。Computer\HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\x.0\Outlook\Security
.html
扩展名命名我的文件。
这有点侥幸 - 电子邮件客户端捡起它并在电子邮件正文中显示HTML。您的html文件仍然是附件,后跟任何其他附件。我已经使用Thunderbird,Outlook和EM Client进行了测试。我快速浏览了一个网络电子邮件阅读器,它没有显示html文本(尽管附件可供阅读)。