Win32,C ++:通过调用默认邮件客户端在Windows 10中发送电子邮件

时间:2017-12-04 17:58:37

标签: c++ email winapi windows-10

Stackoverflow中有很多帖子以及许多其他网站显示如何通过调用默认邮件客户端发送带附件的电子邮件。当你在Windows资源管理器中右键单击任何文件时,从上下文菜单中选择发送到 - >邮件收件人时,几乎一样。

我在网上找到的很多这些样本都使用MAPI,但它们都不起作用。还有一些示例使用ShellExecute并使用mailto:协议。后者适合我,但不是当我尝试发送附件时。附件根本不会显示在Outlook的“新邮件”窗口中。 MAPI示例再次无法使用附件。我得到了奇怪的错误,比如我是想允许还是拒绝。

如果Windows能够做到这一点,那意味着其他应用也应该能够做到这一点。有谁知道哪个API适用于Windows 10?

1 个答案:

答案 0 :(得分:0)

这是有效的代码。它与Qt的东西混合在一起,但Qt类后来在代码中转换为STL。我的代码之前没有工作的原因是因为我将lpszPathName设置为附件的路径,将lpszFileName设置为附件的文件名。必须将路径设置为包含文件名的完整路径,并且文件名应设置为我们希望显示为电子邮件客户端中附件名称的任何内容。它可能只是文件名,也可能是别的。

bool InvokeDefaultEmailClient(HWND hwndParent, const QStringList 
                             &attachmentFilenames, const QString &subject)
{
    HINSTANCE hInst = LoadLibraryW(L"mapi32.dll");
    if (!hInst) {
        return false;
    }

    ULONG(PASCAL *SendMail)(ULONG, ULONG_PTR, MapiMessageW*, FLAGS, ULONG);
    (FARPROC&)SendMail = GetProcAddress(hInst, "MAPISendMailW");

    if (!SendMail) {
        return false;
    }

    std::vector<std::wstring> attachmentFilenamesVector;
    for(int i=0; i<attachmentFilenames.size(); ++i) {
        QString filename = attachmentFilenames[i];
        attachmentFilenamesVector.push_back(filename.toStdWString());
    }

    QVector<MapiFileDescW> fileDescs;
    for (int i = 0; i < attachmentFilenamesVector.size(); ++i) {
        MapiFileDescW fileDesc;
        ZeroMemory(&fileDesc, sizeof(fileDesc));
        fileDesc.nPosition = (ULONG)-1;
        fileDesc.lpszPathName = (TCHAR*)attachmentFilenamesVector[i].c_str();
        fileDesc.lpszFileName = (TCHAR*)attachmentFilenamesVector[i].c_str();
        fileDescs.push_back(fileDesc);
    }

    MapiMessageW message;
    ZeroMemory(&message, sizeof(message));
    message.lpszSubject = (TCHAR*)subject.toStdString().c_str();
    message.nFileCount = fileDescs.size();
    message.lpFiles = fileDescs.data();

    int error = SendMail(0, (ULONG_PTR)hwndParent, &message, MAPI_LOGON_UI | MAPI_DIALOG, 0);

    if (error != SUCCESS_SUCCESS && error != MAPI_USER_ABORT && error != MAPI_E_LOGIN_FAILURE) {
        return false;
    }

    return true;
}