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

В прошлой статье про использование Synapse для отправки писем мы разработали простенькое приложение для отправки текстового сообщения на e-mail.  Сегодня доработаем процедуру отправки письма, а именно, сделаем возможность отпраки на e-mail любых файлов (вложений).

Вкратце напомню содержание предыдущей статьи по Synapse и SMTP. Для работы с электронной почтой мы использовали следующие модули библиотеки: smtpsend, mimemess и mimepart.


Отправка писем происходила по следующей схеме:

  1. Создавался объект TMimeMess для которого в заголовках указывались тема письма, адрес отправителя и адреса получателей
  2. Далее для объекта TMimeMess создавался корневой элемент сообщения, имеющий тип TMimePart
  3. В TMimePart добавлялся либо текст, либо HTML-код
  4. Последовательно вызывались два метода: метод объекта TMimeMess для кодирования письма — EncodeMessage и метод SendToRaw для отправки сообщения.

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

Для добавления в тело сообщения файлов в Synapse предусмотрены следующие методы объекта TMimeMess:

function AddPartBinary(const Stream: TStream; const FileName: string; const PartParent: TMimePart): TMimepart;

добавляет в содержимое сообщения бинарные данные из потока. При этом MIME-тип для вложения определяется автоматически по  расширению файла (FileName), а все данные беруться из потока Stream.

function AddPartBinaryFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;

Также добавляет вложение как и AddPartBinary, но, в отличие от предыдущего метода не требует указания потока с данными. MIME-тип определяется автоматически.

Воспользуемся вторым методом, т.е. AddPartBinaryFromFile и отправим на почту, например, изображение. Процедуру для отправки письма возьмем из предыдущей статьи, но немного её дополним:

Procedure SendMail (pHost, pSubject, pTo, pFrom , pTextBody, pHTMLBody : string);
    var tmpMsg : TMimeMess;
        tmpStringList : TStringList;
        tmpMIMEPart : TMimePart;
begin
    tmpMsg := TMimeMess.Create;
    tmpStringList := TStringList.Create;
    try
        // Headers
        tmpMsg.Header.Subject := pSubject;
        tmpMsg.Header.From := pFrom;
        tmpMsg.Header.ToList.Add(pTo);
 
        // MIMe Parts
        tmpMIMEPart := tmpMsg.AddPartMultipart('alternate',nil);
 
        if length(pTextBody)>0 then
           begin
             tmpStringList.Text := pTextBody;
             tmpMsg.AddPartText(tmpStringList, tmpMIMEPart);
           end
        else
          begin
            tmpStringList.Text := pHTMLBody;
            tmpMsg.AddPartHTML(tmpStringList, tmpMIMEPart);
          end;
 
        if Form1.Edit1.Text<>'' then
            tmpMsg.AddPartBinaryFromFile(Form1.Edit1.Text,tmpMIMEPart)
        // кодируем и отправляем
        tmpMsg.EncodeMessage;
        smtpsend.SendToRaw(pFrom, pTo, pHost, tmpMsg.Lines, 'login', 'password');
 
    finally
        tmpMsg.Free;
        tmpStringList.Free;
    end;
end;

Мы добавили в процедуру всего две строки кода:

if Form1.Edit1.Text<>'' then
tmpMsg.AddPartBinaryFromFile(Form1.Edit1.Text,tmpMIMEPart)

Для того, чтобы отправить на почту файл. При этом указали корневой элемент tmpMIMEPart: TMimePart.
Аналогичным образом в письмо можно добавить любое количество, любых файлов. Остается только добавить, что в Synapse автоматически распознаются следующие MIME-типы и подтипы (по расширению файла):

Расширение Тип Подтип
AU audio basic
MP2 mpeg
MP3 mpeg
RA x-realaudio
SND basic
WAV x-wav
MID midi
AVI video x-msvideo
MOV quicktime
MPEG MPEG
MPG MPEG
QT quicktime
DOC application MSWord
EPS Postscript
PS Postscript
RTF RTF
PDF PDF
WPD Wordperfect5.1
ZIP ZIP
BMP image BMP
GIF GIF
JPEG JPEG
JPG JPEG
PNG PNG
TIF TIFF
TIFF TIFF

