Как отправить файл php mail

Обновлено: 05.07.2024

Письмо, содержащее прикрепленный файл, несколько отличается от простого.
В нем добавляются некоторые заголовки, и немного меняется само построение,
хотя несомненно само письмо остается текстовым файлом. Но давайте все по порядку.

Если мы хотим отослать письмо с прикрепленными файлами, то необходимо использовать заголовок content-type: multipart/mixed, который обозначает, что письмо состоит из нескольких частей, каждая из которых содержит свой заголовок content-type. Для обозначения границы этих частей необходимо использовать параметр boundary, который еще называется маркером границы.
Значением этого параметра может служить любая строка. Но надо учесть, что она должна быть уникальной и не встречалась в теле письма. Иначе письмо может быть неправильно разбито на части.

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

Если у нас идет часть с текстом, то надо заголовок content-transfer-encoding присвоить значение quoted-printable, либо 7bit, либо 8bit. Для части с файлом этот заголовок должен быть равен base64.

Заголовок content-disposition, присутствующий во второй части, указывает, как почтовой программе следует отобразить данную часть письма. Он может принимать значение attachment (этот участок не является частью письма, а просто прикреплен к нему в виде файла) и inline (включение, которое используется непосредственно в письме, например, картинка, вставляемая в html).

В первой части заголовком
content-type: text/plain; charset="windows-1251"

указали, что это простой текст с кодировкой windows.
Во второй же части заголовком
content-type: application/x-rar-compressed; name="file.rar"

В случае, если заранее не известно, какой тип файла отправляем, или формат файла не является стандартным, следует заголовку content-type присвоить значение application/octet-stream.
content-type: application/octet-stream; name="file.dat"

Прикрепленные файлы должны быть размещены в письме в формате base64.
Преобразовать файл в этот формат можно при помощи функции base64_encode():
// Открываем файл для чтения в бинарном формате
$file=fopen("file.zip", "rb");
// Считываем его в строку $str_file
$str_file=fread($file,filesize("file.zip"));
// Преобразуем эту строку в base64-формат
$str_file=base64_encode($str_file);

Теперь переменную $str_file, которая содержит файл, можно вставлять в письмо.

Для окончательного закрепления материала напишем функцию, которая отправляет письмо в
html-формате по указанному адресату с прикрепленным файлом:


PHPMailer обновился и инструкция к прошлой версии не актуальна, хотя вы также можете использовать прикреплённые файлы в той инструкции. Работать будет.


О чем эта инструкция.

Это инструкция по добавлению на ваш сайт PHPMailer и отправки писем с прикреплёнными файлами к вам на почту без перезагрузки страницы.

Здесь будет инструкция для более простой базовой версии формы, без анимации и валидаций на чистом JavaScript. Навороченную версию формы (та, что на картинке) вы можете скачать по ссылке в конце статьи.

1. Скачиваем PHPMailer


В начале кликаем по “Clone or Download”, затем по “Download ZIP”

Во всём архиве нам нужны только 3 файла:

Всё остальн о е, что хранится на Github — на*уй не нужно, можете удалять.

2. Удаляем из файлов весь хлам

Этот пункт вы можете пропустить. Он не является обязательным

Файлы, написанные разработчиками PHPMailer, содержат немереное количество мусора, состоящего из одних комментариев (зачем?!). Вес этих трёх файлов вместе с комментариями равен 196кб, после удаления комментов вес составит 72кб. Почти в 3 раза…

  1. Открываете файл PHPMailer.php
  2. Копируете содержимое файла
  3. Вставляете в форму на сайте php-minify и жмёте “COMPRESS”
  4. Результат пересохраняете в новом файле с тем же названием

Процедуру повторяете со всеми тремя файлами.

Для наглядности файл Exception.php


Слева файл до сжатия, справа он же после удаления мусора

3. Перемещаем файлы в проект

И теперь помещаем эти 3 файла в наш проект. Я создал специально для этих файлов папку под названием phpmailer


4. Создаём файл конфигурации

Создадим файл send.php с таким содержанием

