Simple MAPI это набор интерфейсов и функций, которые обеспечивают
доступ к почтовому транспорту и хранилищам данных (таких как адресные книги и сообщения).
Этот механизм позволяет принимать/отсылать почту из собственных приложений независимо от конкретного почтового клиента,
который будет использоваться.
Все приложения, поддерживающие simple MAPI, должны реализовать двенадцать функций и
предоставить три структуры разработчикам. Описание этих функций и список параметров заранее известен и
жестко определен.
MAPI является стандартом, который поддерживают многие почтовые клиенты Microsoft Windows.
В последних версиях и в TheBat! включена поддержка simple MAPI.
Функции и структуры находятся в библиотеке tbmapi.dll.
Если TheBat! установлен, как обработчик запросов simple MAPI по умолчанию, то
эта библиотека замещает системную mapi32.dll
Ниже приведен список функций и структур.
| Функция | Описание |
| MAPIAddress |
Вывод диалогового окна выбора адресатов |
| MAPIDeleteMail |
Удаление письма |
| MAPIDetails |
Показ диалогового окна со свойствами конкретного адресата из адресной книги TheBat!. Возможно менять эти свойства с записью
в адресную книгу. |
| MAPIFindNext |
Выбор "следующего" письма и папки Inbox |
| MAPIFreeBuffer |
Освобождение памяти, которая была распределена функциями MAPI |
| MAPILogoff |
Завершение сессии MAPI |
| MAPILogon |
Открытие очередной сессии MAPI |
| MAPIReadMail |
Чтение письма, которое было определено функцией MAPIFindNext |
| MAPIResolveName |
Так называемое "разрешение имени адресата" — поиск адреса по имени в адресных книгах. |
| MAPISaveMail |
Сохранение письма |
| MAPISendDocuments |
Создание письма с приаттаченными файлами |
| MAPISendMail |
Создание письма. |
| Структура | Описание |
| MapiFileDesc |
Информация о приаттаченном объекте. |
| MapiMessage |
Параметры и содержимое письма. |
| MapiRecipDesc |
Информация об адресате (получателе/отправителе сообщения) |
|
Подробное описание этих функций и их параметров смотрите в соответствующей литературе — MSDN (самое
полное и подробное руководство); справка по MAPI, например, есть в стандартной поставке Delphi, файл mapi.hlp.
В конце статьи приведен список материалов в сети по этой теме.
Данный материал не является еше одной справкой по simple MAPI, не претендует на абсолютную полноту изложения
материала, возможно упущены некоторые нюансы. Данный материал является лишь обобщением собственного опыта.
Я не ставила перед собой цель написать еще одну статью по simple MAPI, мне хотелось рассказать о
некоторых особенностях применения этих функций именно при работе с theBAT!, о тех нюансах, с которыми мне пришлось столкнуться.
Так как особенности функционирования
самого почтового клиента конечно же отражаются на реализации simple MAPI.
Выводится диалоговое окно с выбором адресата.
Игнорируются некоторые параметры: не учитывается сессия, невозможно изменить надписи в диалоговом окне,
не регулируется количество полей для заполнения(по идее это может быть набор из "TO", "CC" и "BCC").
Можно вызвать окно с уже заполненными адресатами.
Пример:
Var P : PULONG;
RecN : PMapiRecipDesc;
Rec : TMapiRecipDesc;
Begin
GetMem( RecN , SizeOf(Rec) );
Rec.lpszName:='';
Rec.lpszAddress:='info@id.ru';
Rec.ulEIDSize:=0;
Rec.lpEntryID:=nil;
Rec.ulReserved:=0;
Rec.ulRecipClass:=MAPI_BCC;
// Выбор инициализируется одним адресом в поле BCC
HResult:=MapiAddress(0 , 0 , nil , 0 , nil , 1 , Rec , 0 , 0 , P , RecN );
IF HResult = SUCCESS_SUCCESS Then
Begin
// Были выбраны адресаты
...
End;
...
MAPIFreeBuffer(RecN);
В итоге, если нажата кнопка [OK], то указатель RecN содержит адрес
на первый элемент типа TMapiRecipDesc из списка выбранных адресатов.
Вызывает окно свойств указанного адресата. Можно изменять свойства, все изменения будут сохранены в адресной книге.
В качестве уникального определителя служит первичный почтовый адрес. То есть нельзя найти
адресата только по имени. Это поле вообще игнорируется.
Пример:
Var Rec : TMapiRecipDesc;
Begin
Rec.lpszName:='';
Rec.lpszAddress:='info@id.ru';
Rec.ulEIDSize:=0;
Rec.lpEntryID:=nil;
Rec.ulReserved:=0;
Rec.ulRecipClass:=0;
Hresult:=MapiDetails( 0 , 0 , Rec , 0 , 0 );
Если указан несуществующий адресат, то возвращается значение
MAPI_E_UNKNOWN_RECIPIENT.
Если в разных адресных книгах есть один и тот же адресат, то будет выдано окно свойств для самой первой
найденной записи.
К сожалению нельзя получить доступ к свойствам групп. Хотя в MAPI существует такое понятие, как Personal
Distribution List (PDL) , то есть персональный список рассылки, не имеющий собственного адреса.
Ну а группа адресной книги TheBat! соответствует PDL, который является полноправным контейнером
адресной книги для MAPI.
Возвращает идентификатор очередного письма из папки Inbox.
Необходимо вызывать эту функцию перед вызовом MAPIReadMail.
Пример использования и особенности смотрите в опиаснии функции MAPIReadMail
Стоит напомнить, что интерфейс Simple MAPI осуществляет доступ только к
содержимому папки Inbox.
Необходимо вызывать эту функцию для освобождения памяти, отведенной под структуры, которые заполняются
системой почтового клиента.
Завершение сессии.
Открытие сессии работы с почтовой системой.
Если не использовать эту функцию и далее игнорировать параметр Session, то будет
осуществляться работа с тем почтовым ящиком, для которого в TheBat! помечен крыжик
"По умолчанию использовать этот ящик для mailto:". Если такого почтового ящика нет,
то при попытке отослать или прочитать письмо, будет возвращено значение MAPI_E_LOGIN_FAILURE
Если необходимо выбрать почтовый ящик в процессе работы, то стоит использовать MAPILogon.
Пример:
HResult:=MapiLogon(0,'','',MAPI_NEW_SESSION OR MAPI_LOGON_UI,0,Session);
или
HResult:=MapiLogon(0,'M T U','111',MAPI_LOGON_UI,0,Session);
или
HResult:=MapiLogon(0,'Ситилайн','',0,0,Session);
Второй параметр это как раз имя нужного почтового ящика, третий параметр — пароль на почтовый ящик, если ящик запаролен.
Если указан флаг MAPI_LOGON_UI, то будет вызвано окно выбора почтового ящика ("select account").
Правда если при наличие этого флага название ящика (и пароль, если надо) заданы корректно, то диалог
выбора выводится не будет и сессия откроется для указанного акаунта.
Если название ящика не задано или задано неверно и флаг MAPI_LOGON_UI не установлен, то
сессия откроется для того почтового ящика, который установлен "по умолчанию ... для mailto:"
К сожалению в реализации этой функции есть некоторые странные моменты (при работе с запароленым ящиком), о которых
сообщено в RITLabs, так что будет ждать пояснений.
Чтение очередного сообщения из папки Inbox. Очередность определяется
функцией MAPIFindNext.
Смысл в том, чтобы указать, какое именно письмо вам нужно.
Пример:
Var
PMess :PMapiMessage;
PP : PChar;
Begin
// Читаем самое первое письмо из папки Inbox
MAPIFindNext(0,0,nil,nil, MAPI_LONG_MSGID OR MAPI_GUARANTEE_FIFO ,0,PP);
// Или вот так: читаем следующее письмо после 12-го из папки Inbox
MAPIFindNext(0,0,nil,'12', MAPI_LONG_MSGID OR MAPI_GUARANTEE_FIFO ,0,PP);
MAPIReadMail(0,0,PP,0,0,PMess);
...
MAPIFreeBuffer(PMess);
В первом варианте после вызова MAPIFindNext значение РР будет равно '1',
во втором варианте — '13'. Конечно, если такие письма в папке есть.
И тогда переменная PMess будет содержать указатель на структуру, заполненную информацией
из этого письма.
Есть одна неприятная особенность — две эти функции корректно работают только с нулевой сессией, то есть когда
сессия открывается для ящика, который установлен "по умолчанию ... для mailto:"
Не удалось заставить их работать для любого акаунта, если открывать MAPI-сессию функцией
MAPILogon.
Так называемое "разрешение имени адресата" — поиск адреса по имени в адресных книгах.
В качестве параметра задается имя адресата, в случае его успешного поиска, будет возвращена
ссылка на структуру TMapiRecipDesc, содержащую всю информацию о нем.
Пример:
Hresult:=MAPIResolveName(0,0,'jinx',MAPI_DIALOG,0,RecN);
...
MAPIFreeBuffer(RecN);
Если указан флаг MAPI_DIALOG и в адресных книгах найден больше чем один адресат
с таким же именем, то будет выведен диалог "разрешения имени":

