Функция mail() отправляет письмо «как есть»: без нормальной авторизации, часто без HTML и почти всегда в спам. Рабочий вариант — SMTP через PHPMailer.

Установка

composer require phpmailer/phpmailer

Отправка через SMTP

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

$mail = new PHPMailer(true);

try {
    $mail->isSMTP();
    $mail->Host       = 'smtp.yandex.ru';
    $mail->SMTPAuth   = true;
    $mail->Username   = 'robot@example.ru';
    $mail->Password   = getenv('MAIL_PASSWORD');
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
    $mail->Port       = 465;
    $mail->CharSet    = 'UTF-8';

    $mail->setFrom('robot@example.ru', 'Hello-Site');
    $mail->addAddress('client@example.ru', 'Клиент');
    $mail->addReplyTo('support@example.ru');

    $mail->isHTML(true);
    $mail->Subject = 'Ваш заказ готов';
    $mail->Body    = '<p>Здравствуйте! Заказ <b>№123</b> можно забирать.</p>';
    $mail->AltBody = 'Здравствуйте! Заказ №123 можно забирать.';

    $mail->send();
} catch (Exception $e) {
    error_log('Mail error: ' . $mail->ErrorInfo);
}

Вложения

$mail->addAttachment('/path/to/invoice.pdf', 'Счёт.pdf');

Чтобы письма не попадали в спам

  • Отправляйте с домена, у которого настроены SPF и DKIM.
  • Не подставляйте в From адрес пользователя — только свой домен.
  • Всегда заполняйте AltBody и не злоупотребляйте картинками.
  • Для массовых рассылок берите сервис (Unisender, SendPulse, Mailgun): на обычном хостинге лимиты заканчиваются быстро.

PHPMailer умеет SMTP, HTML, вложения и авторизацию из коробки, весит немного и ставится композером — этого достаточно для большинства задач на сайте.