Здравствуйте!
В сегодняшнем выпуске мы рассмотрим тему, которая также весьма и весьма часто фигурирует
в ваших письмах - работа с электронной почтой из программы. Тема эта
хорошо описывается в статье Михаила Плакунова, которую я
и хочу предложить вашему вниманию.
/ / / / СТАТЬЯ / / / / / / / / / / / / / / / / / / / / / /
MAPI. Добавь почту в свое приложение.
Автор: Михаил Плакунов
Источник:
Софт Терра
В последние годы электронная почта является неотъемлемой составляющей персональных информационных средств. С большой степенью вероятности верно то, что, если у человека на столе стоит компьютер, то на нем установлена та или иная система электронной почты. Вместе с тем типичные приложения для работы с электронной почтой в чистом виде далеко не всегда отвечают требованиям автоматизации трудовой деятельности пользователя. В связи с этим существует потребность в создании различного рода приложений, не являющихся частью почтовых систем, но вместе с тем предоставляющих пользователю некоторые средства для работы с электронной почтой. Программный интерфейс MAPI, о котором пойдет речь в этой статье, является одним из средств, позволяющим создавать подобные приложения на платформе Windows.
В широком понимании MAPI (Messaging Application Programming Interface) - это целая архитектура, специфицирующая процессы взаимодействия отдельных приложений с различными почтовыми системами. Архитектура MAPI описывает так называемую подсистему MAPI, которая обеспечивает взаимодействие клиентских приложений с различными службами почтовой системы, такими как служба хранения информации, служба адресной книги, служба транспорта и т.д. С другой стороны MAPI - это прикладной интерфейс, который был создан для того, чтобы разработчики на С, С++, Visual Basic (а в последствии и Visual Basic Script) имели возможность добавлять в свои приложения функциональность для работы с электронной почтой. С точки зрения прикладной программы подсистема MAPI - это набор динамических библиотек, содержащих функции и объектно-ориентированные интерфейсы, благодаря которым взаимодействуют клиентские и серверные части почтовых приложений. О MAPI можно говорить много и долго (благо компания Microsoft постаралась сделать из MAPI очередного программного <монстра>), но наибольший интерес для разработчиков представляют так называемые клиентские прикладные программные интерфейсы, среди которых следует выделить в первую очередь Simple MAPI, MAPI и CDO.
Simple MAPI предоставляет в распоряжение разработчиков всего 12 простейших функций. Они позволяют выполнять такие действия, как <сформировать сообщение>, <указать адрес получателя>, <отправить>, <получить>. Причем все операции с сообщениями можно производить только в рамках одной папки, являющейся папкой для входящих сообщений текущего контейнера доставки (в почтовой системе MS Exchange Server это обычно Другим недостатком Simple MAPI является то, что он позволяет работать только со стандартными полями сообщения, такими как <Тема>, <Отправитель>, <Получатель>, <Дата отправки>, <Текст сообщения>, <Класс сообщения>, а также с вложенными файлами.
При всей своей ограниченности Simple MAPI подкупает имено простотой в освоении и использовании. Тому, кто имеет даже небольшой опыт программирования на С или Visual Basic достаточно нескольких минут для, того чтобы научиться использовать этот интерфейс.
Следующий фрагмент кода на языке С позволит убедиться в этом (для простоты несущественные участки кода, такие как объявление переменных и обработка ошибок опущены).
В приведенном примере формируется сообщение с темой Первым делом клиентской программе необходимо начать сеанс работы с почтовой системой, для чего при помощи функции MAPILogon открывается сессия Simple MAPI. Затем из видимого имени ("Bill Gates") функция MAPIResolveName формирует структуру, содержащую точную и полную информацию об адресате (в частности его электронный адрес). Полученная информация об адресате наряду с темой и текстом формирует структуру, содержащую почтовое сообщение, готовое к отправке. Функция MAPISendMail отправляет сообщение по электронной почте. Наконец, функция MAPILogoff завершает сеанс работы с почтовой системой, закрывая сессию Simple MAPI.
Просто, не правда ли? Немного модифицировав программу, можно дать ей возможность отправлять сообщения, содержащие не только текст, но и вложенные файлы. Изучив еще пару-тройку функций Simple MAPI, можно с легкостью запрограммировать получение анализ и удаление сообщений, содержащихся в почтовом ящике пользователя.
Simple MAPI позволяет запрограммировать две основные функции электронной почты - отправку и прием сообщений. Зачастую это вся функциональность, необходимая приложению для работы с электронной почтой. Типичными примерами использования Simple MAPI являются приложения, производящие рассылку сообщений (возможно однотипных, по шаблону) множеству адресатов, а также приложения, время от времени сканирующие почтовый ящик пользователя и производящие анализ и обработку поступающей в него корреспонденции.
Программисты на С найдут определения всех функций, структур и констант Simple MAPI в файле MAPI.H, входящем в состав Microsoft Visual Studio. Его аналогом для Visual Basic является файл MAPI.BAS. Сами функции находятся в динамической библиотеке MAPI.DLL. Как правило Simple MAPI входит в состав клиентских почтовых программ, причем не только работающих в архитектуре <клиент-сервер> (MS Outlook, MS Exchange Client), но и обычных (MS Outlook Express, Eudora Pro, а в скором будущем и The Bat!).
Simple MAPI на то и MAPI 1.0 предоставляет разработчику не только возможность реализации таких простых функций как отправка или прием почтовых сообщений, но и механизмы для более тесного взаимодействия с отдельными частями систем электронной почты - с адресной книгой, иерархической структурой папок на почтовом сервере, службой транспорта и т.д. Более того, с помощью MAPI 1.0 можно создавать даже части почтовых систем - программные шлюзы, различные службы обработки информации, которые являются частью MAPI-совместимых почтовых серверов. Не будет преувеличением сказать, что, используя MAPI 1.0 можно создать свою собственную клиентскую почтовую программу, аналогичную MS Oulook со всеми ее богатыми возможностями.
Вместе с тем создание приложений на базе MAPI 1.0 - более трудоемкий процесс, нежели программирование с использованием Simple MAPI. MAPI 1.0 требует от разработчика дополнительной квалификации, в частности знания технологии COM. Перепишем уже имеющийся пример с использованием MAPI 1.0. Для наглядности каждый блок кода сопоставлен с соответствующим фрагментом из предыдущего примера.
Как видно из этого примера большинство операций, являющихся примитивными для Simple MAPI, в MAPI 1.0 состоят из последовательностей вызовов тех или иных методов различных интерфейсов. Так, для того, чтобы создать сообщение в MAPI 1.0 требуется получить доступ и открыть контейнер с сообщениями, отыскать в нем папку для исходящих сообщений и только потом собственно создать в ней само сообщение и начинить его всей необходимой информацией. В Simple MAPI все эти промежуточные шаги скрыты от разработчика. С другой стороны MAPI 1.0 позволяет создавать сообщения в любой папке (да и не только сообщения, а объекты календаря, задачи и т.д.). Таким образом, взамен простоте использования появляются новые возможности.
Интерфейс MAPI 1.0, в отличие от Simple MAPI можно использовать при создании служб Windows NT. Это очень полезное свойство позволяет создавать различного рода почтовые мониторы. Типичная задача почтового монитора может заключаться в сканировании почтового ящика пользователя на предмет поступающей в него корреспонденции, ее разбор, анализ и последующие действия по результатам этого анализа.
Отдельного обсуждения заслуживает такая возможность MAPI 1.0 как создание всевозможных расширений (extensions) к клиентским программам почтовой системы MS Exchange Server (MS Outlook или MS Exchange Client). Расширения позволяют автоматизировать различные функции обработки сообщений, не реализованные в базовом наборе функций клиентской программы. В частности, механизм расширений позволяет создавать модули для обработки входящих сообщений, так называемые правила (rules), добавлять к клиентской программе дополнительные команды и пункты меню, а также обработчики событий, изменяющие поведение системы при определенных событиях и многое другое.
Интерфейс CDO (Collaboration Data Objects), ранее известный как OLE Messaging и Active Messaging представляет собой библиотеку, обеспечивающую доступ приложений к несколько ограниченному набору функция MAPI 1.0 через вызовы Automation. Функции работы с сообщениями могут быть встроены в приложения, созданные с помощью любого средства разработки, являющегося контроллером Automation. К таковым относятся C/C++, Visual Basic, Visual Basic for Applications, VBScript, Javascript. Использование CDO существенно упрощает разработку приложений, работающих с электронной почтой, вместе с тем оставляя разработчику широкие возможности MAPI. Наибольшее применение CDO находит в скриптовых языках. Так, например, в комбинации с APS использование CDO позволяет достаточно легко создать почтового Web-клиента.
Итак, мы кратко рассмотрели 3 программных интерфейса, позволяющих встраивать в приложения на платформе Windows функциональность для работы с электронной почтой. У каждого из них есть свои преимущества и недостатки. Ничего универсального не существует - окончательный выбор того или иного средства зависит от конкретной задачи и является прерогативой разработчика. Более подробную информацию на эту тему можно получить на http://msdn.microsoft.com/library/psdk/mapi/.
/ / / / ВОПРОС-ОТВЕТ / / / / / / / / / / / / / / / /
Q|
Как создать окно ввода текста переключаясь в которое устанавливался бы заданный язык.
например необходим ввод только русских слов в строке по которой ищется перевод на английский,
а язык по умолчанию в виндовс английский. хотелесь бы при запуске программы когда
пользователь ткнет мышкой в поле ввода чтобы он не переключал язык по умолчаню на русский.
- Alexander Shinkevich
Ниже приводится пример ее использования :
1) Добавить в проект с помощью Class Wizard'а новый класс CMyEdit на основе
CEdit. TCHAR m_PreviousLayout[KL_NAMELENGTH] ;
3) Добавить обработчики WM_SETFOCUS и WM_KILLFOCUS :
4) Использовать CMyEdit вместо CEdit (на примере диалога) :
/ / / В ПОИСКАХ ИСТИНЫ / / / / / / / / / / / / /
Q|
Можно ли из моей программы управлять окном которое создано другим приложением (закрывать, сворачивать,
нажимать в нем кнопки и т.д.), если да то как?
- Alhim
Ответить на вопрос
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
А на сегодня это все. До встречи через неделю!
Алекс Jenter
jenter@mail.ru
MAPILogon(0,"My Profile", NULL, MAPI_NEW_SESSION, 0, &pSession);
MAPIResolveName(pSession, 0, "Bill Gates", 0, 0, &pRecipient);
ZeroMemory(&pMessage, sizeof(pMessage))
pMessage.lpszSubject = " Greeting";
pMessage.lpszNoteText = "Hello Bill!";
pMessage.nRecipCount = 1;
pMessage.lpRecips = Recipient;
MAPISendMail(pSession, 0, &pMessage, 0, 0);
MAPILogoff(pSession, 0, 0, 0);
MAPI 1.0 - для продвинутых
// Begin MAPILogon(:);
MAPILogonEx(0, "My Profile", NULL, MAPI_NEW_SESSION, &lpSession);
// End MAPILogon(:);
lpSession->GetMsgStoresTable(0, &StoresTable);
HrQueryAllRows(StoresTable, (LPSPropTagArray)&tagDefaultStore, NULL, NULL, 0, &lpRow);
for(i = 0; i < lpRow -> cRows; i++)
{
if(lpRow->aRow[i].lpProps[0].Value.b == TRUE)
break;
}
lpSession->OpenMsgStore(0, lpRow -> aRow[i].lpProps[1].Value.bin.cb,
(LPENTRYID)lpRow -> aRow[i].lpProps[1].Value.bin.lpb, NULL,
MDB_WRITE, &lpMDB);
lpMDB->OpenEntry(lpPropValue -> Value.bin.cb, (LPENTRYID)lpPropValue -> Value.bin.lpb,
NULL, MAPI_MODIFY, &ulObjType, (LPUNKNOWN *)&lpFolder);
lpFolder->CreateMessage(NULL, 0, &lpMsg);
SInitPropValue MsgProps[] =
{
{PR_DELETE_AFTER_SUBMIT, 0, TRUE},
{PR_MESSAGE_CLASS, 0, (ULONG)"IPM.NOTE "},
{PR_SUBJECT, 0, (ULONG)"Greeting"},
{PR_BODY, 0, (ULONG)" Hello Bill!"}
};
lpMsg->SetProps(4, (LPSPropValue)&MsgProps, NULL);
// Begin MAPIResolveName(:);
lpSession->OpenAddressBook(0, NULL, AB_NO_DIALOG, &lpAdrBook);
MAPIAllocateBuffer(CbNewADRLIST(1), (LPVOID*)&lpAdrList);
MAPIAllocateBuffer(2*sizeof(SPropValue), (LPVOID*)&(lpAdrList -> aEntries -> rgPropVals));
ZeroMemory(lpAdrList -> aEntries -> rgPropVals, 2*sizeof(SPropValue));
lpAdrList->cEntries = 1;
lpAdrList->aEntries[0].ulReserved1 = 0;
lpAdrList->aEntries[0].cValues = 2;
lpAdrList->aEntries[0].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
lpAdrList->aEntries[0].rgPropVals[0].Value.lpszA = "Bill Gates";
lpAdrList->aEntries[0].rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
lpAdrList->aEntries[0].rgPropVals[1].Value.l = MAPI_TO;
lpAdrBook->ResolveName(0, 0, NULL, lpAdrList);
lpMsg->ModifyRecipients(MODRECIP_ADD, lpAdrList);
// End MAPIResolveName(:);
// Begin MAPISendMail(:);
lpMsg->SubmitMessage(0);
// End MAPISendMail(:);
// Begin MAPILogoff (:);
lpSession->Logoff(0, 0, 0);
// End MAPILogoff (:);
CDO - разумный компромисс
Сухой остаток
|A1
Для переключения раскладок необходимо вызвать функцию LoadKeyboardLayout
2) Добавить в класс переменную, хранящую предыдущую установленную раскладку
клавиатуры :
void CMyEdit::OnSetFocus(CWnd* pOldWnd)
{
CEdit::OnSetFocus( pOldWnd ) ;
// запоминаем предыдущую раскладку клавиатуры
::GetKeyboardLayoutName( m_PreviousLayout ) ;
// устанавливаем новую раскладку для языка "Русский"
::LoadKeyboardLayout( _T( "00000419" ), KLF_ACTIVATE ) ;
}
void CMyEdit::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
// восстанавливаем предыдущую раскладку клавиатуры
::LoadKeyboardLayout( m_PreviousLayout, KLF_ACTIVATE ) ;
}
class CMyDlg : public CDialog
{
// ...
CMyEdit m_Edit;
// ...
} ;
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestKeyboardDlg)
DDX_Control( pDX, IDC_EDIT, m_Edit ) ;
//}}AFX_DATA_MAP
}
- Алексей Гончаров
|A2
[...] Также можно активизировать т.н. keyboard layout (раскладку клавиатуры) с
помощью функции ActivateKeyboardLayout,
активизирующей раскладку, загруженную предварительно с помощью указанной
выше функции LoadKeyboardLayout. Хотя LoadKeyboardLayout сама может
активизировать раскладку (при использовании флага KLF_ACTIVATE ), но при
частой смене языка
оптимальнее использовать ActivateKeyboardLayout. Т.е. в начале загрузить
раскладку с помощью LoadKeyboardLayout, а многократно переключать язык ввода
функцией ActivateKeyboardLayout.
- Igor Sukharev
Красноярск, 2001.