Для всех остальных файлов выставляется тип application с подтипом octet-stream. Если есть желание добавить в библиотеку распознавание других типов файлов, то дополните массив констант MimeType в модуле mimepart.

2 1 голос
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
23 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Сергей
Сергей
03/12/2010 19:18

Здравствуйте, подскажите, пожалуйста как отправить файл по http методом multipart/form-data? Пытался переделать этот пример, но безуспешно, нигде по этому вопросу информации не нашел.

мико
мико
25/05/2017 23:19
Ответить на  Vlad

if Form1.Edit1.Text<>» then
tmpMsg.AddPartBinaryFromFile(Form1.Edit1.Text,tmpMIMEPart)
Все время ошибку вводит

Сергей
Сергей
04/12/2010 20:43

делаю так:
[code]
StringList := TStringList.Create;
tmpMsg := TMimeMess.Create;
Http:=THTTPSend.Create;
tmpMIMEPart := tmpMsg.AddPartMultipart('alternate',nil);
data1:=TStringStream.Create('');
http.Clear;
http.MimeType:='multipart/form-data; boundary=—————————41184676334';
stringlist.Add('method=pos');
stringlist.Add('key=71a046f65057ff99dab062509ab4bad9');
tmpmsg.AddPartMess(stringlist,tmpMIMEPart) ;
tmpmsg.AddPartBinaryFromFile('1.jpg',tmpMIMEPart);
tmpmsg.Lines.SaveToStream(data1);

http.Document.LoadFromStream(data1);
[/code]
Но отправляется просто пустой post запрос

Сергей
Сергей
08/12/2010 14:59

Спасибо, разобрался, нашел нужную функцию в демо синапса и немного переделал [code] function ProxyHttpPostFile(const URL, FieldName, FileName: string; const Data: TStream; const ResultData: TStrings): Boolean; const CRLF = #$0D + #$0A; var HTTP: THTTPSend; Bound, s: string; begin Bound := IntToHex(Random(MaxInt), 8) + '_Synapse_boundary'; HTTP := THTTPSend.Create; try s := '--' + Bound + CRLF; s := s + 'content-disposition: form-data; name="method"'+ crlf+ crlf; s:= s +'post'+crlf; HTTP.Document.Write(Pointer(s)^, Length(s)); s := '--' + Bound + CRLF; s := s + 'content-disposition: form-data; name="key"'+ crlf+crlf; s:= s +'79bfdb771700dbd4bc280fedc0e11111'+crlf; HTTP.Document.Write(Pointer(s)^, Length(s)); s := '--' + Bound + CRLF; s := s +… Подробнее »

Сергей
Сергей
08/12/2010 15:01

p.s тэг [code] почему-то охватывает не все вложение

jskorvin
jskorvin
15/01/2011 20:22

