Как тестировать отправку писем в PHP на Windows

Отправка писем — это важная функция веб-сайта. Email может использоваться для подтверждения регистрации, восстановления пароля, отправки уведомления и пр. При написании своего веб-приложения, либо для целей отладки, может понадобиться проверка работы отправки писем на локальном компьютере.

Для отправки писем в PHP используется функция mail. Для успешной работы этой функции, интерпретатор PHP обращается к внешней почтовой программе и передаёт ей отправляемое письмо. Обычно это sendmail в Linux.

Как можно догадаться, это не очень применимо к Windows, и уж тем более к веб-серверу на локальном компьютере. Поэтому для тестирования функции отправки писем придумана почтовая заглушка.

Почтовая заглушка — это программа, которая подменяет роль программы для отправки писем — она принимает письмо от PHP, но не пытается его никуда отправить, а сохраняет на диск. В дальнейшем это письмо можно открыть и проверить корректность использования функции mail.

Установка почтовой заглушки для PHP в Windows

Я устанавливал веб-сервер по этой инструкции, если вы это делали другим способом, то замените пути до файлов на ваши.

В каталоге C:\Server\bin\ создайте новый каталог с названием Sendmail. Теперь в этом каталоге создайте файл sendmail.php со следующим содержимым:

#!/usr/bin/env php
  
<?php
/*  PHP.INI
 *  [mail function]
 *  ;SMTP = localhost
 *  ;smtp_port = 25
 *  ;sendmail_from = me@example.com
 *  sendmail_path = php.exe sendmail.php --dir C:\mail --open
 */
  
$is_windows = stristr(PHP_OS, 'WIN');
$options = getopt("", ['open', 'prepend', 'file:', 'dir:']);
$is_open = isset($options['open']);
$is_prepend = isset($options['prepend']);
$is_onefile = isset($options['file']);
$mail_dir = isset($options['dir']) ? $options['dir'] : sys_get_temp_dir() . '/mail';
$file_name = isset($options['file']) ? $options['file'] : mkname();
$file_path = $mail_dir . '/' . $file_name;
  
if (!is_dir($mail_dir)) {
    mkdir($mail_dir, 0777, TRUE);
    if (!is_dir($mail_dir)) {
        die('Mail folder [' . $mail_dir . '] not created');
    }
}
  
$stream = $is_onefile ? PHP_EOL . str_repeat("-=", 10) . date('Y-m-d H:i:s') . str_repeat("-=", 10) . PHP_EOL : '';
while (false !== ($line = fgets(STDIN))) {
    //$stream .= ($is_windows ? str_replace("\n", PHP_EOL, $line) : $line);
    $stream .= $line;
}
  
if ($is_prepend && file_exists($file_path)) {
    $file_contents = file_get_contents($file_path);
    $stream .= $file_contents;
}
  
file_put_contents($file_path, $stream, $is_prepend ? 0 : FILE_APPEND);
  
if ($is_open && $is_windows) {
    pclose(popen("start /B notepad " . $file_path, "r"));
}
  
function mkname($i = 0) {
    global $mail_dir;
    $fn = 'mail_' . date('Y-m-d_H-i-s_') . $i . '.eml';
    return file_exists($mail_dir . '/' . $fn) ? mkname( ++$i) : $fn;
}

Откройте конфигурационный файл PHP, он размещён здесь C:\Server\bin\PHP\php.ini. И добавьте туда одну строчку:

sendmail_path = "C:\Server\bin\PHP\php.exe C:\Server\bin\Sendmail\sendmail.php --dir C:\Server\bin\Sendmail\emails"

Сохраните файл и перезапустите сервер.

c:\Server\bin\Apache24\bin\httpd.exe -k restart

Отлично, теперь все отправленные письма будут сохраняться в каталоге C:\Server\bin\Sendmail\emails\

Для имитации отправки письма используйте следующий код:

<?php
$to      = 'nobody@example.com';
$subject = 'the subject';
$message = 'hello';
$headers = 'From: webmaster@example.com' . "\r\n" .
    'Reply-To: webmaster@example.com' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);

Отправленное письмо сохранено в файл mail_2019-06-03_15-14-06_0.eml. Этот файл для правильного отображения нужно открыть почтовой программой.

Также его можно открыть любым текстовым редактором — там вы увидите заголовки почтового протокола и текст письма, в данном случае там будет:

To: nobody@example.com
Subject: the subject
X-PHP-Originating-Script: 0:test4.php
From: webmaster@example.com
Reply-To: webmaster@example.com
X-Mailer: PHP/7.3.4

hello

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *