![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Демонстрационный проект (Simple MAPI, CMC) - 26 Кб
Этот вопрос возникает в ньюсгруппах с завидной постоянностью. Для отправки электронного письма существует несколько способов, доступных (или недоступных) в зависимости от настройки пользовательского компьютера. Не все они равноценны. Во всех примерах отсутствует проверка ошибок, так что не обольщайтесь - все еще сложнее, чем вы думаете :)
Доступен даже из bat-файлов (через команду start). На компьютере должен быть установлен и настроен почтовый клиент. Если необходимо отправить письмо по адресам email1 и email2 , копию - по адресу email3 с темой "Subject text" и текстом "Body\nText", то достаточно сформировать гиперссылку:
mailto:email1;email2&cc=email3?subject=Subject%20text&body=Body%0dText
Ее можно поместить на веб-страницу (в теге <A href=...>). Щелчок мышью на такой ссылке приведет к открытию окна почтового клиента с готовыми параметрами письма. Пользователю останется только нажать кнопку "отправить". Открыть такую гиперссылку можно и программно (например, с помощью функции ShellExecute).
Вложенные файлы таким способом отправить не удастся.
Доступен из WinAPI-приложений, в том числе из Visual Basic (для него существует специальная обертка этой библиотеки в файле MAPIVB32.BAS)
Ваша программа может использовать различные сервисы MAPI. Здесь я описываю Simple MAPI. В демонстрационном проекте можно найти пример использования CMC. Все описываемые функции недоступны через библиотеки импорта (вследствие очень гибкой архитектуры MAPI). Для их использования необходимо явно загрузить библиотеку mapi32.dll и получить адрес необходимой функции с помощью GetProcAddress. |
Для этого способа необходим почтовый клиент, поддерживающий MAPI - например, Netscape Messenger, Outlook Express, Exchange client, Microsoft Outlook 2000 (см. примечание).
Simple MAPI предоставляет несколько способов отправить письмо. Самый простой в реализации - функция MAPISendDocuments. В отличие от предыдущего способа, здесь нет проблем с вложениями, но нельзя ввести текст письма:
typedef ULONG (FAR PASCAL *SendProc)( ULONG ulUIParam, LPTSTR lpszDelimChar, LPTSTR lpszFullPaths, LPTSTR lpszFileNames, ULONG ulReserved); HMODULE h = LoadLibrary("Mapi32.dll"); SendProc fnSend = (SendProc)GetProcAddress(h,MAPISendDocuments); fnSend((ULONG)hwndMain, ";", "C:\\MyDoc.DOC;C:\\Doc2.DOC", "My Document.DOC;Doc2.DOC", 0); FreeLibrary(h); |
ulUIParam - может содержать HWND окна, дочерним к которому будет диалог "Написать письмо". lpszDelimChar - разделитель имен вложенных файлов (в данном случае - ";"). Параметры lpszFullPaths и lpszFileNames соответственно описывают пути к существующим файлам (для вложения) и их названия в письме.
Кроме невозможности написать текст, имеется еще один существенный недостаток - на экране появится диалог почтового клиента "Отправка сообщения", в котором пользователь должен будет выбрать подтверждение.
ПРИМЕЧАНИЕ Microsoft Outlook 2000 настраивается по умолчанию в режиме Internet-only. При этом MAPI не поддерживается. Для того, чтобы включить MAPI, необходимо перевести Outlook 2000 в корпоративный режим и затем уже настроить учетные записи |
Также предназначен для WinAPI-программ.
Наиболее функциональный способ, но по-прежнему требует наличия MAPI-совместимого клиента. Справедливо все, что говорилось про Simple MAPI. Ваша программа имеет выбор - скрыть интерфейс почтового клиента или нет, предоставить пользователю возможность авторизации или произвести ее самостоятельно, отправлять ли набор вложений и выбирать ли адресатов из адресной книги.
Из за громоздкости примера он приведен полностью в демонстрационном проекте (функция CMailerMAPI::send). Здесь скажу только, что зачастую вместе с MAPISendMail используется "сладкая парочка" MAPILogon/MAPILogoff (для программной авторизации пользователя).
Не все почтовые клиенты поддерживают модель CDO. Она есть, например, в Microsoft Outlook 2000 (но не устанавливается по умолчанию). Для ее установки необходимо выбрать опцию "Объекты совместной работы".
Модель объектов довольно удобная и понятная. Приведу пример на JScript:
var cdoFileData=1; var session=new ActiveXObject("MAPI.Session"); session.Logon("user", "password"); var msg=session.Outbox.Messages.Add("Subject text", "Body text!"); var recip=msg.Recipients.Add(); recip.Name="someone@microsoft.com"; recip.Type=1; recip.Resolve(true); msg.Attachments.Add("MyFile.Doc", 0, cdoFileData, "C:\\Documents\\MyDoc.doc"); msg.Send(); session.Logoff(); |
Отмечу, что появляется возможность послать не сам файл, а ссылку (cdoFileLink=2) на него. Это имеет смысл, если у вас есть общий с адресатом файловый сервер. В этом случае система не проверяет достоверность имени файла.
Хорошо подходит для ASP-приложений и сервисов NT/2000, которым надо посылать много коротких почтовых сообщений. Этот сервис устанавливается с некоторыми серверными продуктами Microsoft, например, IIS 4.0 и выше. Для нормального функционирования CDONTS необходимо настроить SMTP Service в IIS. Начиная с версии CDONTS 1.2, поддерживаются почтовые вложения. Пример на VBScript:
Set objNewMail = CreateObject("CDONTS.NewMail") objNewMail.AttachFile "\\server\Documents\MyDoc.doc", "MyFile.Doc" objNewMail.Send "Generator", "someone@microsoft.com", "Subject", "The message body", 0 Set objNewMail = Nothing |
Заметьте, что не требуется (да и не поддерживается) авторизация.
Ярослав Говорунов и Алексей Остапенко:
CDO for W2K лучше, чем CDONTS и с кодировками проблем нет. Идет с IIS5. JScript:
var Msg = CreateObject("CDO.Message"); Msg.BodyPart.Charset="windows-1251"; Msg.From='"Отправитель" <sender@rsdn.ru>'; Msg.MimeFormatted=true; Msg.Subject="Тема"; Msg.To = '"Получатель" <someone@rsdn.ru>'; Msg.BCC="one@rsdn.ru; two@rsdn.ru"; Msg.TextBody="Текст сообщения"; Msg.TextBodyPart.Charset="windows-1251"; Msg.Send(); |
Опять-таки необходимо настроить SMTP Service. CDO.Message также поддерживает вложения (метод AddAttachment).
Если компьютер подключен к Интернету, но на нем нет (и не будет) никакого почтового ПО, то в этом (и только в этом!) случае можно реализовать необходимую функциональность самому. Для этого необходимо реализовать общение по протоколу SMTP (Simple Mail Transfer Protocol, RFC 0821).
Что это означает? Этот протокол содержит набор текстовых команд, которыми могут обмениваться клиент и сервер для отправки почты. Так как требуется только отправить письмо, нам понадобится знать только 5 команд: HELO, MAIL, RCPT, DATA и QUIT. Предварительно необходимо соединиться с smtp - сервером (например, smtp.mail.ru) по 25 порту - стандартному порту для SMTP. Это позволяет сделать любое средство программирования, разрешающее использование сокетов. Далее наша программа (то есть клиент) посылает серверу набор команд для подключения, составления письма и его отправки. Ниже приведен типовой сеанс соединения с помощью telnet с воображаемым сервером smtp.myserver.com (жирным шрифтом показан ответ сервера):
>telnet smtp.myserver.com 25 HELO myserver.com 250 root.myserver.com myserver.com MAIL FROM:<someone@myserver.com> 250 OK. RCPT TO:<someone@microsoft.com> 250 OK. DATA 354 Start mail input, end with <CRLF>.<CRLF>. Blah blah blah . 250 OK. QUIT Goodbye someone@myserver.com |
Здесь someone@myserver.com - адрес отправителя, someone@microsoft.com - адрес получателя. В конце письма необходимо поставить точку, о чем сервер нас честно предупреждает. Вообще говоря, надо внимательно анализировать ответы сервера и реагировать соответственно (например, может потребоваться ввести пароль). Так как задача довольно нудная и объемная, советую сначала взглянуть на готовую реализацию SMTP - мэйлера (например, на CodeGuru: http://www.codeguru.com/internet/smtp.shtml) и уже потом решать, стоит ли с этим связываться.
И в заключение добавлю, что вложения при этом способе также можно реализовать. Вкладываемый файл кодируется по определенному стандарту (чаще всего - MIME base64), после чего передается обычным текстом в теле письма. По этому поводу смотрите, например, http://www.codeguru.com/internet/mimemfc.shtml. Но можно использовать и более доступный стандарт кодирования, например распространенный у фидошников Uuencode.
Добавление от Тимофея Чадова:
Для парсинга mime есть замечательная вещь MIME++ (http://www.hunnysoft.com/mimepp/). Многоплатформенная. Отдается с документацией, исходниками и примерами для smtp, pop3, nntp. В общем-то сейчас ей и пользуюсь.
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |