Отправка почты в PHP: с чего начать новичку
Как отправить первое письмо из PHP: встроенная mail(), почему она чаще всего попадает в спам, и рабочая связка PHPMailer с SMTP-аутентификацией. С проверками на каждом шаге.

К концу этого гайда вы отправите письмо из PHP-скрипта через SMTP-сервер и увидите его в своём ящике, а не в спаме. На настройку с нуля уйдёт около 20–30 минут, если у вас уже есть почтовый ящик с доступом по SMTP. Работаем на PHP 8.1+ и библиотеке PHPMailer 6.x — на момент написания это актуальная мажорная версия.
Что нужно иметь до начала
Прежде чем писать код, соберите доступы. Без них вы упрётесь на середине.
- PHP 8.1 или новее с менеджером зависимостей Composer. Проверьте:
php -vиcomposer --versionдолжны вывести номера версий, а не «command not found». - Почтовый ящик с доступом по SMTP. Подойдёт Яндекс, Mail.ru, Gmail или ящик на вашем хостинге. Для Gmail и Яндекса при включённой двухфакторной аутентификации обычный пароль не сработает — нужен пароль приложения (создаётся в настройках безопасности ящика).
- Параметры SMTP вашего провайдера: адрес сервера, порт и тип шифрования. Их всегда публикуют в справке почтовой службы. Не угадывайте — сверьтесь с документацией провайдера.
Почему не стоит начинать со встроенной mail()
В PHP есть встроенная функция mail(), и первый порыв — использовать её:
<?php
// Так делать не надо на реальном проекте
mail('user@example.com', 'Тема', 'Текст письма');
Функция вернёт true — и это обманчиво. true означает лишь то, что письмо принято локальным агентом отправки (обычно sendmail), а не то, что оно дошло. У mail() три беды: она не умеет SMTP-аутентификацию, поэтому письма с shared-хостинга без настроенных SPF/DKIM почти гарантированно летят в спам; она плохо работает с UTF-8 и вложениями без ручной сборки заголовков; и она ничего не сообщает о том, почему письмо не дошло. Для учебного «hello world» сойдёт, для чего угодно серьёзнее — нет.
Правило простое: если письмо должен получить живой человек, отправляйте его через SMTP с аутентификацией, а не через голую mail(). Это единственный способ, при котором почтовые сервисы вам доверяют.
Ставим PHPMailer
PHPMailer — самая распространённая библиотека для отправки писем в PHP. Она берёт на себя SMTP, кодировки, вложения и HTML-письма.
- В корне проекта выполните:
Должна появиться папкаcomposer require phpmailer/phpmailervendor/и файлcomposer.jsonс записью о зависимости. Если Composer ругается на версию PHP — обновите PHP или проверьтеcomposer.json. - Убедитесь, что установлено расширение для работы через защищённое соединение. Выполните
php -m | grep openssl— в выводе должна быть строкаopenssl. Без него SMTP по TLS не заработает.
Первое письмо через SMTP
Создайте файл send.php. Параметры сервера ниже — заглушки, подставьте свои из справки провайдера.
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require __DIR__ . '/vendor/autoload.php';
$mail = new PHPMailer(true); // true — включить исключения при ошибках
try {
// Настройки SMTP
$mail->isSMTP();
$mail->Host = 'smtp.example.com'; // адрес SMTP-сервера провайдера
$mail->SMTPAuth = true;
$mail->Username = 'you@example.com'; // логин почтового ящика
$mail->Password = 'YOUR_APP_PASSWORD'; // пароль приложения, не хранить в коде
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; // шифрование
$mail->Port = 465; // порт под выбранное шифрование
$mail->CharSet = 'UTF-8'; // чтобы кириллица не рассыпалась
// Кто отправляет и кому
$mail->setFrom('you@example.com', 'Моё приложение');
$mail->addAddress('user@example.com', 'Получатель');
// Содержимое
$mail->isHTML(true);
$mail->Subject = 'Первое письмо из PHP';
$mail->Body = '<h1>Работает</h1><p>Это письмо отправлено через PHPMailer.</p>';
$mail->AltBody = 'Работает. Это письмо отправлено через PHPMailer.'; // для клиентов без HTML
$mail->send();
echo 'Письмо отправлено';
} catch (Exception $e) {
echo 'Ошибка отправки: ' . $mail->ErrorInfo;
}
Запустите из терминала: php send.php. Если всё верно, в консоли появится «Письмо отправлено», а в ящике получателя — письмо в течение минуты. Проверьте и папку «Спам».
Про порт и шифрование
Два рабочих сочетания, которые не стоит путать:
| Порт | Значение SMTPSecure | Что это |
|---|---|---|
| 465 | ENCRYPTION_SMTPS | Соединение шифруется сразу (implicit TLS) |
| 587 | ENCRYPTION_STARTTLS | Соединение начинается открытым и переходит в TLS командой STARTTLS |
Какой из них у вашего провайдера — смотрите в его справке. Порт 25 без шифрования на большинстве хостингов закрыт и для отправки не годится.
Если не получилось
Самые частые ошибки, которые вы увидите в $mail->ErrorInfo:
- «SMTP connect() failed» — не удалось подключиться к серверу. Проверьте адрес
Host, порт и то, что хостинг не блокирует исходящие соединения на этот порт. На локальной машине частая причина — фаервол или отсутствие интернета из PHP. - «Could not authenticate» или «535 Authentication failed» — неверный логин или пароль. Для Gmail и Яндекса с двухфакторкой обычный пароль не подойдёт: заведите пароль приложения в настройках безопасности ящика.
- «Class "PHPMailer\PHPMailer\PHPMailer" not found» — вы забыли
require __DIR__ . '/vendor/autoload.php';или запускаете скрипт не из папки сvendor/. - «SMTP Error: data not accepted» — сервер принял соединение, но отклонил письмо. Часто из-за того, что адрес в
setFrom()не совпадает с ящиком вUsername: большинство провайдеров запрещают отправлять от чужого имени. - Письмо ушло, но попало в спам — на стороне кода вы сделали всё, что могли. Дальше вопрос к домену: нужны SPF и DKIM-записи в DNS. Об этом ниже.
Куда двигаться дальше
Отправка одного письма работает. Три шага, которые стоит сделать следом:
- Вынесите пароль из кода. Храните SMTP-логин и пароль в переменных окружения или отдельном конфиге вне репозитория. Пароль в коде рано или поздно утечёт в git.
- Настройте SPF и DKIM для своего домена. Пока вы шлёте с чужого ящика (Яндекс, Gmail) — это забота провайдера. Как только начнёте отправлять со своего домена, без этих DNS-записей письма будут уходить в спам. Настройка DNS — отдельная тема, здесь её не разворачиваем.
- Для массовых рассылок не используйте отправку прямо из веб-запроса. Ставьте письма в очередь и отправляйте фоновым процессом, иначе страница будет висеть на время отправки, а провайдер упрётся в лимит писем в минуту.
Проверьте актуальные примеры и полный список настроек в официальном репозитории PHPMailer — API между мажорными версиями меняется.
Проверка грамотности: Орфография, пунктуация, стиль — с объяснением каждой правки
Спросить за 10 ₽Источники: PHPMailer — официальный репозиторий и документация, PHP: mail — руководство по функции
Частые вопросы
А если у меня старая версия PHP, например 7.4?
Обязательно ставить PHPMailer через Composer? У меня нет Composer на хостинге.
Письмо отправляется, но приходит в спам. Это ошибка в коде?
Можно ли отправлять письма без SMTP, просто через mail()?
Скрипт выдаёт «SMTP connect() failed», хотя логин и пароль верные. Что делать?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.