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

в 10:18, , рубрики: fake sendmail, php, php mail, sendmail, метки: ,

Каждый раз настраивая локальный вебсервер, сталкиваюсь с вопросом о заглушке для 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, о котором и пойдёт дальнейшее описание.

Из плюсов:

  • Отсутствие сторонних сервисов
  • Кроссплатформенное решение для 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:serverbinphpphp.exe C:sendmail.php --dir C:mail --open"

На линукс можно сразу указать путь к файлу, не забыв предварительно сделать его запускаемым: chmod 755 sendmail.php

sendmail_path = "/home/someuser/sendmail.php --dir /tmp/mail"

Сам sendmail.php скрипт:

#!/usr/local/bin/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 = substr(php_uname(), 0, 7) === "Windows";
$is_open = (empty($argv) || !in_array('--open', $argv)) ? FALSE : TRUE;
$is_prepend = (empty($argv) || !in_array('--prepend', $argv)) ? FALSE : TRUE;
$is_onefile = (empty($argv) || !in_array('--file', $argv)) ? FALSE : TRUE;
$mail_dir = get_next_arg('--dir', sys_get_temp_dir().'/mail');
$file_name = get_next_arg('--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 : '';
$fp = fopen('php://stdin','r');
if (!$fp) {
  die('Unable to open stdin for input');
}
while($t=fread($fp,2048)) {
  if( $t===chr(0) ) {
    break;
  }
  $stream .= ($is_windows ? str_replace("n", PHP_EOL, $t) : $t);
}
fclose($fp);

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;
}

function get_next_arg($key, $default = NULL) {
  global $argv;
  if(empty($argv) || !in_array($key, $argv) || empty($argv[array_search($key, $argv, TRUE)+1])) {
    return $default;
  } else {
    return $argv[array_search($key, $argv, TRUE)+1];
  }
}

Буду рад, если Вам это будет полезным.

Автор: klev

Источник

  1. Юрий:

    А есть наоборот – не заглушка, а рабочий сенд-майл для windows? чтоб подменить его в денвере и оно реально бы слало письма, а не складировало в папку

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js