Знакомство с php-функцией mail() и простейший пример её использования для отправки писем по электронной почте. Что лучше или Sendmail vs mail.
PHP-функция mail() позволяет вам отправлять письма на указанный адрес электронной почты.
Синтаксис :
Bool mail (string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]]);
Параметры :
- to
— адрес электронной почты получателя письма в соответствии с форматом RFC 2822. Например
:
- [email protected]
- [email protected], [email protected]
- Имя пользователя < [email protected]>
- Имя пользователя < [email protected]> , Имя ещё одного пользователя < [email protected]>
- subject — тема отправляемого письма в соответствии с форматом RFC 2047
- message
— содержание отправляемого письма. Каждая строка должна быть не длиннее 70 символов и заканчиваться символом новой строки (\n).
Только для Windows : Когда PHP обращается к SMTP серверу напрямую, точка в начале строки удаляется. Для борьбы с этим нюансом, следует использовать замену на двойную точку в начале строки.
$message = str_replace ("\n.", "\n..", $message);
- additional_headers (не обязательно) – строка, которая будет добавлена после заголовков письма. Обычно используется для добавления дополнительных заголовков (From, Cc и Bcc). Строки должны быть разделены CRLF (\r\n).
- additional_parameters (не обязательно) – дополнительные параметры, используемые программой назначенной для отправки писем.
Возвращает : TRUE если письмо отправлено успешно или FALSE если нет. Следует отметить, если письмо успешно поставлено в очередь на отправление, это не значит, что оно достигнет адресата.
Теперь, когда мы разобрались в теории, можно приступить к практике. Но для начала я хочу привести парочку полезных функций, которые позволят в значительной степени облегчить нашу задачу.
Пример : php-функция MIME base64 кодирования, с учетом кодировки
Function mime_base64($string, $charset="windows-1251") { return "=?" . $charset . "?B?" . base64_encode(trim($string)) . "?="; }
Одна из проблем, возникающих при отправке почты, заключается в формировании заголовка письма. В частности, заголовок, имена отправителя и получателя, написанные кириллицей могут быть распознаны почтовым клиентом получателя в искаженном виде. Для того чтобы избежать этой проблемы, можно воспользоваться MIME base64 кодированием, преобразующее последовательность байт в последовательность печатных ASCII символов.
Function is_email($string) { return preg_match("/^()+([\.a-zA-Z0-9_-])*@()+(\.+)*\.({2,6})$/", $string); }
С эти тоже разобрались. А теперь то, ради чего и писалась данная заметка.
Пример : отправка писем с помощью php-функции mail()
$charset = "windows-1251";
$from = mime_base64("Имя отправитель", $charset) . " Письмо отправлено. Произошла ошибка.
Думаю, что комментарии излишни, так как я и без того уделил достаточно много внимание различным деталям. Варианты набора RFC-заголовков могут отличаться, но на локальном сервере я получил следующее:
X-Sendmail-Cmdline: sendmail.pl -t -i
To: =?windows-1251?B?yOz/IO/u6/P36PLl6/w=?=
Sendmail vs php mail()
Напоследок небольшой ликбез. Sendmail является одним из почтовых серверов (MTA), в то время как php-функция mail() просто реализует процесс отправки писем через SMTP соединение. Понятно, что использование php-функции является удобным, но далеко не оптимальным решением. Обычно mail() используется в тех случаях, когда речь не заходит о масштабных рассылках.
Каждый раз настраивая локальный вебсервер, сталкиваюсь с вопросом о заглушке для 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 файла:
;SMTP = localhost ;smtp_port = 25 ;sendmail_from = [email protected] 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
Буду рад, если Вам это будет полезным.
Каждый раз настраивая локальный вебсервер, сталкиваюсь с вопросом о заглушке для 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 файла:
;SMTP = localhost ;smtp_port = 25 ;sendmail_from = [email protected] 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
Как я и обещал, есть также возможность обойтись совсем без файла.
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
Буду рад, если Вам это будет полезным.
Недавно настраивал домашний сервер, и понадобилось мне там протестировать отправку почты. Но вот беда, при запросе страницы, которая отправляет почту вылезала 500 ошибка.
Проблема
Начал смотреть, в чём же дело. В логах php-fpm ничего интереного нет, в логах nginx видно, что php-fpm upstream отваливает по таймауту.
2013/04/18 15:28:01 6928#0: *1409 upstream timed out (110: Connection timed out) while reading response header from upstream, client: xx.xx.xx.xx, server: , request: "POST /page.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9010", host: "site.ru", referrer: "http://site.ru"
И тут мне в голову пришла идея заглянуть в syslog. Там то я и увидел интересные строчки:
Sep 9 18:53:20 mega sm-msp-queue: My unqualified host name (mega) unknown; sleeping for retry Sep 9 18:54:20 mega sm-msp-queue: unable to qualify my own domain name (mega) -- using short name
Ага, начал грешить в сторону sendmail. Пробую перезапустить его командой:
Sudo service sendmail restart
и вижу подтверждение своей догадки.
Andrey@mega:/home/andrey# sudoservice sendmail restart sudo: unable to resolve host xyz.xyz * Restarting Mail Transport Agent (MTA) sendmail andrey@mega:/home/andrey#
Решение
Дело оказалось в имени сервера. После того, как поставил вот такое имя сервера (с точкой) — всё заработало как надо.
127.0.0.1 localhost localhost.localdomain mega mega.foobar