Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Отправка писем

Подтверждение регистрации, сброс пароля, сообщение из формы обратной связи — без писем не обходится почти ни один сайт. В 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);

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.