Как отправить почту с помощью MAPI?

#c #windows #winapi #email #mapi

#c #Windows #winapi #Адрес электронной почты #mapi

Вопрос:

Я хочу отправить электронное письмо с помощью почтового клиента на компьютере пользователя с Windows. Насколько я могу судить по сети, MAPI — это правильный путь. Однако, прочитав документацию MSDN, я обнаружил, что MAPI довольно обширен, без примеров исходного кода. И мне не нужны 99% функций, я просто хочу отправить электронное письмо. Как мне это сделать?

Я нашел примеры здесь, на SO и в Интернете, но они, похоже, полагаются на то, что называется Simple MAPI, который Microsoft, по-видимому, перечислила как устаревший: «Использование Simple MAPI не рекомендуется. Он может быть изменен или недоступен в последующих версиях Windows «. Поэтому я не хочу использовать эти функции.

Я нашел здесь очень хороший пример, но, к сожалению, он предназначен для Windows CE и не полностью совместим с Win32 API. Мне удалось реализовать код из этой ссылки, пока он не попал туда, где он пытается открыть папку черновиков, параметры для GetProps несовместимы. Кто-нибудь знает, где я могу найти аналогичный пример кода для ПК? Предпочтительнее C .

Комментарии:

1. Полный MAPI присутствует только на компьютере с Windows, если у вас установлен Outlook или другой клиент MAPI. Windows поставляется только с простым MAPI. Если вы знаете, что у вас установлен Outlook, почему бы не использовать API Outlook для отправки электронной почты?

2. Идея состоит в том, чтобы использовать любой клиент MAPI, который у них есть, я бы предпочел не заставлять людей использовать определенный почтовый клиент. Но из любопытства, что именно представляют собой API Outlook? Это VBA или что-то еще?

3. Если вы не хотите заставлять пользователя использовать определенный почтовый клиент, вы, вероятно, застряли с простым mapi. Это не сработает, если они используют веб-почту, но большинство почтовых клиентов поддерживают простой MAPI. Проверьте здесь: msdn.microsoft.com/en-us/library/gg608200.aspx для получения дополнительной информации об API Outlook.

4. Что касается автоматизации Outlook, это проблема с точки зрения тестирования для поддержки более старых версий. Это нормально, если вы можете настроить таргетинг на одну версию.

Ответ №1:

Я решил это самостоятельно, с помощью различных интернет-источников.

Официальная документация MSDN

MAPIEx: расширенная оболочка MAPI

Как только код будет должным образом протестирован и задокументирован, я постараюсь опубликовать его здесь для дальнейшего использования.

Комментарии:

1. @DougN Да, сейчас он запущен и запущен в производственном коде. К сожалению, теперь это корпоративная собственность, поэтому я не могу поделиться ею целиком. Кроме того, он настроен для конкретного приложения, поэтому я не уверен, какое значение он будет иметь для других. Однако я рад помочь с фрагментами и подсказками, если кто-то еще столкнется с этим. Я все еще новичок в этом, поскольку я обычно работаю со встроенными системами, далеко от MAPI 🙂

Ответ №2:

См. раздел Отправка электронной почты с помощью MAPI — COM DLL

[Править / править код]

Я использовал MAPI один раз, и я опубликую код. Я не уверен, что это то, что вы ищете. Это отправляет сообщение с необязательно прикрепленными файлами (но без тела).

Заголовок:

 #pragma once

class MailSender  
{
public:
    MailSender();
    ~MailSender();

    void AddFile(LPCTSTR path, LPCTSTR name = NULL);
    bool Send(HWND hWndParent, LPCTSTR szSubject = NULL);

private:
    struct attachment { tstring path, name; };
    vector<attachment> m_Files;
    HMODULE m_hLib;
};
  

Cpp:

 #include "stdafx.h"
#include "MySendMail.h"
#include <mapi.h>

MailSender::MailSender()
{
    m_hLib = LoadLibrary(_T("MAPI32.DLL"));
}

MailSender::~MailSender()
{
    FreeLibrary(m_hLib);
}

void MailSender::AddFile( LPCTSTR file, LPCTSTR name )
{
    attachment a;
    a.path = file;
    if (!name)
        a.name = PathFindFileName(file);
    else
        a.name = name;
    m_Files.push_back(a);
}

bool MailSender::Send(HWND hWndParent, LPCTSTR szSubject)
{
    if (!m_hLib)
        return false;

    LPMAPISENDMAIL SendMail;
    SendMail = (LPMAPISENDMAIL) GetProcAddress(m_hLib, _T("MAPISendMail"));

    if (!SendMail)
        return false;

    vector<MapiFileDesc> filedesc;
    for (std::vector<attachment>::const_iterator ii = m_Files.begin(); ii!=m_Files.end(); ii  )
    {
        MapiFileDesc fileDesc;
        ZeroMemory(amp;fileDesc, sizeof(fileDesc));
        fileDesc.nPosition = (ULONG)-1;
        fileDesc.lpszPathName = (LPTSTR) ii->path.c_str();
        fileDesc.lpszFileName = (LPTSTR) ii->name.c_str();
        filedesc.push_back(fileDesc);
    }

    tstring subject;
    if (szSubject)
        subject = szSubject;
    else
    {
        for (std::vector<attachment>::const_iterator ii = m_Files.begin(); ii!=m_Files.end(); ii  )
        {
            subject  = ii->name.c_str();
            if (ii 1 != m_Files.end())
                subject  = ", ";
        }
    }

    MapiMessage message;
    ZeroMemory(amp;message, sizeof(message));
    message.lpszSubject = (LPTSTR) subject.c_str();
    message.nFileCount = filedesc.size();
    message.lpFiles = amp;filedesc[0];

    int nError = SendMail(0, (ULONG)hWndParent, amp;message, MAPI_LOGON_UI|MAPI_DIALOG, 0);

    if (nError != SUCCESS_SUCCESS amp;amp; nError != MAPI_USER_ABORT amp;amp; nError != MAPI_E_LOGIN_FAILURE)
        return false;

    return true;
}
  

Комментарии:

1. Я сам пару раз находил эту ссылку. Именно поэтому я написал, что простой MAPI нельзя использовать.

2. В чем разница между простым MAPI и полным MAPI?

3. Я новичок в этом, но, насколько я могу судить, простой MAPI прост, расширенный MAPI огромен. К сожалению, ваш код использует простой MAPI, поэтому он может устареть.

4. Дело не в этом. Я пишу программу, которая должна будет существовать более 10 лет.

5. Кстати, я где-то читал, что Simple MAPI не поддерживает HTML, так что, вероятно, об этом не может быть и речи. Я бы предпочел не создавать у пользователя впечатление, что электронное письмо было отправлено в 80-х годах, но пришло только сейчас 🙂