Как стать автором
Обновить

Sendmail-заглушка для PHP и на PHP

Время на прочтение3 мин
Количество просмотров36K
image

Каждый раз настраивая локальный вебсервер, сталкиваюсь с вопросом о заглушке для Sendmail.

Есть прекрасное решение для Windows: fake sendmail for windows (sendmail.exe) http://glob.com.au/sendmail/
На хабре есть статья об этом решении: PHP mail под Windows http://habrahabr.ru/post/26518/
Ещё одно решение под Windows: Test Mail Server Tool http://www.toolheap.com/test-mail-server-tool/
Так же есть статья для линуксоидов: Sendmail-заглушка для Linux http://habrahabr.ru/post/49665/

Лично мне больше понравилось решение на чистом PHP, о котором и пойдёт дальнейшее описание.


Особенность этого решения в том, что для его настройка минимальна, можно даже обойтись без самого файла, если конечно вам нет нужды знать содержимое сообщения. На мой взгляд, такой метод стоит того, что бы о нём знали другие разработчики PHP.

Вопрос в том, что является вашим приоритетом как разработчика, ваши потребности от заглушки, а также ваш уровень знаний и умений.

Из плюсов:
  • Отсутствие сторонних сервисов
  • Кроссплатформенное решение для OS на которой установлен PHP
  • Минимальный размер файла заглушки
  • Минимальная настройка
  • Вся логика заглушки доступна для редактирования на PHP
  • Сохранение сообщения в файле


Из минусов:
  • Отсутствие пересылки на реальный почтовый ящик
  • Отсутствие удобного доступа к отправленным сообщениям


Список аргументов и возможностей заглушки:
  • --dir <Путь к папке> — Папка для файлов
  • --file <имя файла> — Сохранять каждое сообщение в конкретном общем файле
  • --prepend — Добавлять новое сообщение в начало общего файла
  • --open — Автоматически открывать файл сообщения в Notepad


Параметры для PHP.INI файла:

[mail function]
;SMTP = localhost
;smtp_port = 25
;sendmail_from = me@example.com
sendmail_path = "php.exe C:\sendmail.php --dir C:\mail --open"


Если путь к php.exe прописан в PATH, то можно не указывать его в PHP.INI иначе желательно изменить php.exe на <Путь к папке с PHP>\php.exe

sendmail_path = "C:\server\bin\php\php.exe C:\sendmail.php --dir C:\mail --open"


На линукс можно сразу указать путь к файлу, не забыв предварительно сделать его запускаемым: chmod 755 sendmail.php
sendmail_path = "/home/someuser/sendmail.php --dir /tmp/mail"


Сам 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);
}

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.'.txt';
  return file_exists($mail_dir.'/'.$fn) ? mkname(++$i) : $fn;
}


Как я и обещал, есть также возможность обойтись совсем без файла.

sendmail_path = "C:\server\bin\php\php.exe -r 'echo 1;'"


Либо использовать упрощённый вариант решения

sendmail_path = "C:\server\bin\php\php.exe C:\sendmail.php"


sendmail.php:

#!/usr/bin/env php

<?php
$mail = '';
while (false !== ($line = fgets(STDIN))) {
  $mail .= $line;
}
file_put_contents("c:/mail/mail.txt", $mail . PHP_EOL . str_repeat("-=", 20) . PHP_EOL, FILE_APPEND);


Буду рад, если Вам это будет полезным.
Теги:
Хабы:
+9
Комментарии21

Публикации

Истории

Работа

PHP программист
157 вакансий

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн