уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Сегодня решил немного поэкспериментировать с библиотекой Synapse и научиться отправлять письма, используя протокол SMTP (Simple Mail Transfer Protocol — протокол передачи почты). Тема эта достаточно интересная и полезная. Дело даже не в том, чтобы написать для себя почтовый клиент, коих миллионы. Подобные навыки работы с бибилиотекой могут потребоваться, например, если Вы захотитенаписать своего клиента для отправки сообщений в свой блог на ЖЖ, Blogger или LiveInternet — эти блог сервисы поддерживают публикацию новых постов по e-mail. Так что, полученные сегодня навыки несомнено должы принести Вам (мне точно) определенную пользу. Для работы с протоколом SMTP в Synapse можно использовать следующие модули библиотеки:

  1. smtpsend — содержит объект Tsmtpsend и ключевые методы для отправки электронных писем.
  2. mimemess — содержит объекты TMessHeader — заголовки сообщения; TMimeMess — сообщение;
  3. mimepart — содержит объект TMimePart для работы с частями сообщения, которые можно использовать для отправки по почте файлов.

Сегодня сосредоточимся на основной задаче — отправке текста. Так как именно для этого в свое время и был создан SMTP, а пересылкой файлов (аттачей) занимается не протокол, а расширение к протоколу —  MIME (Multupurpose Internet Mail Extentions, RFC-1521). Расширениями займемся позднее.

Итак, сегодня в наши задачи входит:

  1. Составить правильный заголовок сообщения
  2. Добавить в сообщение текст (plain text) или html-код
  3. Оправить сообщение на постовый ящик, используя заданый 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

Итак, в заголовки сообщения нам необходимо включить:

  1. Имя отправителя
  2. Адрес отправителя
  3. Список получателей (в нашем случае получатель будет один)

Подключаем к проекту модули 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-протоколами, но и не менее просто отправлять электронную почту.

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
110 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
ManGysITI
28/02/2010 01:44

Спасибо за интересную статью. Не подскажешь как реализовать отправку файла на мыло?

Станислав
Станислав
17/03/2010 18:07

Так же было интересно прочитать статью про отправку писем через SMTP сервер использующий SSL (gmail, yhoo, msn)

Slayer
Slayer
23/03/2010 05:05

А как проверить корректность отправки почты? Ошибка не выдаётся даже тогда, когда нет подключения к SMTP-серверу.

Андрей
Андрей
23/03/2010 16:31

А я-то как удивился! Я в Ubuntu использую Lazarus. Попробую в Windows ещё поковыряться Lazarus.

Станислав
Станислав
24/03/2010 17:40

И у меня такая же ерундень. Стоит Delphi 7 с стандартными настройками. Никаких обибок или сообщений не выдает. Наверное надо самому как-то проверять все события или читать их статус. Кстати, то что письмо не отправилось можно проверить посмотрев на то, что вернула функция Send Сам не пробовал, но должно работать.

Евгений
Евгений
05/04/2010 15:17

меня интересует как у From и To установить кодировку?

Msg.Header.Subject := Subject;//тема сообщения
Msg.Header.From := From; //имя и адрес отправителя
Msg.Header.ToList.Add(pTo); //имя и адрес получателя

Жека
Жека
05/06/2010 07:05

у меня это вообще не работает, пишу под xp библиотеку от сюда взял http://www.koders.com/info.aspx?c=ProjectInfo&pid=DEQAQ82QTXZZNDY4RT2N9NNSRB как не отправляю ничего не доходит, логин пытался и с @mail.ru и без него, не робит никак, код от сюда скопирован, не пойму в чем моя ошибка, можете что нибуть подсказать?

Алекс
Алекс
19/09/2010 17:25

Полдня мучился с отправкой сообщения с помощью компонентов 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) :… Подробнее »

Антон
Антон
02/10/2010 19:10

Пользуюсь сервисом Mail.ru. Если указать отправщика отличного от логина(логин test_test, а отправщик test_111@mail.ru), то почта не отслылается. А если отправщик test_test@mail.ru, то отлично работает. В чём проблемка может бытЬ?

Archil
Archil
08/10/2010 19:15

Vlad, очень помогают твои статьи Delphi+Synapse, большое спасибо!

Юрик
Юрик
20/10/2010 23:14

Есть сайты на которых регистрация происходит при помощи 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 чтобы правильно отправить этот запрос? я уже не один день пытаю реализовать, а так как новичок, нехера не выходит(((

Юрик
Юрик
21/10/2010 00:05

ОК. Спс за помощь. Буду дальше курить мануалы)) и попробую реализовать.

_scorpio_
_scorpio_
27/10/2010 19:29

А как быть с кодировками?
можно ли самому указывать кодировку темы и тела отправляемого письма?

_scorpio_
_scorpio_
27/10/2010 19:36

к примеру в utf-8

_scorpio_
_scorpio_
30/10/2010 05:47

благодарен за ответ, и ещё один вопрос:
можно ли программно запросить подтверждение прочтения письма, т.е. с помощью Synapse.
И как осуществить?

_scorpio_
_scorpio_
30/10/2010 16:52

ну к примеру в почтовой веб-агенте SquirrelMail version 1.4.17 на php есть возможность запрашивать подтверждение о принятии письма и об его прочтении… хотелось бы сделать тоже самое программно…
рыскал в интернете, вроде в обычном аутлуке от майкрософт тоже было такое

_scorpio_
_scorpio_
30/10/2010 17:54

это пока проблемно, так как я пока что не смотрел исходники, у меня провайдер такую почту для локальных клиентов сделал, и поцепил эту веб-морду… позже посмотрю, скину тот кусок

_scorpio_
_scorpio_
31/10/2010 02:43

Поэкспериментировав с отправляемыми письмами заметил, что в заголовках идет этот запрос. когда отправил письмо, оно пришло в таком виде: 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… Подробнее »

_scorpio_
_scorpio_
31/10/2010 02:45

скачал исходники, копаю дальше…

_scorpio_
_scorpio_
31/10/2010 03:19

вот что в исходниках [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… Подробнее »

_scorpio_
_scorpio_
31/10/2010 03:21

порубало код =)))

_scorpio_
_scorpio_
31/10/2010 03:39

на сколько я понял, нужно править исходники самого синапса, тоесть либо 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:… Подробнее »

_scorpio_
_scorpio_
31/10/2010 06:15

пол ночи за компом, решение: нужно редактировать исходники, а точнее mimemess.pas
и добавлять туда
[code]// запрос о прочтении
X-Confirm-Reading-To: отправитель@мейл.ру
Disposition-Notification-To: отправитель@мейл.ру
// запрос о получении
Return-Receipt-To:отправитель@мейл.ру[/code]

_scorpio_
_scorpio_
31/10/2010 21:54

можно просто вставить любой заголовок, а можно просто добавить функцию в исходники… вчера ночью так и сделал, сделал дополнительный параметр, который отвечает за прочтения письма в 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… Подробнее »

6ruse
6ruse
05/11/2010 23:10

Доброго времени суток! у меня не выходит отправить письмо на мыло, (mail.ru) прошу помощи! использую ОС Windows7

Pim
Pim
10/11/2010 04:57

Привет всем.Тут такой вопрос.Можно ли с помощью TIdSMTP проверить получение письма?Тут дето упамямнался этот компонент.Если можно,то как? А если нельзя так,то можно какнить попроще ,чем описывает Scorpio?

Pim
Pim
10/11/2010 15:19

Даже выше упомянутую задачу можно упростить до проверки существования почтового ящика.
У самого не получается,пожскажите пож.

_scorpio_
_scorpio_
10/11/2010 18:17

