PHP: почта через SMTP с аутентификацией или msmtp

Давно хотел узнать, как отправлять почту через сторонний сервер с помощью стандартной функции mail, так как считаю неправльным использовать всякие классы-надстройки, а держать SMTP-сервер только для этих целей зачастую нежелательно. И вроде бы нашел решение для Linux и FreeBSD: программа msmtp.

Во многих дистрибутивах она изначально есть в пакетах, поэтому ее установка проблем не составляет. В Debian Linux пишем:

# apt-get install msmtp

В FreeBSD:

# cd /usr/ports/mail/msmtp
# make && make install && make clean
# rehash 

Теперь выполним

# msmtp --version

чтобы узнать, где находится системный файл конфигурации (обычно под Linux это /etc/msmtprc, под FreeBSD — /usr/local/etc/msmtprs). Теперь можно приступить к его редактированию. Файл может содержать настройки для нескольких аккаунтов. В простейшем случае для аутентификации достаточно указать следующее:

account default
auth on
user имя_пользователя
password пароль
from ящик_отправителя
timeout 5

Последняя строка — это таймаут для соединения с сервером. В случае отправки почты из PHP-скриптов он должен быть небольшим, чтобы если SMTP-сервер упадет, это не сильно сказалось на работе сайта.

Проверим, что подключение к серверу проходит нормально:

# msmtp --serverinfo

Далее найдем в php.ini строку sendmail_path и укажем в ней путь к msmtp (пример для FreeBSD):

sendmail_path = "/usr/local/bin/msmtp -t"

Не забываем про кавычки, их отсутствие будет приводить к ошибке.

Казалось бы, на этом все, и после перезапуска Apache отправка почты должна заработать, но обнаружилась одна тонкость. При отправке письма с опцией -t msmtp создает где-то (скорее всего, в текущем каталоге) временный файл, и в ряде случаев на это может не хватить прав. В этом случае письмо не отправится, и запись в лог об этом так же не будет сделана. Чтобы избежать такого, нужно прописать в переменную TMPDIR каталог, который точно открыт для записи, например, /tmp. Сделать это можно разными способами, самый простой — добавить в скрипт перед вызовом функции mail вот такую строку:

putenv('TMPDIR=/tmp');

После этого отправка писем через внешний сервер должна заработать.