Если адресат с таким именем существует и он только один, то переменная RecN будет содержать
указатель на искомую структуру. В этом случае диалога выводится не будет независимо от установленных флагов.
Если такого адресата не найдено, не будет выведен диалог и будет возвращена ошибка
MAPI_E_AMBIGUOUS_RECIPIENT независимо от установленных флагов.
Очень быстрый и простой способ создания стандартного сообщения
с прикрепленными файлами и без указания адресов получателей.
Пример:
MapiSendDocuments(0,';','d:\11.txt;d:\22.txt','11.txt;22.txt',0);
или
MapiSendDocuments(Session^,';','d:\11.txt;d:\22.txt','11.txt;22.txt',0);
или
MapiSendDocuments(Session^,';','d:\11.txt;d:\22.txt','',0);
или
MapiSendDocuments(Session^,';','d:\11.txt;d:\22.txt','файл1;файл2',0);
В случае с указанием сессии Session, письмо будет создано для почтового ящика,
который открыт в этой сессии (см. MAPILogon), в случае с нулевой сессией —
для почтового ящика "по умолчанию..."
Именно эта функция используется, когда вы нажимаете на правую кнопку мыши в проводнике файлов и выбираете
меню "Zip and E-mail ... ".
Создание и отправка сообщения. В отличии от предыдущей функции здесь задаются все параметры
в режиме run-time, таким образом сообщение может быть создано и сразу отправлено
без участия пользователя.
Пример:
Var
Mess : TMapiMessage;
Rec : TMapiRecipDesc;
Begin
Rec.lpszName:='Информационный центр';
Rec.lpszAddress:='Info@id.ru';
Rec.ulEIDSize:=0;
Rec.lpEntryID:=nil;
Rec.ulReserved:=0;
Rec.ulRecipClass:=MAPI_TO;
Mess.ulReserved:=0;
Mess.lpszSubject:='';
Mess.lpszNoteText:='';
Mess.lpOriginator:=nil;
Mess.nRecipCount:=1;
Mess.lpRecips:=RecN;
Mess.lpszMessageType:=nil;
Mess.lpszDateReceived:=nil;
Mess.lpszConversationID:= '';
Mess.flFlags:=0;
Mess.nFileCount:=0;
Mess.lpFiles:=nil;
// Окно редактирования письма будет выдано на экран
HResult:= MapiSendMail(Session^,0, Mess , MAPI_DIALOG ,0);
// Или письмо будет сразу после создания отправлено
// без вмешательства пользователя
HResult:= MapiSendMail(Session^,0, Mess , 0 ,0);
Все, что касается использования сессии Session смотрите в описании функции
MAPISendDocuments
Версии TheBAT! до 1.54 Beta/9 имеют ошибку в реализации функции
MapiSendMail, которая не позволяла корректно отсылать письма без
участия пользователя. Вариант с флагом MAPI_DIALOG работает
корректно во всех версиях.
Елена Филиппова
Ссылки по теме: