Сегодня решил немного поэкспериментировать с библиотекой Synapse и научиться отправлять письма, используя протокол SMTP (Simple Mail Transfer Protocol — протокол передачи почты). Тема эта достаточно интересная и полезная. Дело даже не в том, чтобы написать для себя почтовый клиент, коих миллионы. Подобные навыки работы с бибилиотекой могут потребоваться, например, если Вы захотитенаписать своего клиента для отправки сообщений в свой блог на ЖЖ, Blogger или LiveInternet — эти блог сервисы поддерживают публикацию новых постов по e-mail. Так что, полученные сегодня навыки несомнено должы принести Вам (мне точно) определенную пользу. Для работы с протоколом SMTP в Synapse можно использовать следующие модули библиотеки:
- smtpsend — содержит объект Tsmtpsend и ключевые методы для отправки электронных писем.
- mimemess — содержит объекты TMessHeader — заголовки сообщения; TMimeMess — сообщение;
- mimepart — содержит объект TMimePart для работы с частями сообщения, которые можно использовать для отправки по почте файлов.
Сегодня сосредоточимся на основной задаче — отправке текста. Так как именно для этого в свое время и был создан SMTP, а пересылкой файлов (аттачей) занимается не протокол, а расширение к протоколу — MIME (Multupurpose Internet Mail Extentions, RFC-1521). Расширениями займемся позднее.
Итак, сегодня в наши задачи входит:
- Составить правильный заголовок сообщения
- Добавить в сообщение текст (plain text) или html-код
- Оправить сообщение на постовый ящик, используя заданый smtp-сервер.
1. Подготавливаемся к работе с SMTP в Delphi. Загоовка приложения.
Открываем Delphi, создаем новое приложение и на главной форме размещаем компоненты как показано на рисунке:
Как вы знаете, SMTP-серверы почтовых служб таких как mail.ru требуют обязательной авторизации, поэтому на форме нашего будущего приложения предусмотрены два поля: «Логин пользователя» и «Пароль пользователя» — туда будем записывать данные для авторизации на SMTP-сервере.
Поле «Хост» должно содержать хост smtp-сервера, например, smtp.mail.ru или smtp.yandex.ru и т.д., смотря от чьего имени вы будете слать письма. Поле «Адрес e-mail» для отправителя должен содержать правильный адрес, т.е. применительно к mal.ru, если ваш логин «blogger», то ящик должен быть «blogger@mail.ru», а хост «smtp.mail.ru».
С формой приложения и назначением элементов главной формы, думаю, разобрались. Переходим ко второму пункту нашей работы — создадим правильное сообщение.
2. Формируем сообщение e-mail, используя Synapse
Итак, в заголовки сообщения нам необходимо включить:
- Имя отправителя
- Адрес отправителя
- Список получателей (в нашем случае получатель будет один)
Подключаем к проекту модули mimemess, mimepart, smtpsend. Создаем процедуру с названием, например SendMail:
Procedure SendMail (Host, Subject, pTo, From , TextBody, HTMLBody, login,password : string); var Msg : TMimeMess; //собщение StringList : TStringList; //содержимое письма MIMEPart : TMimePart; //части сообщения (на будущее) begin Msg := TMimeMess.Create; //создаем новое сообщение StringList := TStringList.Create; try // Добавляем заголовки Msg.Header.Subject := Subject;//тема сообщения Msg.Header.From := From; //имя и адрес отправителя Msg.Header.ToList.Add(pTo); //имя и адрес получателя // создаем корневой элемент MIMEPart := Msg.AddPartMultipart('alternative', nil); if length(TextBody)>0 then begin StringList.Text := TextBody; Msg.AddPartText(StringList, MIMEPart); end else begin StringList.Text := HTMLBody; Msg.AddPartHTML(StringList, MIMEPart); end; // Кодируем и отправляем Msg.EncodeMessage; smtpsend.SendToRaw(From, pTo, Host, Msg.Lines, login, password); finally Msg.Free; StringList.Free; end; end;
Разберем по частям, что к чему. В начале создаем новое сообщение, используя объект TMimeMess (сообщение) из модуля Synapse mimemess.
Далее добавляем в сообщение все необходимые заголовки. Создаем объект TMimePart. Так как создается корневой элемент MIME, то вторым параметром, согласно условиям работы с Synapse, ставится nil. Если мы отправляем простой текст, то используем метод AddPartText, где вторым параметром выступает как раз созданные нами корневой элемент, иначе, если текстовое содержимое не отсылается, то принимаем, что отсылается HTML-код и используем соответственно метод AddPartHTML. Также Вы можете добавить в сообщение:
- Текст из файла, используя метод AddPartTextFromFile.
- HTML-код из файла, используя метод AddPartHTMLFromFile
- Бинарный файл, загрузив данные в поток TStream и указав его в параметрах метода AddPartBinary
Есть ещё ряд других методов, расширяющих возможности объекта TMimePart, разобраться с работой которых, думаю, будет достаточно просто.
После того, как сообщение собрано, мы его кодируем, используя метод EncodeMessage, в котором собираются правильные, согласно RFC заголовки, «склеиваются» все части и т.д. И, наконец, отправляется письмо, используя метод SendToRaw из модуля Synapse httpsend.
Теперь, когда основная процедура отправки готова. Дописываем приложение.
3. Дорабатываем приложение для отправки почты.
В обработчике onClick кнопки пишем:
procedure TForm5.Button1Click(Sender: TObject); begin if RadioButton1.Checked then SendMail(Edit1.Text, 'Test Message', '"' + Edit4.Text + '" <' + Edit5.Text + '>', '"' + Edit2.Text + '" <' + Edit3.Text + '>', Memo1.Text, '', Edit6.Text, Edit7.text) else SendMail(Edit1.Text, 'Test Message', '"' + Edit4.Text + '" <' + Edit5.Text + '>', '"' + Edit2.Text + '" <' + Edit3.Text + '>', '', Memo1.Text, Edit6.Text, Edit7.text) end;
Теперь можете проверить работу приложения. Например я отправил себе на второй ящик письмо:
И спустя буквально пару секунд получил новое письмо на свой ящик:
Теперь можете потренироваться с приложением, добавить возможность отправки файлов по электронной почте и т.д. Как видите, с Synapse не только просто работать с HTTP и HTTPS-протоколами, но и не менее просто отправлять электронную почту.

