Я использую сервер Ubuntu 14.04 (Linux). Я очень хорошо установил и настроил Postfix и OpenDKIM на сервере; Я могу отправить электронную почту к себе с такими командами, как echo hi | sendmail root
и постфикс / opendkim будет добавить заголовки , такие как Message-Id
, Date
, и DKIM-Signature
, вперед электронную почту на мой личный адрес электронной почты, и все прекрасно работает.
Теперь я хотел бы создать приложение, которое запускается в контейнере Docker и может с той же легкостью отправлять электронные письма. В частности, я не хочу беспокоиться о добавлении заголовков, как Message-Id
, и я не хочу делать слишком много настроек или установки программного обеспечения внутри самого контейнера.
Каков наилучший способ сделать это?
Есть ли способ позволить контейнеру запустить sendmail
execuable на хосте?
Я попытался установить соединение с Postfix из контейнера, используя протокол SMTP на порту 25, но Postfix, похоже, обрабатывает сообщения, полученные таким образом, по-другому; Я думаю, что это не добавило никаких заголовков, поэтому сообщение было полностью отклонено как спам от gmail (оно даже не было достаточно хорошим, чтобы помещаться в мою папку «Спам»).
Здесь содержание почтового журнала
Sep 28 23:35:52 dantooine postfix/smtpd[4306]: connect from unknown[172.17.0.95]
Sep 28 23:35:52 dantooine postfix/smtpd[4306]: DD457889B: client=unknown[172.17.0.95]
Sep 28 23:35:52 dantooine postfix/cleanup[4309]: DD457889B: message-id=<>
Sep 28 23:35:52 dantooine spamd[3175]: spamd: connection from localhost [::1]:59471 to port 783, fd 6
Sep 28 23:35:52 dantooine spamd[3175]: spamd: handle_user (getpwnam) unable to find user: 'someone'
Sep 28 23:35:52 dantooine spamd[3175]: spamd: still running as root: user not specified with -u, not found, or set to root, falling back to nobody
Sep 28 23:35:52 dantooine spamd[3175]: spamd: processing message (unknown) for someone:65534
Sep 28 23:35:52 dantooine spamd[3175]: spamd: clean message (2.5/5.0) for someone:65534 in 0.0 seconds, 331 bytes.
Sep 28 23:35:52 dantooine spamd[3175]: spamd: result: . 2 - MISSING_DATE,MISSING_FROM,MISSING_MID,UNPARSEABLE_RELAY scantime=0.0,size=331,user=someone,uid=65534,required_score=5.0,rhost=localhost,raddr=::1,rport=59471,mid=(unknown),autolearn=no autolearn_force=no
Sep 28 23:35:52 dantooine opendkim[3179]: DD457889B: can't determine message sender; accepting
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: DD457889B: from=<whoever@example.com>, size=275, nrcpt=1 (queue active)
Sep 28 23:35:53 dantooine postfix/smtpd[4306]: disconnect from unknown[172.17.0.95]
Sep 28 23:35:53 dantooine postfix/smtp[4311]: DD457889B: to=<someone@gmail.com>, relay=gmail-smtp-in.l.google.com[2607:f8b0:4003:c05::1b]:25, delay=0.25, delays=0.12/0.01/0.03/0.09, dsn=5.7.1, status=bounced (host gmail-smtp-in.l.google.com[2607:f8b0:4003:c05::1b] said: 550-5.7.1 [fd17:8b70:893a:44bf:fe73:6c21] Our system has detected that 550-5.7.1 this message is likely unsolicited mail. To reduce the amount of spam 550-5.7.1 sent to Gmail, this message has been blocked. Please visit 550-5.7.1 http://support.google.com/mail/bin/answer.py?hl=en&answer=188131 for 550 5.7.1 more information. su20si7357528oeb.94 - gsmtp (in reply to end of DATA command))
Sep 28 23:35:53 dantooine postfix/cleanup[4309]: 254E688A0: message-id=<20140928233553.254E688A0@myserver.example.com>
Sep 28 23:35:53 dantooine postfix/bounce[4330]: DD457889B: sender non-delivery notification: 254E688A0
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: 254E688A0: from=<>, size=3374, nrcpt=1 (queue active)
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: DD457889B: removed
Sep 28 23:35:53 dantooine postfix/virtual[4331]: 254E688A0: to=<whoever@example.com>, relay=virtual, delay=0.01, delays=0/0/0/0, dsn=2.0.0, status=sent (delivered to maildir)
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: 254E688A0: removed
To
заголовок,Subject
заголовок и однострочное тело. Я не знаю, как определить, какие заголовки у него были после того, как Postfix пропустил его через миллиметры, знаете как? Вот вывод в / var / log / syslog, показывающий, как он был обработан Postfix и отклонен Gmail: gist.github.com/DavidEGrayson/fbf65c8290c049a1f262Ответы:
Поскольку у вас есть рабочее решение, здесь я попытаюсь объяснить другое поведение, когда вы используете telnet для postfix (SMTP) и когда вы используете sendmail (не-SMTP).
К вашему сведению, OpenDKIM будет вызываться постфиксом с механизмом Милтера . Вы можете получить некоторую информацию о более легкой реализации в postfix через эту официальную документацию . Вот схема крюка milter в постфиксе.
Вы можете видеть, что sendmail-way (не-SMTP) и telnet-way (SMTP) имеют разный порядок обработки.
Электронная почта, не относящаяся к SMTP, будет обработана после очистки, прежде чем будет введена в milter. Cleanup демон был ответственен за добавление недостающих заголовков: (Resent-) From :, To :, Message-Id :, и Дата: . Поэтому при отправке в OpenDKIM milter ваше письмо будет иметь полный заголовок, даже если исходное письмо имело неполный заголовок.
SMTP-сообщение будет отправлено в OpenDKIM milter до начала любой очистки. Поэтому, если ваше оригинальное письмо имело неполный заголовок, тогда opendkim может отказать в подписи. From: заголовок является обязательным (см RFC 6376 ) , и если письмо не имеет его, OpenDKIM откажется подписать письмо и дать вам предупреждение
Поскольку я никогда не использую docker, я не знаю, какое ограничение на sendmail / pickup внутри контейнера. Я думаю, что обходной путь Дэвида Грейсона был достаточно безопасным, чтобы OpenDKIM подписывал сообщение.
источник
From:
заголовка в вашу электронную почту :)Message-Id
которых я не очень разбираюсь, и, вероятно, я ошибаюсь ... кажется, проще, чтобы демон очистки позаботился об этом.From
заголовок. Но, если вы хотите сгенерировать свой собственный идентификатор сообщения, вы можете использовать рекомендации, подобные этому черновику IETFВы должны указать
inet_interfaces
на docker bridge (docker0
) в конфиге postfix, расположенном в set/etc/postfix/main.cf
Дополнительные внутренние рабочие детали при отправке электронной почты от docker-through-postfix -установлено-на-хосте
источник
172.17.0.0/16
чтобыmynetworks
в/etc/postfix/main.cf
иservice postfix restart
.Это наполовину или хотя бы наполовину проверенный ответ, поскольку в настоящее время я работаю над той же проблемой. Я надеюсь, что кто-то может помочь объяснить то, что я пропустил.
Ответ от ОП (Дэвид Грейсон) звучит для меня как переосмысление почтовой катушки postdrop, но использование этой почтовой катушки звучит как многообещающий подход, так что вот где я дошел.
Интерфейс совместимости / usr / bin / sendmail, предоставляемый postfix, передает почту на postdrop, которая является sgid postdrop, что позволяет ему сохранять почту в очереди maildrop по адресу / var / spool / postfix / maildrop. Это должно происходить в док-контейнере. Остальная часть постфикса не должна запускаться в контейнере.
Итак, я хост монтирую / var / spool / postfix / maildrop и / var / spool / postfix / public. Я могу получить почту, доставленную в / var / spool / postfix / maildrop в хост-среде, так как я смонтировал каталог очереди maildrop. Потому что я смонтировал
/var/spool/postfix/public
,maildrop
может сигнализироватьpickup
о получении почты из очереди. К сожалению, используются uids и gids, если я об этом не позабочусь, это означает, что раскладка в каталоге хоста не может читать файлы спула, и что еще хуже, установка postfix портит разрешения для каталога maildrop в среде хоста.Тем не менее, это похоже на работу:
Хотя это работает, я не очень доволен жестким кодированием uids и gids. Это означает, что один и тот же контейнер не может быть подсчитан для запуска везде одинаково. Я полагаю, однако, что если вместо монтирования тома с хоста я монтирую его из контейнера, который запускает postfix, то он никогда не конфликтует, и мне нужна только одна постфиксная установка для получения почты из многих контейнеров. Я бы установил эти uids и gids в базовом изображении, от которого наследуются все мои контейнеры.
Хотя мне интересно, действительно ли это хороший подход. С такой простой почтовой конфигурацией и отсутствием демона, используемого в контейнере для повторной попытки доставки, более подходящий локальный MTA, такой как msmtp, может быть более подходящим. Он будет доставлять через TCP на ретранслятор на том же хосте, где будет происходить спулинг.
Проблемы с подходом msmtp включают в себя:
В целом, подход с общим спулинговым постфиксным спулом выглядит более уязвимым для настройки, но менее вероятен сбой во время выполнения (ретрансляция недоступна, поэтому почта отбрасывается).
источник
Я решил, что способ, которым контейнер будет отправлять почту, заключается в том, чтобы записать ее в файл в определенном каталоге, который будет доступен как из контейнера, так и с хоста как «том» Docker.
Я сделал сценарий оболочки под названием mailsender.sh, который читает почту из указанного каталога, отправляет ее в sendmail, а затем удаляет:
Ubuntu использует upstart, поэтому я создал файл с именем,
/etc/init/mailsender.conf
чтобы превратить этот скрипт в демона:Я могу начать службу с
start mailsender
и остановить егоstop mailsender
. Я могу посмотреть его журналы/var/log/upstart/mailsender.log
и, конечно, я могу контролировать его, используя файл PID.Вам нужно создать
/var/mailsend
каталог, а затем сделать его доступным из контейнера Docker, добавив аргумент-v /var/mailsend:/var/mailsend
в вашуdocker run
команду.источник