Хочу рассказать сегодня как получить список писем, аттачей из Windows Exchange и программно отсылать письма через протокол Simple MAPI.Для этого нам понадобится небольшой класс. Он слегка недоделан: отправка почты и получение списка аттачей, но это доделать не так сложно.
Описание протокола Simple MAPI можно почитать по адресу: http://msdn.microsoft.com/en-us/library/dd296728(v=VS.85).aspx
Итак, описание класса на C++ (Builder):
#ifndef SimpleMapiH
#define SimpleMapiH
using namespace std;
#include <windows.h>
#include <windowsx.h>
#include <mapi.h>
#include <winbase.h>
#include <vector>
//структура с информацией о письме
struct TMail {
AnsiString from;
AnsiString subj;
unsigned int files;
TDateTime date;
//указатели на письмо
LPSTR lpszMessageID;
MapiMessage *lpMessage;
};
class SimpleMapi {
private:
//библиотека и указатели на нужные нам функции
HANDLE hMAPILib;
LPMAPILOGON lpfnMAPILogon;
LPMAPIFINDNEXT lpfnMAPIFindNext;
LPMAPILOGOFF lpfnMAPILogoff;
LPMAPIREADMAIL lpfnMAPIReadMail;
LPMAPIFREEBUFFER lpfnMAPIFreeBuffer;
//текущая сессия
LHANDLE lhSession;
//буфферы
char szSeedMessageID[512];
char szMessageID[512];
LPSTR lpszSeedMessageID;
LPSTR lpszMessageID;
//указатель на письмо
MapiMessage *lpMessage;
//тип ошибки
ULONG err;
//разбор даты
TDateTime __fastcall ParseDate(AnsiString date);
public:
//полный список писем
vector<tmail> MailList;
__fastcall SimpleMapi();
//подключение к Exchenge
bool __fastcall Connect();
//перейти к первому письму из списка
bool __fastcall GetFirst();
//перейти к следующему письму из списка
bool __fastcall GetNext();
//получить указатель на полную информацию о текущем письме
bool __fastcall GetElement();
//заполнить структуру текущим письмом
TMail __fastcall Fetch();
//получить список всех писем (заполняем вектор)
bool __fastcall GetList();
//отключаемся от Exchange
void __fastcall Disconnect();
//отправить письмо - не реализовано
void __fastcall SendMail();
//получить список приложений письма по указателю
vector<ansistring> __fastcall GetAttachs(LPSTR lmID, MapiMessage *lpMes);
};
#endif
#include <vcl.h>
#pragma hdrstop
#include "SimpleMapi.h"
#pragma package(smart_init)
__fastcall SimpleMapi::SimpleMapi() {
lpszSeedMessageID=&szSeedMessageID[0];
lpszMessageID=&szMessageID[0];
*lpszSeedMessageID = '\0';
//необходимые нам функции из мапи
hMAPILib = LoadLibrary("MAPI32.DLL");
lpfnMAPILogon = (LPMAPILOGON) GetProcAddress(hMAPILib, "MAPILogon");
lpfnMAPILogoff = (LPMAPILOGOFF) GetProcAddress(hMAPILib, "MAPILogoff");
lpfnMAPIFindNext = (LPMAPIFINDNEXT) GetProcAddress(hMAPILib, "MAPIFindNext");
lpfnMAPIReadMail = (LPMAPIREADMAIL) GetProcAddress(hMAPILib, "MAPIReadMail");
lpfnMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress(hMAPILib, "MAPIFreeBuffer");
}
//подключаемся к мапи
bool __fastcall SimpleMapi::Connect() {
err = (*lpfnMAPILogon)(0L, "Microsoft Outlook", NULL, 0L, 0L, &lhSession);
if(err != SUCCESS_SUCCESS) {
FreeLibrary(hMAPILib);
return false;
}
return true;
}
//получаем первое письмо
bool __fastcall SimpleMapi::GetFirst() {
//MAPI_GUARANTEE_FIFO - сортировка по дате
err = (*lpfnMAPIFindNext)(lhSession, 0L, NULL, lpszSeedMessageID, MAPI_GUARANTEE_FIFO, 0L, lpszMessageID);
return err == SUCCESS_SUCCESS;
}
//получаем следующее письмо
bool __fastcall SimpleMapi::GetNext() {
//MAPI_GUARANTEE_FIFO - сортировка по дате
//чистим буфер
(*lpfnMAPIFreeBuffer)(lpMessage);
lstrcpy(lpszSeedMessageID, lpszMessageID);
//переходим
err = (*lpfnMAPIFindNext)(lhSession, 0L, NULL, lpszSeedMessageID, MAPI_GUARANTEE_FIFO, 0L, lpszMessageID);
return err == SUCCESS_SUCCESS;
}
//заполняет указатель на письмо
bool __fastcall SimpleMapi::GetElement() {
//MAPI_SUPPRESS_ATTACH - аттачи тоже загружаем
err = (*lpfnMAPIReadMail)(lhSession, 0L, lpszMessageID, MAPI_SUPPRESS_ATTACH, 0L, &lpMessage);
return err == SUCCESS_SUCCESS;
}
//заполним структуру данными письма
TMail __fastcall SimpleMapi::Fetch() {
TMail buf;
if((lpMessage->lpOriginator->lpszName != NULL) && lpMessage->lpOriginator->lpszName[0] != '\0') {
buf.from = lpMessage->lpOriginator->lpszName;
} else {
buf.from = lpMessage->lpOriginator->lpszAddress;
}
buf.subj = AnsiString(lpMessage->lpszSubject);
buf.files = (unsigned int)lpMessage->nFileCount;
buf.date = SimpleMapi::ParseDate(AnsiString(lpMessage->lpszDateReceived));
buf.lpszMessageID = lpszMessageID;
buf.lpMessage = lpMessage;
return buf;
}
//распарсить дату письма (учтем перевод стрелок)
TDateTime __fastcall SimpleMapi::ParseDate(AnsiString date) {
//пример: 2010/04/02 12:02
unsigned short y,m,d,h,i,s;
y = (unsigned short)date.SubString(1, 4).ToInt();
m = (unsigned short)date.SubString(6, 2).ToInt();
d = (unsigned short)date.SubString(9, 2).ToInt();
h = (unsigned short)date.SubString(12, 2).ToInt();
i = (unsigned short)date.SubString(15, 2).ToInt();
TTimeZoneInformation tzi;
if(GetTimeZoneInformation(&tzi) == TIME_ZONE_ID_STANDARD) {
//в зимнее время добавляем 1 час
h++;
}
TDateTime dt(y, m, d);
TDateTime tm(h, i, 0, 0);
return dt + tm;
}
//заполним вектор письмами
bool __fastcall SimpleMapi::GetList() {
if(!Connect()) return false;
if(!GetFirst()) return false;
TMail buf;
int i = 0;
while(err == SUCCESS_SUCCESS) {
if(GetElement()) {
buf = Fetch();
MailList.push_back(buf);
}
GetNext();
if(i%1000 == 0 && i > 0) {
//переделать на вопрос
if( Application->MessageBox("Загрузка списка писем может занять продолжительное время. Продолжить?",
Application->Title.c_str(),
MB_ICONQUESTION | MB_YESNO) == IDNO ) break;
}
i++;
}
Disconnect();
return true;
}
//отключаемся
void __fastcall SimpleMapi::Disconnect() {
//закрываем подключение
(*lpfnMAPILogoff)(lhSession, 0L, 0L, 0L);
//освобождаем библиотеку
FreeLibrary(hMAPILib);
}
void __fastcall SimpleMapi::SendMail() {
//TODO
/*
документация: http://msdn.microsoft.com/en-us/library/dd296721(v=VS.85).aspx
примеры:
- http://stackoverflow.com/questions/2350011/how-do-i-programmatically-send-email-w-attachment-to-a-known-recipient-using-mapi
- http://www.codeproject.com/KB/IP/SendTo.aspx
- http://www.codeguru.com/forum/archive/index.php/t-105158.html (без приложений)
*/
}
//получить список аттачей
//аттачи сохраняются во временную дирректорию
vector<AnsiString> __fastcall SimpleMapi::GetAttachs(LPSTR lmID, MapiMessage *lpMes) {
vector<AnsiString> atachs;
err = (*lpfnMAPIReadMail)(lhSession, 0L, lmID, MAPI_SUPPRESS_ATTACH, 0L, &lpMes);
if(err == SUCCESS_SUCCESS) {
//TODO
//for(int i = 0; i < lpMes->nFileCount; i++) {
//lpMes->lpFiles->lpszPathName;
//lpMes->lpFiles->lpszFileName;
//lpMes->lpFiles++;
//}
}
return atachs;
}
Комментариев нет:
Отправить комментарий