Отправка PHP почты из Docker

Не так давно начал мигрировать на Docker, слепил себе контейнер для php-fpm, но основное с чем возникли сложности - это отправка почты.

Если использовать почту в домене и авторизовываться в ящике, то можно прикрутить какой-нибудь PHPMailer, но я хотел обычный почтовик настроить, чтобы от любого емейла слать уведомления с сайта и не пользоваться услугами почтовых сервисов для этого.

Изначально пишем примерно такой скрипт

<?php

$to      = 'mymail@gmail.com';
$subject = 'the subject';
$message = 'hello4';
$headers = 'From: admin2@site.ru' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);

Настройка хоста

На самом хосте ставим Postfix, настраиваем его nano /etc/postfix/main.cf

#обязательно указать PTR на ваш айпи равный этому
myorigin = web.mydomain.ru

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

#тут хак для подмены отправителя из докеров
sender_canonical_classes = envelope_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps


smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
mydomain = $myhostname 
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = localhost

#указать, если нужно слать через почтарь хостера
relayhost = 

#последним подсеть докеров - допустимые доверительные подсети
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/24
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
smtp_tls_security_level = may

Далее создадим файлик nano /etc/postfix/sender_canonical_maps

/.+/    postmaster@web.mydomain.ru

Настройки в докере

apk add ssmtp

И конфиг /etc/ssmtp/ssmtp.conf

rewriteDomain=web.mydomain.ru
FromLineOverride=YES
mailhub=172.17.0.1
#hostname=web.mydomain.ru
UseTLS=YES
UseSTARTTLS=YES

В чем был подвох?

ssmtp это минималистичный мейлер из докера, в нем прописан адрес нашего хоста 172.17.0.1 и прописан домен, которым он должен прикидываться, в postfix вся подсеть из докера в доверенной зоне.

Если на этом остановиться, то почта по идее ходила, но она была от имени root, т.е. From не работал, после того, как я прописал FromLineOverride=YES - у меня адекватно заработал From и отправитель отображался корректно, но при этом почта попадала в спам на gmail. Но при этом с самого хоста почта работала хорошо и досылалась и в спам не попадала.

Оказывается в smtp есть сам заголовок в теле письма и есть еще заголовки при общении почтарей, это smtp.from, утилита ssmtp подменяла всё и сразу из заголовка From, а гугл проверял домен @... и говорил что ваш сервер не имеет права от него слать и письмо в спам улетало.

Вот тут и помогла подмена отправителя следующей конструкцией

sender_canonical_classes = envelope_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps
Обратите внимание! nslookup <ip> должен возвращать тот домен, который везде фигурирует, в моем примере это web.mydomain.ru
Показать комментарии