Сергей, спасибо! Уже второй раз пригождается, примеров по синапсу в сети крайне мало =(

andyshark
andyshark
28/04/2011 00:47

Столкнулся с интересным приколом Синапса — в некоторых случаях почта НЕ отправляется. Обычно все проходило нормально всегда, пользовал SendToRaw и проблем не было. Единственное почему-то ну душа к TMimeMess не прикипела, в итоге пользую для формирования письма TSakMsg (не пинать — так хочется). Смысл один по любому — объьект формирует текст письма и потом его отправляю. И вот недавно попалось машин 5-7 которые не могут отправить письмо! Версии полностью идентичные, от операционки данная проблема точно не зависит, т.к. вылазит однозначно на ХР, про другие не помню. Но много других машин с ХР письма отправляют! Общей закономерности пока даже не заметил… Подробнее »

Виктор
Виктор
14/03/2012 17:19

Наблюдаю интересный факт:
Если принимаю письмо в  Outlook (2003 или Express) прикрепленного файла нет — только скрепка, если в TheBat!- все нориально (файл есть и читается). На нескольких машинах проверял.    XP, Dephi 2006.

Олег
Олег
20/07/2012 23:38

в кого не відправляються файли
потрібно стрічку
MIMEPart := Msg.AddPartMultipart(‘alternative’, nil);

замінити на

MIMEPart := Msg.AddPartMultipart(‘Mixed’, nil);

Dozent
Dozent
28/02/2013 12:23

Олег, не помогло:(

Tolyan249
Tolyan249
07/03/2013 21:43

А как можно посмотреть размер письма с вложением для отправки что бы установить progressbar в максимальное значение для отпрвки писма и смотреть сколько отправилось если отправляеться большое письмо с вложениями. При получении можно спросить размер письма у сервера , а тут как быть tmpMsg.size нет такой функции.

tolyan249
tolyan249
08/03/2013 08:25

Сделал так

stream:Tmemorystream.create;
list:=TstringList.create;
list:= tmpMsg.lines;
list.savetostream(stream);
progressbar1.max:=stream.size;
stream.free;

trackback

[…] Synapse в Delphi. Отправка писем с вложениями. […]

crazysmith
crazysmith
01/05/2013 22:59

Подскажите, пожалуйста, как отправить rar-файл во вложении, используя описанный метод? Добавление констант в mimepart типа (‘RAR’, ‘application’, ‘x-rar-compressed’) ничего не дало, как и (‘RAR’, ‘application’, ‘rar’) и (‘RAR’, ‘application’, ‘octet-stream’) — ничего не отправляется. При этом, файлы иных типов отсылаются прекрасно.

Александр
Александр
22/08/2013 17:27

Да тоже хотелось бы узнать по поводу RAR-файлов и еще почему то у меня проблемы с пересылкой вордовских doc-файлов

Александр
Александр
22/08/2013 19:25

Разобрался. crazysmith, для RAR-файлов у меня подошло (‘RAR’, ‘application’, ‘x-rar-compressed’), посмотрите может вы забыли изменить количество констант. Для doc я удалил существующую константу (‘DOC’, ‘application’, ‘MSWord’), а для docx добавил (‘DOCX’, ‘application’, ‘vnd.openxmlformats-officedocument.wordprocessingml.document’)

trackback

[…] заготовкой приложения, которую мы использовали при отправке писем с вложениями. Так как в работе используется ssl, то обязательно в uses […]

Владислав
Владислав
02/11/2015 16:13

Приветствую. Спасибо за полезные статьи по отправке почты по протоколу SMTP с помощью Synapse.

Недавно возникла проблема по теме данной статьи. Пытаюсь переслать файл формата PDF на произвольный ящик Яндекс.Почты по схеме, приведённой в этой статье. Однако вложение не доходит до получателя, хотя, например, файл формата TXT доходит успешно. Другие почтовые программы (например, Mozilla Thunderbird) отправляют PDF-файлы на такие ящики нормально. Исправить своими силами проблему не смог :(

Oleg
Oleg
21/11/2018 07:41

Для отправки больше одного файла:
Files1:array of string;
вставить по ходу строку
if length(Files1)=0 then PartTyp:=’alternative’ else PartTyp:=’multipart’;
перед MIMEPart := Msg.AddPartMultipart(PartTyp, nil);

if length(HTMLBody)0 then//а если вообще нет никаких сообщений, только тема и файлы в аттаче
перед begin
StringList.Text := HTMLBody;
Msg.AddPartHTML(StringList, MIMEPart);
end;

и саму отправку
if length(Files1)>0 then
for i:=0 to High(Files1)do
if FileExistsUTF8(Files1[i]) then
begin
Msg.AddPartBinaryFromFile(Utf8ToAnsi(Files1[i]), MIMEPart);
memLog.Lines.Add(‘Вложение ‘+inttostr(i)+’> ‘+Files1[i]);
end;