Здесь вам нужно отредактировать эти поля под себя:

Нужно использовать не пароль от самой почты, а “Пароль приложения”. В настройках вашей почты, будь то Gmail, Yandex или Mailru— есть раздел “Пароли приложений”, где вы можете специально создать отдельный сгенерированный пароль для PHPMailer.

Сохраняем этот файл send.php и помещаем его в корень сайта

5. Создаём HTML форму

Теперь поместим эту форму в нужное место на вашем сайте

Обратите внимание на onsubmit. Там вторым аргументом должно быть указано имя файла, то есть send.php.

6. Прописываем JavaScript

Нужно теперь просто где-то в коде разместить эту функцию. Вы можете её скопировать в свой script файл, который уже подключён в <head>, либо вставить его после закрывающего тега </body>.

7. Всё (почти)

Форма у вас должна выглядеть вот так:


8. Почему ошибка?

Это очень частый вопрос, где я с полной уверенностью могу сказать: 60% причин ошибок — это ваш хостинг, 30% — ваша почта, 9% — вы неверно указали данные от почты, а 1% причин —ты, сука, даун, который решил изменить код, а потом начинаешь искренне удивляться, почему ничерта не работает.

Чтобы узнать, в чём причина, нужно раскомментировать вот эту строчку кода (убрать //):


Причина: Error: authentication failed: Invalid user or password! , то есть неверно указаны данные почты.

Если для вас эти строчки, как иероглифы, и уверены, что ошибки в написании данных почты нет, то отправляете два письма: одно в тех.поддержку вашего хостинга, второе в тех.поддержку вашей почты с таким содержанием:

Через некоторое время они ответят и письма начнут нормально уходить.

После того, настоятельно рекомендую снова закомментировать строчку c $mail->SMTPDebug = 2

У этой формы есть минус: нет защиты от спама. Каптчу вам нужно отдельно подключать

При создании нашего php кода для отправки функции mail() мы учтём моменты выше, чтобы минимизировать процент попадания письма в папку «Спам».

Создание файла mail.php и основных переменных

Создадим в корне сайта файл mail.php и добавим в него следующий код.

Мы создали 4 переменных:

  • $admin_email - список получателей (через запятую);
  • $form_subject - тема письма;
  • $project_name - отправитель письма;
  • $html - начало HTML письма (далее мы его будет дополнять контентом).

Формирование текстовой версии письма (text/plain) и таблицы для HTML-версии

Затем в переменную $plain_text добавим текстовую версию. Всё это сделаем в цикле foreach . Также предусмотрим возможный вариант $_POST['value'] в виде массива (значений чекбоксов).

Таким образом, мы обработали полученные с фронтенда данные формы.

В первом пункте данной статьи мы создали файл mail.php и объявили основные переменные для нашего файла, в числе которых была переменная $html . Во втором пункте мы создали переменную $table , в которой сформировали HTML-таблицу из name и value . Теперь нам необходимо добавить таблицу с данными к переменной $html .

Создание заголовков почтового письма

Сформируем заголовки в виде массива (для PHP >= 7.2).

Для более старых версий php необходимо создавать $headers без использования массива. В конце каждой строки нужно добавлять \r\n

На что стоит обратить внимание:

Желательно чтобы заголовки From, Reply-To и Return-Path совпадали.

Только вместо Return-Path мы укажем обратный адрес e-mail в 5 параметре функции mail() . Это позволит избежать проблему №4 в начале данной статьи.

Отправка mail() в php с проверкой

Итоговый код

В результате наш mail.php должен выглядеть примерно так:

PHP_ORIG_SCRIPT

Для удаления заголовка X-PHP-Originating-Script существует 2 способа
(если знаете ещё, поделитесь в комментариях):

  1. редактирование php.ini
  2. редактирование .htaccess

Чтобы не попасть в папку спам мы сделали всё от нас зависящее.
Остальные настройки вам необходимо делать на сервере: SPF, DKIM, DMARC, PTR.

Надеюсь, вам понравилась данная информация. Если вам интересна тема web-разработки, то можете следить за выходом новых статей в Telegram.

Для начала разберу пару простых примеров, чтобы было понятно, как отправлять письма с помощью PHPMailer.

Отправка писем через функцию mail() с помощью PHPMailer

Если вы хотите отправлять письма со своего хостинга через свой почтовый сервер, то всё довольно просто и будет выглядеть примерно так:

Как видим, всё довольно просто: подключаем библиотеку, заполняем от кого, кому, тему и текст письма и отправляем. Отправка писем таким способом будет работать только с почтовых адресов вашего домена (если только они не привязаны к другим почтовикам).

Отправка писем через SMTP с помощью PHPMailer на примере Yandex и Google


Дальше в php-программе отправка писем через PHPMailer происходит аналогично как через yandex, нужно только заменить настройки SMTP так:

Отправка письма с вложением с помощью PHPMailer

Здесь всё довольно просто, нужно лишь использовать метод addAttachment. Приведу пример, заодно продемонстрировав еще несколько дополнительных возможностей:

Адресов получателей можно добавить несколько с помощью addAddress. Или, если необходимо, можно наоборот, очистить все адреса получателей методом clearAddresses(). Очистить все вложения можно с помощью clearAttachments().

Так же можно использовать AddEmbeddedImage чтобы добавить в письмо вложение (обычно изображения), которое предназначено для использования в html-коде и не будет доступно для скачивания. Пример использования картинки в письме, не доступной для скачивания:

Таким образом, вы можете отправлять письма с изображениями, которые есть только в теле письма, но их нельзя скачать как вложение. Эти изображения можно использовать в любом месте html-кода письма, нужно лишь указывать вместо url-адреса cid изображения, который вы использовали в AddEmbeddedImage.

Отправка подписанного и зашифрованного письма через PHPMailer

По-умолчанию, PHPMailer шифрует все отправляемые письма. Отключить шифрование письма можно только при отправке писем через SMTP использовав код:

Чтобы подписать письмо подписью DKIM, необходимо выполнить несколько действий:

  • Сгенерировать приватный (private) и публичный (public) ключи для вашего домена
  • Добавить DNS-запись для домена типа TXT с публичным ключом
  • Настроить DKIM подпись в PHPMailer перед отправкой письма

Теперь опишу каждый шаг немного подробнее.

Генерация приватного и публичного ключей

Если у вас Linux-хостинг и есть доступ в Shell, то сгенерировать файлы ключей проще простого, нужно выполнить всего 2 команды с обычными правами своего пользователя:

Соответственно, test-private.pem и test-public.pem - это приватный и публичный ключи. Сохранить их нужно в папке, которая будет не доступна посетителям сайта или кому-то еще кроме вас.

Если нет возможности выполнить команды в shell, тогда чтобы сгенерировать приватный (private) и публичный (public) ключи и сохранить их в файлы, можно воспользоваться следующим кодом:

Внимание! Не забудьте убедиться, что папка, в которую будут сохраняться файлы, доступна для записи.

Добавление DNS-записи с публичным ключом

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

Нужно добавить DNS-запись следующего вида:

Имя записи: mail._domainkey.test.ru. (в конце точка ".")

TTL: 3600 (или какое будет по-умолчанию)

Тип записи: TXT

Значение: v=DKIM1; h=sha256; t=s; p=ВАШ_ПУБЛИЧНЫЙ_КЛЮЧ

В имени записи test.ru нужно заменить на имя вашего домена. Слова "ВАШ_ПУБЛИЧНЫЙ_КЛЮЧ" вы заменяете на текст, который вы получили на предыдущем шаге после "Public key", без "-----BEGIN PUBLIC KEY-----" и "-----END PUBLIC KEY-----", только сам ключ. При этом все строчки ключа нужно соединить в одну длинную строку, чтобы переводов строки не было.

Настройка подписи DKIM в PHPMailer и отправка письма

Теперь осталось лишь сделать несколько настроек PHPMailer перед отправкой письма и оно будет подписано. Думаю, на приведенном примере будет всё понятно:

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

Читайте также: