Программы. Игры. Браузеры. Windows. Архиваторы
  • Главная
  • Взлом
  • Отправка писем с помощью php. Решение проблем с отправкой почты из скриптов в Sendmail Поверенный inurl sendmail php

Отправка писем с помощью php. Решение проблем с отправкой почты из скриптов в Sendmail Поверенный inurl sendmail php

Знакомство с php-функцией mail() и простейший пример её использования для отправки писем по электронной почте. Что лучше или Sendmail vs mail.

PHP-функция mail() позволяет вам отправлять письма на указанный адрес электронной почты.

Синтаксис :

Bool mail (string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]]);

Параметры :

  • to — адрес электронной почты получателя письма в соответствии с форматом RFC 2822. Например :
  • 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) . " "; $to = mime_base64("Имя получитель", $charset) . " "; $subject = mime_base64("Тема отправляемого письма", $charset); $message = "Содержание отправляемого письма."; $message = wordwrap($message, 70); $headers = "From: " . $from . "\r\n" . "Reply-To: " . $from . "\r\n" . "X-Mailer: PHP/" . phpversion(). "\r\n" . "MIME-Version: 1.0" . "\r\n" . "Content-type: text/plain; charset="" . $charset . """; if (mail($to, $subject, $message, $headers)) { echo "

Письмо отправлено.

"; } else { echo "

Произошла ошибка.

"; }

Думаю, что комментарии излишни, так как я и без того уделил достаточно много внимание различным деталям. Варианты набора RFC-заголовков могут отличаться, но на локальном сервере я получил следующее:

X-Sendmail-Cmdline: sendmail.pl -t -i To: =?windows-1251?B?yOz/IO/u6/P36PLl6/w=?= Subject: =?windows-1251?B?0uXs4CDu8u/w4OLr/+Xs7uPuIO/o8fzs4A==?= From: =?windows-1251?B?yOz/IO7y7/Dg4ujy5ev8?= Reply-To: =?windows-1251?B?yOz/IO7y7/Dg4ujy5ev8?= X-Mailer: PHP/5.3.3 MIME-Version: 1.0 Content-type: text/plain; charset="windows-1251"

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

Спасибо!

Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:

Лучшие статьи по теме