Отправка писем
Подтверждение регистрации, сброс пароля, сообщение из формы обратной связи — без писем не обходится почти ни один сайт. В PHP есть встроенная функция mail(), но в настоящих проектах письма отправляют через почтовый сервер по протоколу SMTP.
Примеры отправляют почту и здесь не запускаются — выполните их у себя.
Функция mail
<?php
// send.php
$sent = mail(
'anna@example.com',
'Заказ принят',
'Спасибо! Ваш заказ №42 принят в работу.',
['From' => 'shop@example.com']
);
echo $sent ? 'Отправлено' : 'Ошибка';Аргументы: получатель, тема, текст, заголовки. Функция возвращает true, если письмо принято к отправке, — это ещё не значит, что оно дошло.
Почему mail недостаточно
mail() передаёт письмо почтовой программе сервера. На домашнем компьютере её обычно нет, а письма с хостинга без настройки часто попадают в спам. Поэтому письма отправляют через SMTP-сервер почтовой службы — с логином и паролем, как из почтовой программы.
PHPMailer
Самая распространённая библиотека для этого — PHPMailer:
composer require phpmailer/phpmailer<?php
// send.php
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->Username = getenv('MAIL_USER');
$mail->Password = getenv('MAIL_PASSWORD');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->CharSet = 'UTF-8';
$mail->setFrom('shop@example.com', 'Магазин');
$mail->addAddress('anna@example.com', 'Анна');
$mail->Subject = 'Заказ принят';
$mail->Body = 'Спасибо! Ваш заказ №42 принят в работу.';
$mail->send();Аргумент true в конструкторе включает исключения: при сбое send() бросит ошибку с описанием.
Письмо в формате HTML
<?php
// send-html.php
$mail->isHTML(true);
$mail->Subject = 'Заказ принят';
$mail->Body = '<h1>Спасибо!</h1><p>Ваш заказ <b>№42</b> принят в работу.</p>';
$mail->AltBody = 'Спасибо! Ваш заказ №42 принят в работу.';AltBody — текстовая версия для почтовых программ, которые не показывают HTML.
Вложения
<?php
// send-invoice.php
$mail->addAttachment(__DIR__ . '/invoices/42.pdf', 'Счёт.pdf');Обработка ошибок
<?php
// send-safe.php
use PHPMailer\PHPMailer\Exception;
try {
$mail->send();
echo 'Письмо отправлено';
} catch (Exception $e) {
error_log('Почта: ' . $mail->ErrorInfo);
echo 'Не удалось отправить письмо. Попробуйте позже.';
}Подробности пишут в журнал, а посетителю показывают общую фразу.
Проверка при разработке
Чтобы не рассылать настоящие письма во время разработки, используют программу Mailpit: она принимает письма по SMTP и показывает их в браузере. В настройках достаточно указать Host = 'localhost' и Port = 1025.
Частая ошибка
Данные из формы нельзя подставлять в заголовки без проверки. Если посетитель введёт в поле почты перенос строки и Bcc: …, ваш сайт разошлёт спам от вашего имени. Проверяйте адрес функцией filter_var() и не ставьте адрес посетителя в From — для ответа есть Reply-To:
<?php
// contact.php
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
if ($email === false) {
exit('Неверный адрес почты');
}
$mail->setFrom('site@example.com', 'Сайт');
$mail->addReplyTo($email);