В прошлой статье про использование Synapse для отправки писем мы разработали простенькое приложение для отправки текстового сообщения на e-mail. Сегодня доработаем процедуру отправки письма, а именно, сделаем возможность отпраки на e-mail любых файлов (вложений).
Вкратце напомню содержание предыдущей статьи по Synapse и SMTP. Для работы с электронной почтой мы использовали следующие модули библиотеки: smtpsend, mimemess и mimepart.
Отправка писем происходила по следующей схеме:
- Создавался объект TMimeMess для которого в заголовках указывались тема письма, адрес отправителя и адреса получателей
- Далее для объекта TMimeMess создавался корневой элемент сообщения, имеющий тип TMimePart
- В TMimePart добавлялся либо текст, либо HTML-код
- Последовательно вызывались два метода: метод объекта 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 | |
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.
Здравствуйте, подскажите, пожалуйста как отправить файл по http методом multipart/form-data? Пытался переделать этот пример, но безуспешно, нигде по этому вопросу информации не нашел.
Так, а в чём там проблема? Вставляете заголовок в запрос, каждую часть разделяете грницей + пустая строка и отправляете.
if Form1.Edit1.Text<>» then
tmpMsg.AddPartBinaryFromFile(Form1.Edit1.Text,tmpMIMEPart)
Все время ошибку вводит
Символ — » лишний
делаю так:
[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 запрос
А зачем вы используете TMimeMess вместе с HTTPSend? Есть же нормальный класс TSMTPSend для отправки писем с вложениями. Это первое. Второе, boudary вы определили, а где используется его значение (boundary=—————————41184676334)? Не проще ли тогда уже использовать код, который я приводил здесь?
Спасибо, разобрался, нашел нужную функцию в демо синапса и немного переделал [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 +… Подробнее »
p.s тэг [code] почему-то охватывает не все вложение
Сергей, спасибо! Уже второй раз пригождается, примеров по синапсу в сети крайне мало =(
Столкнулся с интересным приколом Синапса — в некоторых случаях почта НЕ отправляется. Обычно все проходило нормально всегда, пользовал SendToRaw и проблем не было. Единственное почему-то ну душа к TMimeMess не прикипела, в итоге пользую для формирования письма TSakMsg (не пинать — так хочется). Смысл один по любому — объьект формирует текст письма и потом его отправляю. И вот недавно попалось машин 5-7 которые не могут отправить письмо! Версии полностью идентичные, от операционки данная проблема точно не зависит, т.к. вылазит однозначно на ХР, про другие не помню. Но много других машин с ХР письма отправляют! Общей закономерности пока даже не заметил… Подробнее »
Наблюдаю интересный факт:
Если принимаю письмо в Outlook (2003 или Express) прикрепленного файла нет — только скрепка, если в TheBat!- все нориально (файл есть и читается). На нескольких машинах проверял. XP, Dephi 2006.
в кого не відправляються файли
потрібно стрічку
MIMEPart := Msg.AddPartMultipart(‘alternative’, nil);
замінити на
MIMEPart := Msg.AddPartMultipart(‘Mixed’, nil);
Олег, не помогло:(
А как можно посмотреть размер письма с вложением для отправки что бы установить progressbar в максимальное значение для отпрвки писма и смотреть сколько отправилось если отправляеться большое письмо с вложениями. При получении можно спросить размер письма у сервера , а тут как быть tmpMsg.size нет такой функции.
Как вариант, можно и самому посчитать сколько будет занимать все письмо вместе с вложением…не вижу вообще никаких проблем: размер файлов-вложений узнать проще простого, размер отправляемого текста тем более.
Сделал так
stream:Tmemorystream.create;
list:=TstringList.create;
list:= tmpMsg.lines;
list.savetostream(stream);
progressbar1.max:=stream.size;
stream.free;
[…] Synapse в Delphi. Отправка писем с вложениями. […]
Подскажите, пожалуйста, как отправить rar-файл во вложении, используя описанный метод? Добавление констант в mimepart типа (‘RAR’, ‘application’, ‘x-rar-compressed’) ничего не дало, как и (‘RAR’, ‘application’, ‘rar’) и (‘RAR’, ‘application’, ‘octet-stream’) — ничего не отправляется. При этом, файлы иных типов отсылаются прекрасно.
Да тоже хотелось бы узнать по поводу RAR-файлов и еще почему то у меня проблемы с пересылкой вордовских doc-файлов
Разобрался. crazysmith, для RAR-файлов у меня подошло (‘RAR’, ‘application’, ‘x-rar-compressed’), посмотрите может вы забыли изменить количество констант. Для doc я удалил существующую константу (‘DOC’, ‘application’, ‘MSWord’), а для docx добавил (‘DOCX’, ‘application’, ‘vnd.openxmlformats-officedocument.wordprocessingml.document’)
[…] заготовкой приложения, которую мы использовали при отправке писем с вложениями. Так как в работе используется ssl, то обязательно в uses […]
Приветствую. Спасибо за полезные статьи по отправке почты по протоколу SMTP с помощью Synapse.
Недавно возникла проблема по теме данной статьи. Пытаюсь переслать файл формата PDF на произвольный ящик Яндекс.Почты по схеме, приведённой в этой статье. Однако вложение не доходит до получателя, хотя, например, файл формата TXT доходит успешно. Другие почтовые программы (например, Mozilla Thunderbird) отправляют PDF-файлы на такие ящики нормально. Исправить своими силами проблему не смог :(
Для отправки больше одного файла:
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;