выше мною написанное способ, в котором нужно редактировать исходники синапса, можно конечно это сделать при помощью своих заголовков (тоесть при создании письма, нужно создать заголовок в котором существует запрос. в моём случае ответ на данный запрос приходит в виде письма о прочтении)
в теме нужно добавить строку или пару строк:
[code]// запрос о прочтении

X-Confirm-Reading-To: отправитель@мейл.ру

Disposition-Notification-To: отправитель@мейл.ру

// запрос о получении

Return-Receipt-To:отправитель@мейл.ру
[/code]

_scorpio_
_scorpio_
10/11/2010 18:18

тоесть не в теме, а в теле заголовка

_scorpio_
_scorpio_
10/11/2010 18:26

и ещё одно, при создании заголовка сначала желательно посмотреть обычный заголовок и тот что с запросом… так как разные мейл-агенты и я думаю разные способы у них… времени читать не было…)

Валерий
Валерий
01/05/2011 04:20

Выложите,пожалуйста,исходник программы, а то чёт не получается!!!

_scorpio_
_scorpio_
02/05/2011 17:16

увы исходники остались на винте, у которого электроника сгорела))

Антон
Антон
06/05/2011 13:11

А есть ли какая-то возможность избежать подвисания формы? Типо антифриза в Инди?

John
John
13/05/2011 08:21

Чтобы форма не висла, отправку письма лучше сделать в отдельном потоке…

Игорь
Игорь
13/05/2011 15:24

в инди можно было прописать «adr1@mail.ru; adr2@mail.ru»
Как отослать писмо на 2-3 адреса сразу?

Игорь
Игорь
13/05/2011 15:32

хм.. Нодо было справку посмотреть сначало.
Оказывается через запятую нужно писать адреса

_scorpio_
_scorpio_
14/05/2011 15:37

справка видимо написана не для тех кто методом тыка химичит

_scorpio_
_scorpio_
15/05/2011 22:03

но практика в который раз показывает что нужно учиться читать))))

tomat
tomat
07/06/2011 00:39

[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… Подробнее »

Гость
Гость
21/07/2011 08:21

А модули как определить, то?

Владимир
Владимир
10/09/2011 14:08

Ругается на строчку:
if length(TextBody)&gt;0 then

[Error] Unit1.pas(355): Illegal character in input file: ‘&’ ($26)

Илья
Илья
05/12/2011 12:18

добрый день.
с кодом вроде сложностей нет, все понятно. есть проблема с подключением модулей, негде не могу найти, сам раньше не пользовался. можно подробнее описать, как делается.

«…..Подключаем к проекту модули mimemess, mimepart, smtpsend…….. »

Спасибо. 

Илья
Илья
05/12/2011 13:22

с модулями разобрался.))
осталось решить 2 ошибки:
 [DCC Error] Unit1.pas(51): E2003 Undeclared identifier: ‘SendMail’
[DCC Fatal Error] otpravkasmtp.dpr(5): F2063 Could not compile used unit ‘Unit1.pas’

_scorpio_
_scorpio_
06/12/2011 17:21

программа не знает что такое «SendMail»

_scorpio_
_scorpio_
06/12/2011 17:23

Владимиру:
&gt; это <

_scorpio_
_scorpio_
06/12/2011 17:25

«…..Подключаем к проекту модули mimemess, mimepart, smtpsend…….. »
сами модули можно вкинуть в папку с проектом, или же установить синапс…
подключение модулей как выше писалось в uses
 

Илья
Илья
06/12/2011 22:37

с модулями разобрался, все подключил. ошибки тоже исправил, просто процедуру не в то место написал.
компилируется без замечаний, но сообщения не отправляются, на почту не приходят. пробовал windows 7 и ХР. пока не разобрался почему.

Илья
Илья
06/12/2011 22:49

вопрос: настройки безопасности системы могут влиять на блокировку отправки сообщений? никаких оповещений от системы не было.

_scorpio_
_scorpio_
10/12/2011 20:44

проверь смтп
и да, файрвол может блокировать порт отправки