Отправляйте электронные письма в PHP: от простого к сложному
Основные способы отправки писем в PHP
Наиболее эффективное решение: библиотека PHPMailer с поддержкой SMTP
PHPMailer – самая популярная библиотека для отправки почты в PHP. Она поддерживает SMTP-аутентификацию, шифрование TLS/SSL, вложения, HTML-формат и корректно обрабатывает кодировки. Установка через Composer:
composer require phpmailer/phpmailerPhp отправить письмо (отправка письма через php)
Пример отправки письма через SMTP Яндекса:
<?php
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 = 'user@yandex.ru';
$mail->Password = 'пароль_приложения';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
$mail->setFrom('user@yandex.ru', 'Иван Иванов');
$mail->addAddress('recipient@example.com', 'Получатель');
$mail->addReplyTo('info@example.com', 'Информация');
$mail->isHTML(true);
$mail->Subject = 'Тестовое письмо';
$mail->Body = '<h1>Привет!</h1><p>Это HTML-письмо.</p>';
$mail->AltBody = 'Привет! Это текстовая версия.';
$mail->send();
echo 'Письмо отправлено успешно';
} catch (Exception $e) {
echo "Ошибка: {$mail->ErrorInfo}";
}
Цель использования: обеспечение надёжной доставки через внешние SMTP-серверы (Яндекс, Gmail, Mail.ru).
Типичные проблемы:
- Ошибка аутентификации – неверный пароль приложения (для Яндекса и Google требуется специальный пароль).
- Блокировка порта 465/587 хостингом – необходимо обратиться к провайдеру или использовать порт 25 с шифрованием STARTTLS.
- Сертификаты SSL – отключить проверку можно через
$mail->SMTPOptions = ['ssl' => ['verify_peer' => false]];, но это снижает безопасность.
Как отправить письмо без использования внешних библиотек?
Функция mail() – встроенный способ, доступный на большинстве хостингов. Пример:
<?php
$to = 'recipient@example.com';
$subject = 'Тема письма';
$message = 'Текст сообщения';
$headers = 'From: sender@example.com' . "\r\n" .
'Reply-To: sender@example.com' . "\r\n" .
'MIME-Version: 1.0' . "\r\n" .
'Content-type: text/plain; charset=UTF-8' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
if (mail($to, $subject, $message, $headers)) {
echo 'Письмо отправлено';
} else {
echo 'Ошибка отправки';
}
Цель: простые одноразовые уведомления, когда не требуется высокая надёжность. Часто используется на shared-хостинге.
Проблемы и решения:
- Письма попадают в спам – настройте SPF, DKIM и DMARC записи для домена.
- Заголовки не обрабатываются – убедитесь, что нет лишних пробелов перед
\r\n. - Не работает на Windows – требуется настроить SMTP через
php.iniили использовать библиотеки.
Как отправить письмо напрямую через SMTP без библиотек?
fsockopen() и SMTP-протокол – низкоуровневый подход. Пример:
<?php
$smtpServer = 'smtp.mail.ru';
$port = 465;
$socket = fsockopen('ssl://'.$smtpServer, $port, $errno, $errstr, 30);
if (!$socket) {
die("Ошибка подключения: $errstr ($errno)");
}
$crlf = "\r\n";
fgets($socket, 512); // читаем приветствие
fwrite($socket, "EHLO client" . $crlf);
fgets($socket, 512);
fwrite($socket, "AUTH LOGIN" . $crlf);
fgets($socket, 512);
fwrite($socket, base64_encode('login@mail.ru') . $crlf);
fgets($socket, 512);
fwrite($socket, base64_encode('пароль') . $crlf);
fgets($socket, 512);
fwrite($socket, "MAIL FROM:<login@mail.ru>" . $crlf);
fgets($socket, 512);
fwrite($socket, "RCPT TO:<recipient@example.com>" . $crlf);
fgets($socket, 512);
fwrite($socket, "DATA" . $crlf);
fgets($socket, 512);
$message = "Subject: Тест$crlf";
$message .= "From: login@mail.ru$crlf";
$message .= "To: recipient@example.com$crlf";
$message .= $crlf;
$message .= "Текст письма";
$message .= "$crlf.";
fwrite($socket, $message . $crlf);
fgets($socket, 512);
fwrite($socket, "QUIT" . $crlf);
fclose($socket);
echo 'Письмо отправлено (ручной SMTP)';
Цель: учебный пример, понимание работы SMTP-протокола.
Ошибки:
- Отсутствие расширения OpenSSL – порты 465 требуют SSL.
- Неверный ответ сервера – нужно анализировать каждый ответ функцией fgets().
Как отправить письмо через REST API (Mailgun, SendGrid, Mailjet)?
Внешние сервисы предоставляют HTTP API. Пример для Mailgun (используется cURL):
<?php
$apiKey = 'key-ваш_ключ';
$domain = 'mg.example.com';
$ch = curl_init("https://api.mailgun.net/v3/$domain/messages");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "api:$apiKey");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'from' => 'sender@example.com',
'to' => 'recipient@example.com',
'subject' => 'Привет!',
'text' => 'Текст письма',
'html' => '<h1>HTML версия</h1>'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode == 200) {
echo 'Письмо отправлено через Mailgun';
} else {
echo 'Ошибка: ' . $response;
}
curl_close($ch);
Цель: высоконагруженные проекты (до 10 000 писем в день на бесплатных тарифах), встроенная аналитика доставки.
Проблемы:
- Лимиты бесплатных тарифов – превышение квоты блокирует отправку.
- Необходима верификация домена (SPF, DKIM).
Расширенные примеры отправки писем в PHP
PHPMailer: вложения и встраивание изображений
Пример: отправка письма с PDF-вложением и встроенной картинкой (не attachment). Код:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php';
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'user@gmail.com';
$mail->Password = 'пароль_приложения';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('user@gmail.com', 'Администратор');
$mail->addAddress('client@example.com');
$mail->addCC('manager@example.com');
// Вложение файла
$mail->addAttachment('/path/to/file.pdf', 'документ.pdf');
// Встраивание изображения (cid)
$mail->addEmbeddedImage('/path/to/logo.png', 'logo');
$mail->isHTML(true);
$mail->Subject = 'Заказ №123';
$mail->Body = '<h1>Спасибо за заказ!</h1><img src="cid:logo" alt="Логотип">';
$mail->AltBody = 'Спасибо за заказ! Логотип не отображается в текстовой версии.';
if ($mail->send()) {
echo 'Письмо с вложением отправлено';
}
Результат: на почте получателя откроется HTML-письмо с картинкой внутри и прикреплённым PDF.
SwiftMailer (альтернатива PHPMailer)
Компонент SwiftMailer стабилен, поддерживает очереди и работу с несколькими серверами. Установка:
composer require swiftmailer/swiftmailer
Пример отправки через SMTP:
<?php
require 'vendor/autoload.php';
$transport = new Swift_SmtpTransport('smtp.mail.ru', 465, 'ssl');
$transport->setUsername('login@mail.ru')
->setPassword('пароль');
$mailer = new Swift_Mailer($transport);
$message = (new Swift_Message('Тема'))
->setFrom(['login@mail.ru' => 'Отправитель'])
->setTo(['recipient@example.com' => 'Получатель'])
->setBody('<h1>HTML контент</h1>', 'text/html')
->addPart('Текстовая версия', 'text/plain')
->attach(Swift_Attachment::fromPath('/path/file.pdf'));
$result = $mailer->send($message);
if ($result > 0) {
echo 'Успешно отправлено ' . $result . ' писем';
} else {
echo 'Ошибка отправки';
}
Результат: письмо отправлено с теми же возможностями, что и PHPMailer.
Отправка через SendGrid API с использованием Guzzle
SendGrid предоставляет простой REST API. Установка:
composer require guzzlehttp/guzzle
Пример:
<?php
require 'vendor/autoload.php';
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.sendgrid.com/v3/mail/send', [
'headers' => [
'Authorization' => 'Bearer YOUR_SENDGRID_API_KEY',
'Content-Type' => 'application/json',
],
'json' => [
'personalizations' => [
['to' => [['email' => 'recipient@example.com']]]
],
'from' => ['email' => 'sender@example.com'],
'subject' => 'Тест SendGrid',
'content' => [
['type' => 'text/plain', 'value' => 'Текст']
]
]
]);
if ($response->getStatusCode() == 202) {
echo 'Письмо принято в очередь';
} else {
echo 'Ошибка: ' . $response->getBody();
}
Результат: API возвращает 202 Accepted, письмо доставляется из облака SendGrid.
Пакетная отправка с разными получателями (phpmailer + цикл)
Для массовой рассылки лучше создавать одно письмо и использовать addBCC, либо новый экземпляр для каждого получателя. Пример:
<?php
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
// ... настройки SMTP ...
$recipients = ['user1@example.com', 'user2@example.com'];
foreach ($recipients as $email) {
$mail->clearAddresses();
$mail->addAddress($email);
$mail->Subject = 'Новости для ' . $email;
$mail->Body = '<p>Персонализированное письмо</p>';
try {
$mail->send();
echo 'Отправлено: ' . $email . PHP_EOL;
} catch (Exception $e) {
echo 'Ошибка для ' . $email . ': ' . $mail->ErrorInfo . PHP_EOL;
}
}
Результат: каждое письмо отправляется отдельно, возможна персонализация и обработка ошибок построчно.