Отправляйте электронные письма в PHP: от простого к сложному

Раздел: Работа с сетью в PHP -> Отправка почты в PHP

Основные способы отправки писем в PHP

Наиболее эффективное решение: библиотека PHPMailer с поддержкой SMTP

PHPMailer – самая популярная библиотека для отправки почты в PHP. Она поддерживает SMTP-аутентификацию, шифрование TLS/SSL, вложения, HTML-формат и корректно обрабатывает кодировки. Установка через Composer:

composer require phpmailer/phpmailer

Php отправить письмо (отправка письма через 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;
    }
}

Результат: каждое письмо отправляется отдельно, возможна персонализация и обработка ошибок построчно.

Отправка письма через PHP - comments

En
Php отправить письмо (php)