Спасибо за интересную статью. Не подскажешь как реализовать отправку файла на мыло?
Чтоб отправить файл на мыло надо использовать TMimePart и его метод AddPartBinary. Прицпляешь сначало текст, потом файлик и также само отправляешь.
Так же было интересно прочитать статью про отправку писем через SMTP сервер использующий SSL (gmail, yhoo, msn)
Надо посмотреть. Вроде бы с Synapse все должно сработать быстро, главно не забыть подцепить модуль ssl_openssl :)
А как проверить корректность отправки почты? Ошибка не выдаётся даже тогда, когда нет подключения к SMTP-серверу.
Странно…у меня при невозможности соединения с сервером исключение возникает, да и другие исключения обрабатывает. Может у Вас в IDE стоит пропуск каких-нибудь исключений?
А я-то как удивился! Я в Ubuntu использую Lazarus. Попробую в Windows ещё поковыряться Lazarus.
И у меня такая же ерундень. Стоит Delphi 7 с стандартными настройками. Никаких обибок или сообщений не выдает. Наверное надо самому как-то проверять все события или читать их статус. Кстати, то что письмо не отправилось можно проверить посмотрев на то, что вернула функция Send Сам не пробовал, но должно работать.
меня интересует как у From и To установить кодировку?
Msg.Header.Subject := Subject;//тема сообщения
Msg.Header.From := From; //имя и адрес отправителя
Msg.Header.ToList.Add(pTo); //имя и адрес получателя
у меня это вообще не работает, пишу под xp библиотеку от сюда взял http://www.koders.com/info.aspx?c=ProjectInfo&pid=DEQAQ82QTXZZNDY4RT2N9NNSRB как не отправляю ничего не доходит, логин пытался и с @mail.ru и без него, не робит никак, код от сюда скопирован, не пойму в чем моя ошибка, можете что нибуть подсказать?
Полдня мучился с отправкой сообщения с помощью компонентов Indy – ничего не получалось. Наткнулся на Вашу статью! Все просто и понятно – получилось сразу! Огромнейшее спасибо Автору! Единственное – пришлось сделать пару доработок. В модуле smtpsend описана константа const cSmtpProtocol = ‘25’ ; Если smtp-порт сервера отличается от указанного значения – отправка не происходит. К примеру для Yandex порт «587». Поэтому вместо « const cSmtpProtocol = ‘25’» написал «var cSmtpProtocol : String; » Так же нет проверки на успешное отправку сообщения. После всего получилось вот что: function SendMsgMail (Host, Subject, pTo, From , TextBody, HTMLBody, login,password, port : string) :… Подробнее »
2Алекс. Не за что. Рад, что статья Вам пригодилась.
Пользуюсь сервисом Mail.ru. Если указать отправщика отличного от логина(логин test_test, а отправщик test_111@mail.ru), то почта не отслылается. А если отправщик test_test@mail.ru, то отлично работает. В чём проблемка может бытЬ?
Так видимо в том и проблема, что логин на мэйле — это начало адреса вашего e-mail.
Vlad, очень помогают твои статьи Delphi+Synapse, большое спасибо!
Да всегда пожалуйста :)
Есть сайты на которых регистрация происходит при помощи MIME. То есть хедер ка положино:
Keep-Alive: 115
Connection: keep-alive
И тому подобное. А вот:
Content-Type: multipart/form-data; boundary=—————————41184676334
То есть каждый раз рисуется рамочка такого плана:
——————————41184676334
Content-Disposition: form-data; name=»MAX_FILE_SIZE»
128000
——————————41184676334
И как реализовать такие вот пост запросы хз. Как совместить httpsend и TMimePart чтобы правильно отправить этот запрос? я уже не один день пытаю реализовать, а так как новичок, нехера не выходит(((
Юрик, я прекрасно вижу все комментарии в блоге — повторять дважды смысла нет.
По вопросу.
Достаточно использовать THTTPSend. Делается это так, как рассказывалось здесь. Обычный составной запрос. Где-то в исходниках синапса даже был вроде специальный метод расписан.
ОК. Спс за помощь. Буду дальше курить мануалы)) и попробую реализовать.
А как быть с кодировками?
можно ли самому указывать кодировку темы и тела отправляемого письма?
к примеру в utf-8
Можно изменять кодировку. В одном из постов я об этом писал. Можете глянуть здесь.
благодарен за ответ, и ещё один вопрос:
можно ли программно запросить подтверждение прочтения письма, т.е. с помощью Synapse.
И как осуществить?
Никогда такого не делал, но судя по всему можно. По крайней мере при получении писем можно определить его приоритет…
ну к примеру в почтовой веб-агенте SquirrelMail version 1.4.17 на php есть возможность запрашивать подтверждение о принятии письма и об его прочтении… хотелось бы сделать тоже самое программно…
рыскал в интернете, вроде в обычном аутлуке от майкрософт тоже было такое
>>SquirrelMail version 1.4.17 на php есть возможность запрашивать подтверждение
Пример этого PHP-кода можно глянут ? Именно отрывок где запрашивается подтверждение
это пока проблемно, так как я пока что не смотрел исходники, у меня провайдер такую почту для локальных клиентов сделал, и поцепил эту веб-морду… позже посмотрю, скину тот кусок
Поэкспериментировав с отправляемыми письмами заметил, что в заголовках идет этот запрос. когда отправил письмо, оно пришло в таком виде: Return-Path: <отправитель@мейл.ру> X-Original-To: получатель@мейл.ру Delivered-To: получатель@мейл.ру Received: from webmail.мейл.ру (localhost [127.0.0.1]) by mail.мейл.ру (Postfix) with ESMTP id 73BC98A0211 for <получатель@мейл.ру>; Sat, 30 Oct 2010 23:21:06 +0300 (EEST) Received: from 91.___.___.___ (SquirrelMail authenticated user отправитель) by webmail.мейл.ру with HTTP; Sat, 30 Oct 2010 23:21:06 +0300 (EEST) Message-ID: <e8df5990af3e1b21bf1eb2f2ac27a01a.squirrel@webmail.мейл.ру> Date: Sat, 30 Oct 2010 23:21:06 +0300 (EEST) Subject: 1 From: =?utf-8?B?0JDRgNGC0ZHQvA==?= <отправитель@мейл.ру> To: получатель@мейл.ру Reply-To: отправитель@мейл.ру User-Agent: SquirrelMail/1.4.17 MIME-Version: 1.0 Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: 8bit X-Confirm-Reading-To: отправитель@мейл.ру Disposition-Notification-To: отправитель@мейл.ру X-Priority: 3 (Normal) Importance: Normal… Подробнее »
скачал исходники, копаю дальше…
вот что в исходниках [code] ========== squirrelmail.po ========== # translation of squirrelmail.po into Russian # Copyright (c) 1999-2009 The SquirrelMail Project Team # $Id: squirrelmail.po 13693 2009-05-14 00:26:43Z jervfors $ # Konstantin Riabitsev <squirrelmail-i18n@mricon.com>, 2001. # Gregory Mokhin <mok@kde.ru>, 2003-2007. # msgid "" msgstr "" "Project-Id-Version: squirrelmail\n" "Report-Msgid-Bugs-To: SquirrelMail Internationalization <squirrelmail-" "i18n@lists.sourceforge.net>\n" "POT-Creation-Date: 2007-02-14 12:48+0100\n" "PO-Revision-Date: 2007-08-27 18:11-0400\n" "Last-Translator: Gregory Mokhin <mok@kde.ru>\n" "Language-Team: Russian <kde-russian@lists.kde.ru>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" "10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ... msgid "Priority" msgstr "Срочность" msgid "High" msgstr… Подробнее »
порубало код =)))
на сколько я понял, нужно править исходники самого синапса, тоесть либо smtpsend.pas, а именно функцию SendToEx [code] function SendToEx(const MailFrom, MailTo, Subject, SMTPHost: string; const MailData: TStrings; const Username, Password: string): Boolean; var t: TStrings; begin t := TStringList.Create; try t.Assign(MailData); t.Insert(0, ''); t.Insert(0, 'X-mailer: Synapse - Delphi & Kylix TCP/IP library by Lukas Gebauer'); t.Insert(0, 'Subject: ' + Subject); t.Insert(0, 'Date: ' + Rfc822DateTime(now)); t.Insert(0, 'To: ' + MailTo); t.Insert(0, 'From: ' + MailFrom); Result := SendToRaw(MailFrom, MailTo, SMTPHost, t, Username, Password); finally t.Free; end; end; [/code] либо mimemess.pas, на сколько я понял там процедура TMessHeader.EncodeHeaders [code] procedure TMessHeader.EncodeHeaders(const Value:… Подробнее »
пол ночи за компом, решение: нужно редактировать исходники, а точнее mimemess.pas
и добавлять туда
[code]// запрос о прочтении
X-Confirm-Reading-To: отправитель@мейл.ру
Disposition-Notification-To: отправитель@мейл.ру
// запрос о получении
Return-Receipt-To:отправитель@мейл.ру[/code]
Может не стоит редактировать исходники? Есть же TSMTPSend, TMimeMess — у которого есть Headers куда можно вставить любой заголовок?
можно просто вставить любой заголовок, а можно просто добавить функцию в исходники… вчера ночью так и сделал, сделал дополнительный параметр, который отвечает за прочтения письма в mimemess.pas, вызывается так: [code]var Msg : TMimeMess; //собщение ... Msg.Header.ReturnReceiptTo:=True; ...[/code] сам кусок исходника имеет такой вид: [code]... TMessHeader = class(TObject) private ... FReplyTo: string; FReturnReceiptTo: Boolean; //принятие FXConfirmReadingTo: Boolean; //прочтение ... published ... {:Address for replies} property ReplyTo: string read FReplyTo Write FReplyTo; {:Address for ReturnReceiptTo} property ReturnReceiptTo: Boolean read FReturnReceiptTo Write FReturnReceiptTo; {:Address for XConfirmReadingTo} property XConfirmReadingTo: Boolean read FXConfirmReadingTo Write FXConfirmReadingTo; ... procedure TMessHeader.EncodeHeaders(const Value: TStrings); ... begin ... for n… Подробнее »
Доброго времени суток! у меня не выходит отправить письмо на мыло, (mail.ru) прошу помощи! использую ОС Windows7
Что конкретно не выходит? Где ошибка?
Привет всем.Тут такой вопрос.Можно ли с помощью TIdSMTP проверить получение письма?Тут дето упамямнался этот компонент.Если можно,то как? А если нельзя так,то можно какнить попроще ,чем описывает Scorpio?
Даже выше упомянутую задачу можно упростить до проверки существования почтового ящика.
У самого не получается,пожскажите пож.
выше мною написанное способ, в котором нужно редактировать исходники синапса, можно конечно это сделать при помощью своих заголовков (тоесть при создании письма, нужно создать заголовок в котором существует запрос. в моём случае ответ на данный запрос приходит в виде письма о прочтении)
в теме нужно добавить строку или пару строк:
[code]// запрос о прочтении
X-Confirm-Reading-To: отправитель@мейл.ру
Disposition-Notification-To: отправитель@мейл.ру
// запрос о получении
Return-Receipt-To:отправитель@мейл.ру
[/code]
тоесть не в теме, а в теле заголовка
и ещё одно, при создании заголовка сначала желательно посмотреть обычный заголовок и тот что с запросом… так как разные мейл-агенты и я думаю разные способы у них… времени читать не было…)
Выложите,пожалуйста,исходник программы, а то чёт не получается!!!
увы исходники остались на винте, у которого электроника сгорела))
А есть ли какая-то возможность избежать подвисания формы? Типо антифриза в Инди?
Чтобы форма не висла, отправку письма лучше сделать в отдельном потоке…
в инди можно было прописать «adr1@mail.ru; adr2@mail.ru»
Как отослать писмо на 2-3 адреса сразу?
хм.. Нодо было справку посмотреть сначало.
Оказывается через запятую нужно писать адреса
справка видимо написана не для тех кто методом тыка химичит
У каждого свой подход к программированию. Как-то слышал фразу «Хэлп читают трУсы» :)
но практика в который раз показывает что нужно учиться читать))))
[code] unit emile; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,mimemess, mimepart, smtpsend, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdMessageClient, IdSMTP, IdMessage; type TForm2 = class(TForm) lbl1: TLabel; edt1: TEdit; lbl2: TLabel; edt2: TEdit; lbl3: TLabel; lbl4: TLabel; edt3: TEdit; lbl5: TLabel; edt4: TEdit; lbl6: TLabel; lbl7: TLabel; edt5: TEdit; lbl8: TLabel; edt6: TEdit; lbl9: TLabel; btn1: TButton; lbl10: TLabel; edt7: TEdit; mmo1: TMemo; idsmtp2: TIdSMTP; idmsg1: TIdMessage; procedure btn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; implementation {$R *.dfm} function SendmsgMail (Host, Subject, pTo, From , TextBody, login,password, port… Подробнее »
А модули как определить, то?
>>А модули как определить, то?
В uses
Ругается на строчку:
if length(TextBody)>0 then
[Error] Unit1.pas(355): Illegal character in input file: ‘&’ ($26)
Владимир, это просто какого-то лиха символ < заменился на его код
добрый день.
с кодом вроде сложностей нет, все понятно. есть проблема с подключением модулей, негде не могу найти, сам раньше не пользовался. можно подробнее описать, как делается.
«…..Подключаем к проекту модули mimemess, mimepart, smtpsend…….. »
Спасибо.
с модулями разобрался.))
осталось решить 2 ошибки:
[DCC Error] Unit1.pas(51): E2003 Undeclared identifier: ‘SendMail’
[DCC Fatal Error] otpravkasmtp.dpr(5): F2063 Could not compile used unit ‘Unit1.pas’
программа не знает что такое «SendMail»
Владимиру:
> это <
«…..Подключаем к проекту модули mimemess, mimepart, smtpsend…….. »
сами модули можно вкинуть в папку с проектом, или же установить синапс…
подключение модулей как выше писалось в uses
с модулями разобрался, все подключил. ошибки тоже исправил, просто процедуру не в то место написал.
компилируется без замечаний, но сообщения не отправляются, на почту не приходят. пробовал windows 7 и ХР. пока не разобрался почему.
вопрос: настройки безопасности системы могут влиять на блокировку отправки сообщений? никаких оповещений от системы не было.
проверь смтп
и да, файрвол может блокировать порт отправки