В статье Как сделать отправку письма? рассказывалось об отправке простого текстового письма. Описанные в ней правила следует учитывать и при отпраке письма с вложением. Посмотрим, как можно создать такое письмо.
Прежде всего в заголовках письма с вложением должен быть указан MIME-тип multipart/mixed
, например:
MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="::"
Параметр boundary является обязательным и определяет состоящий из символов разделитель, используемый в строке-разделителе для разграничения отдельных частей письма. Значение данного параметра не обязательно заключать в кавычки, но если этого не сделать, то, например, знак двоеточия в разделителе использовать уже будет нельзя. В строке-разделителе должны находиться два дефиса перед значением разделителя, а в последней такой строке – еще и два дефиса после значения разделителя. Необходимо выбирать такой разделитель, при котором строка-разделитель не присутствовала ни в одной части письма. Чтобы не тратить ресурсы на формирование разделителя, удовлетворяющего данному условию, можно кодировать все части письма в кодировке Base64, в алфавите которой отсутствует символ дефис. При этом добавлять дефисы в сам разделитель не требуется, потому что они входят в состав строки-разделителя.
Полный текст письма с одним вложением имеет следующий формат:
Пролог --разделитель Заголовки текстовой части письма Содержимое текстовой части письма --разделитель Заголовки вложения Содержимое вложения --разделитель-- Эпилог
Если вложений несколько, они должны размещаться перед последней строкой-разделителем и отделяться друг от друга обычной строкой-разделителем.
Пролог и эпилог обычно представляют собой небольшие пояснительные тексты в кодировке US-ASCII для получателей, использующих устаревшие почтовые клиенты, не поддерживающие письма с вложениями. Пролог или эпилог могут отсутствовать, однако строки-разделители, которыми они отделяются от других частей письма, должны присутствовать обязательно. Эпилог часто отсутствует. Если пролог или эпилог отсутствуют, то могут отсутствовать и соответствующие разделители строк "\r\n"
после пустого пролога или перед пустым эпилогом.
В каждой части письма между заголовками и содержимым должна находиться пустая строка. У текстовой части письма заголовки могут отсутствовать, если ее содержимое представляет собой незакодированный текст в кодировке US-ASCII, но и в этом случае перед содержимым должна находиться пустая строка.
Пример типичного набора заголовков текстовой части письма:
Content-Transfer-Encoding: base64 Content-Type: text/plain; charset=utf-8
Пример типичного набора заголовков вложения:
Content-Transfer-Encoding: base64 Content-Type: text/plain; name="file.txt" Content-Disposition: attachment; filename="file.txt"
Использование в заголовке вложения Content-Type параметра name с исходным (рекомендуемым) именем файла вместо параметра charset, определяющего символьную кодировку содержимого, связано с тем, что клиент прежде всего должен предоставлять пользователю возможность сохранения вложения в виде файла, а не отображать его содержимое. Такая подмена параметра, вероятно, обусловлена тем, что исторически заголовок Content-Type появился раньше заголовка Content-Disposition, явно определяющего, должно ли отображаться содержимое вложения. Этим же, вероятно, обусловлено и дублирование имени файла в заголовках.
Для отображения содержимого вложения в «основном потоке» нужно указать в заголовке Content-Disposition значение inline вместо значения attachment, при этом также можно использовать параметр filename.
В текстовой части письма можно использовать не только тип text/plain, но и тип text/html, как это было описано для простого текстового письма. Более того, для совместимости можно объединить обе текстовые версии с помощью контейнера типа multipart/alternative, размещенного в текстовой части письма. Заголовок и содержимое контейнера данного типа имеют формат, аналогичный описанному выше (версия типа text/plain как более простая в плане совместимости должна располагаться первой):
--разделитель-1 Content-Type: multipart/alternative; boundary="разделитель-2" --разделитель-2 Заголовки первой версии Содержимое первой версии --разделитель-2 Заголовки второй версии Содержимое второй версии --разделитель-2-- --разделитель-1
Строки-разделители внешнего контейнера добавлены для большей наглядности.
Попробуйте выполнить следующий код, предварительно сохранив его в файле в кодировке UTF-8 с указанием корректного значения $to:
<?php $to='user@example.com'; $subject='=?utf-8?B?'.base64_encode('Письмо с вложением').'?='; $message='--::'."\r\n". 'Content-Transfer-Encoding: base64'."\r\n". 'Content-Type: text/plain; charset=utf-8'."\r\n". "\r\n". chunk_split(base64_encode('Файл прилагается!'))."\r\n". '--::'."\r\n". 'Content-Transfer-Encoding: base64'."\r\n". 'Content-Type: text/plain; name="file.txt"'."\r\n". 'Content-Disposition: attachment; filename="file.txt"'."\r\n". "\r\n". chunk_split(base64_encode('Hello world!'))."\r\n". '--::--'; $headers='MIME-Version: 1.0'."\r\n". 'Content-Type: multipart/mixed; boundary="::"'; mail($to,$subject,$message,$headers); ?>Done
После результата, возвращаемого функцией chunk_split, нет необходимости добавлять разделитель строк \r\n
, т.к. функция добавляет разделитель строк непосредственно в конец результата. Однако при кодировании содержимого письма или отдельной его части в кодировке Base64 после кода содержимого вполне допустимо наличие дополнительных разделителей строк.
Комментарии: 0
Отправить комментарий