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

phpmailer

PHPMailer – очень удобная и популярная библиотека для отправки e-mail сообщений с вашего сайта. В этой статье рассказаны основные настройки библиотеки и приведены примеры кода для отправки сообщений. PHPMailer имеет в своем ассортименте пожалуй всё, что можно пожелать от работы с почтой: отправка разными способами, через разные серверы в т.ч. через smtp, возможность шифровать и подписывать ваши письма, чтобы не попадали в спам и многое другое.

Скачать библиотеку PHPMailer можно с https://github.com/PHPMailer/PHPMailer (кнопка “Code” -> “Download ZIP”).

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

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

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

// Подключаем библиотеку PHPMailer
use PHPMailer\PHPMailer\PHPMailer;
require 'PHPMailer/PHPMailer.php';
 
// Создаем письмо
$mail = new PHPMailer();
$mail->setFrom('test@domain.ru', 'Иван Иванов'); // от кого (email и имя)
$mail->addAddress('test@ya.ru', 'Вася Петров');  // кому (email и имя)
$mail->Subject = 'Тест';                         // тема письма
// html текст письма
$mail->msgHTML("<html><body>
                <h1>Здравствуйте!</h1>
                <p>Это тестовое письмо.</p>
                </html></body>");
// Отправляем
if ($mail->send()) {
  echo 'Письмо отправлено!';
} else {
  echo 'Ошибка: ' . $mail->ErrorInfo;
}  

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

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

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

// Подключаем библиотеку PHPMailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
require 'PHPMailer/PHPMailer.php';
require 'PHPMailer/SMTP.php';
 
// Создаем письмо
$mail = new PHPMailer();
$mail->isSMTP();                   // Отправка через SMTP
$mail->Host   = 'smtp.yandex.ru';  // Адрес SMTP сервера
$mail->SMTPAuth   = true;          // Enable SMTP authentication
$mail->Username   = 'login';       // ваше имя пользователя (без домена и @)
$mail->Password   = 'password';    // ваш пароль
$mail->SMTPSecure = 'ssl';         // шифрование ssl
$mail->Port   = 465;               // порт подключения
 
$mail->setFrom('login@ya.ru', 'Иван Иванов');    // от кого
$mail->addAddress('test@ya.ru', 'Вася Петров'); // кому
 
$mail->Subject = 'Тест';
$mail->msgHTML("<html><body>
                <h1>Здравствуйте!</h1>
                <p>Это тестовое письмо.</p>
                </html></body>");
// Отправляем
if ($mail->send()) {
  echo 'Письмо отправлено!';
} else {
  echo 'Ошибка: ' . $mail->ErrorInfo;
}

Отправка писем через Google имеет один нюанс: нужно в аккаунте google разрешить доступ ненадежным приложениям. Для этого нужно зайти в свой аккаунт https://myaccount.google.com, перейти в безопасность, зайти в раздел “Ненадежные приложения, у которых есть доступ к аккаунту” и там переключить в “Разрешено”. На момент написания статьи это страница https://myaccount.google.com/u/0/lesssecureapps.

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

$mail->Host   = 'smtp.gmail.com';  // Адрес SMTP сервера
$mail->SMTPAuth   = true;          // Enable SMTP authentication
$mail->Username   = 'login';       // ваше имя пользователя
$mail->Password   = 'password';    // ваш пароль
$mail->SMTPSecure = 'ssl';         // шифрование ssl
$mail->Port   = 465;               // порт подключения

Если первый раз запускаете программу отправки через smtp, тогда желательно перед отправкой дополнительно использовать $mail->SMTPDebug = 1; чтобы получать все сообщения клиента и smtp-сервера, т.е. на экран выведется весь процесс подключения, авторизации и т.д., что очень полезно для отладки вашей программы.

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

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

// Подключаем библиотеку PHPMailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'PHPMailer/PHPMailer.php';
require 'PHPMailer/Exception.php';
 
// Создаем письмо
$mail = new PHPMailer;
$mail->CharSet = 'UTF-8';
$mail->setFrom('test@test.ru', 'Иван Иванов');     // от кого
$mail->addReplyTo('test@test.ru', 'Иван Иванов');  // обратный адрес
$mail->addAddress('test@ya.ru', 'Вася Петров');    // кому
$mail->Subject = 'Тест';                           // тема
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);  // получаем "тело" письма из файла
$mail->AltBody = 'Письмо обычным текстом';  // письмо обычным текстом, если клиент не поддерживает html
$mail->addAttachment('my_file.txt');        // прикрепляем один файл
$mail->addAttachment('phpmailer.jpg');      // прикрепляем второй файл
 
// Отправляем
if ($mail->send()) {
  echo 'Письмо отправлено!';
} else {
  echo 'Ошибка: ' . $mail->ErrorInfo;
}

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

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

// Подключаем библиотеку PHPMailer
use PHPMailer\PHPMailer\PHPMailer;
require 'PHPMailer/PHPMailer.php';
 
//Создаем письмо
$mail = new PHPMailer;
$mail->IsHTML(true);
$mail->setFrom('test@test.ru', 'Иван Иванов');
$mail->addAddress('test@ya.ru', 'Вася Петров');
$mail->Subject = 'Test';
$mail->AddEmbeddedImage('phpmailer.jpg','testImage');
$mail->Body = '<p>Изображение в html-коде <img src="cid:testImage"></p>';
 
// Отправляем
$mail->send();

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

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

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

$mail->SMTPSecure = false;
$mail->SMTPAutoTLS = false;

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

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

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

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

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

openssl genrsa -out test-private.pem 1024
openssl rsa -in test-private.pem -out test-public.pem -pubout

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

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

$domain = 'test.ru';                   // ваш домен
$privatekeyfile = 'test-private.pem';  // имя файла, в который будет записан приватный ключ
$publickeyfile = 'test-public.pem';    // имя файла, в который будет записан публичный ключ
 
if (file_exists($privatekeyfile)) {
  echo "<p>Using existing keys</p>";
  $privatekey = file_get_contents($privatekeyfile);
  $publickey = file_get_contents($publickeyfile);
} else {
  echo "<p>Create keys</b>";
  $pk = openssl_pkey_new(
      [
          'digest_alg' => 'sha256',
          'private_key_bits' => 2048,
          'private_key_type' => OPENSSL_KEYTYPE_RSA,
      ]
  );
  openssl_pkey_export_to_file($pk, $privatekeyfile);
  $pubKey = openssl_pkey_get_details($pk);
  $publickey = $pubKey['key'];
  file_put_contents($publickeyfile, $publickey);
  $privatekey = file_get_contents($privatekeyfile);
}
echo "<p>Private key (keep this private!):</p><pre>" . $privatekey . "</pre>";
echo "<p>Public key:</p><pre>" . $publickey . "</pre>";

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

Добавление 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 перед отправкой письма и оно будет подписано. Думаю, на приведенном примере будет всё понятно:

// Подключаем библиотеку
use PHPMailer\PHPMailer\PHPMailer;
require 'PHPMailer/PHPMailer.php';
 
// Создаем письмо
$mail = new PHPMailer;
$mail->CharSet = 'UTF-8';
$mail->setFrom('test@test.ru');
$mail->addAddress('test@ya.ru');
$mail->Subject = 'Это тест';
$mail->msgHTML('<p>Это тест</p>');
 
// Настройка DKIM подписи
$mail->DKIM_domain = 'test.ru';
$mail->DKIM_private = 'test-private.pem';
$mail->DKIM_selector = 'mail';
 
// Отправляем
$mail->send();

Разумеется, test.ru вы должны поменять на имя своего домена, а test-private.pem на полный путь и имя файла приватного ключа, который был создан на этапе генерации ключей.

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

Источник