Customize direct-delivery Postfix configuration

If you have a mail receiver container which requires customised Postfix configuration, this is the topic for you. Herein are described the steps required to set Postfix main.cf configuration variables to whatever your heart desires.

Postfix configuration variables can be set via the container environment. Any environment variable starting with POSTCONF_ will set a Postfix configuration variable named for the rest of the environment variable to the value of the environment variable. For example, if you set the environment variable POSTCONF_always_bcc to bob@example.com, then Postfix will be configured with always_bcc = bob@example.com, which will send a copy of all incoming mail to Bob. Poor Bob.

Procedure

  1. Figure out what configuration variables you want to set, and what values to set them to. This may be done by reading the fine manual, or through recommendations in other Discourse documentation, or otherwise.

  2. Connect to your Discourse server via SSH, grab some root privileges, and head over to where all the discourse-docker configuration lives:

    ssh ubuntu@192.0.2.42
    sudo -i
    cd /var/discourse
    
  3. Open up containers/mail-receiver.yml in your text editor of choice, and swing down to the env: section of the file. Somewhere in there, add entries for the variables you want to add, being careful to not modify anything else, and maintaining appropriate indenting. For example, if we were adding our always_bcc setting, the file might look a bit like this:

    env:
      LANG: en_US.UTF-8
      MAIL_DOMAIN: discourse.example.com
      DISCOURSE_BASE_URL: 'https://discourse.example.com'
      DISCOURSE_API_KEY: abcdefghijklmnop
      DISCOURSE_API_USERNAME: system
    
      POSTCONF_always_bcc: 'bob@example.com'
    

    Once you’re happy with what you’ve added, save and exit your editor.

  4. To load the configuration, you simply have to restart the mail-receiver container (a rebuild is not required):

    ./launcher restart mail-receiver
    

    After a brief spasm, the container should be running again.

  5. Test your changes. Ensure both that what you wanted to have happen has, indeed, happened, and also that nothing you didn’t expect to change hasn’t.

Addendum: adding files to the mail-receiver container

Many Postfix configuration parameters require access to “database files”, which provide key/value information which Postfix uses to make decisions about what do with mail. If you see that a configuration parameter accepts a filename that looks like hash:/some/file, you’ve found a use for database files.

The thing is, Postfix running inside the container needs to be able to get at those files while it’s running, which means you need to either copy those files into the container, or (preferably) put those files into a directory on the host, and then mount that directory as a volume inside the container. These instructions describe the second method.

Once you have completed this procedure, any file you place into /var/discourse/shared/mail-receiver/etc will immediately become visible at /etc/postfix/shared inside the container, and any changes you make to those files will be immediately visible to Postfix.

Here’s how to make it happen.

  1. If you’re not still logged in as root to your Discourse server, do so again:

    ssh ubuntu@192.0.2.42
    sudo -i
    cd /var/discourse
    
  2. Open up containers/mail-receiver.yml in your text editor of choice, and this time head for the volume: section. Underneath the existing definition for the /var/spool/postfix directory, add another one, so that your volume section looks like this:

    volumes:
      - volume:
          host: /var/discourse/shared/mail-receiver/postfix-spool
          guest: /var/spool/postfix
      - volume:
          host: /var/discourse/shared/mail-receiver/etc
          guest: /etc/postfix/shared
    

    Save/exit your editor.

  3. To attach the new volume, you simply have to restart the mail-receiver container (a rebuild is not required):

    ./launcher restart mail-receiver
    

All done!

10 лайков

Мэтт, думаешь, возможно включить учётные записи вроде admin@domain или info@domain в этой конфигурации Postfix?

Мне нужно всего несколько адресов для входящей почты, и у меня это работает с Discourse, но я не могу настроить учётные записи (они, похоже, заблокированы по умолчанию, хотя сообщения обрабатываются).

Спасибо за все твои руководства.

Я только что настроил пробную службу Discourse, используя Digital Ocean и Mailgun для исходящей электронной почты. У меня есть домен с соответствующей MX-записью, указывающей на IP-адрес Digital Ocean. Исходящая и входящая электронная почта работают в Discourse корректно. Ответы на темы генерируют исходящие письма для пользователей с включёнными уведомлениями, а тестовые пользователи могут отвечать на эти письма, и сообщения появляются в Discourse. Пока всё отлично.

Я попытался добавить опцию POSTCONF_always_bcc, как указано выше, но, похоже, она не работает. Я подозреваю, что часть Discourse, отвечающая за получение почты (mail-receiver), не может корректно отправлять письма через Mailgun, хотя часть приложения (app) умеет это делать: в файле app.yml указаны имя пользователя и пароль сервера Mailgun, но я не видел примеров того, как внести эту информацию в файл настроек mail-receiver.

Я знаю, что опция always_bcc считывается и обрабатывается, потому что если я ввожу:

./launcher enter mail-receiver

а затем выполняю

mailq

то вижу тестовое сообщение, которое я отправил, находящееся в очереди и пытающееся быть доставленным. В столбце «-Sender/Recipient-------» указан адрес, с которого пришло моё тестовое сообщение, фраза «(unknown mail transport error)» и затем адрес электронной почты, который я указал в настройке always_bcc.

Я надеялся каким-то образом фильтровать входящие сообщения так, чтобы, если сообщение отправлено на postmaster@mydomain или admin@mydomain, оно пересылалось в открытый интернет через Mailgun на мой адрес Gmail, а не отправлялось в Discourse для обработки. Возможно, именно это пытался сделать пользователь @satonotdead.

Буду признателен за любые подсказки, как это реализовать!

Хм. Да, сначала вам нужно настроить mailgun получателя почты так, чтобы у него был способ доставки писем, так как он не знает о учетных данных или механизме транспорта в app.yml. Думаю, вам потребуется добавить более полную конфигурацию, как намекнуто в следующем разделе о монтировании томов; детали выходят за рамки этого документа.

Простое решение вопроса «как мне работать с письмами от postmaster и admin» — создать для каждого из них отдельную группу, добавить туда всех, кто должен получать эти письма, и тогда они смогут обрабатывать их как групповые сообщения.

3 лайка

Вы имели в виду «mail-receiver», а не Mailgun? То есть научить «mail-receiver» общаться с Mailgun через публичный интернет и правильно передавать учётные данные, чтобы попросить его выполнить фактическую доставку?

Да. Извините за путаницу.

Да, именно это, либо, alternatively, настроить mail-receiver (то есть Postfix) для доставки почты каким-либо другим способом. Я скорее склоняюсь к тому, что если вы знаете, как это сделать, то, возможно, лучше просто сделать это самостоятельно, а не использовать mail-receiver.

Другое решение — запустить какой-то процесс <mail thing>, который будет обрабатывать почту для domain и пересылать остальное на mail-receiver, возможно, через другой MX-запись.

Проведя вечер в попытках различных комбинаций, я смог установить Postfix вне контейнеров, в которых работает Discourse, и отправлять электронную почту через Mailgun из командной строки. Таким образом, я успешно настроил Postfix для использования Mailgun. Однако мне пока не удаётся настроить параметры в контейнере mail-receiver, чтобы обеспечить ретрансляцию через Mailgun. Уверен, что должно существовать (простое!) решение. Я не могу найти логи, чтобы понять, почему сообщения застревают в очереди почты. Контейнеры появились уже после того, как я в последний раз работал с Linux (несколько лет назад). Есть ли способ включить логирование, чтобы я мог увидеть, какие соединения пытается установить Postfix, и определить, где именно проблема? Концептуально я хочу, чтобы письма, отправленные на admin@mydomain, после поступления сразу пересылались через Mailgun на мой личный аккаунт Gmail, а письма на category1@mydomain, category2@mydomain и т. д. перенаправлялись локально в Discourse для создания публикаций.

2 лайка

Можно ли использовать mail-receiver вне контейнеров Discourse на другом VPS или в другом дата-центре?

Идея заключается в том, чтобы изменить IP-адрес Discourse для повышения конфиденциальности и использовать внешний “mail-receiver”, работающий и аутентифицирующийся с форумом Discourse.

Да, я именно этим и занимаюсь. Получатель почты работает на DigitalOcean, а Discourse — на машинах в другом дата-центре.

Может, кто-нибудь объяснит, как это сделать? Этот парень просит деньги даже за ответ.

Какой у вас вопрос?

Для настройки почтового получателя на любом сервере не требуется ничего особенного, если на нём установлен Docker и есть доступ к необходимым портам.

Я настроил mail-receiver, так как это быстро и просто… но когда я перехожу к проверке обработки писем, получаю ошибку 404.

Мой сайт находится на поддомене, например: forum.site.com.

В приложении mail-receiver у меня указан следующий конечный адрес:

DISCOURSE_MAIL_ENDPOINT: ‘http://forum.site.com/admin/email/handle_mail

Мне нужно также пересобрать Discourse?

Если вы получаете ошибку 404, то, скорее всего, неверен API-ключ.

2 лайка

Это стандартный API, но всё равно выдаёт 404.. Я отправил вам в Google Talk, пожалуйста, проверьте.

1 лайк

Настройка SMTP-баннера?

Суперинструмент MXtoobox сообщает об ошибке при проверке SMTP-баннера.
image

Обычно баннер EHLO должен совпадать с MAIL_DOMAIN, который, в свою очередь, должен соответствовать обратному DNS-указателю (запись PTR). Таким образом, если мой mail-receiver работает на домене discourse.example, то POSTCONF_myhostname должен быть установлен в discourse.example.

Как правильно настроить баннер EHLO?

Моя первая мысль заключалась в том, чтобы попытаться установить HOSTNAME в файле mail-receiver.yml, чтобы он заменил исходное значение host-mail-receiver.localdomain в /etc/postfix/mail-receiver-environment.json. Однако это не меняет ни /etc/hostname, ни параметр myhostname в конфигурации Postfix.

Я склоняюсь к использованию POSTCONF_myhostname, но боюсь, что это вызовет нежелательные побочные эффекты, так как переменная $myhostname используется в нескольких местах, и тогда она перестанет совпадать с /etc/hostname.

root@host-mail-receiver:/etc/postfix# postconf | grep myhostname
lmtp_lhlo_name = $myhostname
local_transport = local:$myhostname
milter_macro_daemon_name = $myhostname
myhostname = host-mail-receiver.localdomain
myorigin = $myhostname
smtp_helo_name = $myhostname
smtpd_proxy_ehlo = $myhostname
root@host-mail-receiver:/etc/postfix# cat /etc/hostname
host-mail-receiver

Существует настройка, которую запрашивает Discourse-setup. Я не помню её названия, и на телефоне её трудно найти. Вы можете посмотреть исходный код или запустить его.

Настройка Postfix smtp_helo_name изменяет имя, указываемое в команде HELO (или EHLO), но это параметр исходящей доставки, тогда как SMTP-баннер отправляется при получении почты. Имя хоста по умолчанию, указанное в нём, берётся из myhostname, но вы можете изменить баннер, чтобы он отображал что-то другое, с помощью настройки smtpd_banner.

1 лайк

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

Так что спасибо, что помогли мне осознать, что проблема связана с API-ключом :slightly_smiling_face:

1 лайк

Возможно, что-то изменилось с момента написания этого сообщения? Я обнаружил, что добавление значения POSTCONF_smtpd_banner в секцию env: абсолютно не применялось после нескольких перезапусков. Чтобы изменения вступили в силу, мне пришлось выполнить пересборку (./launcher rebuild mail-receiver).

Привет, друзья,

Я только что завершил миграцию домена (согласно Change the domain name or rename your Discourse), и всё прошло гладко. Однако я использую контейнер mail-receiver с MX-записями для входящей почты в несколько категорий…

Насколько я могу судить, конфигурация контейнера по умолчанию жёстко задаёт как входящий домен, так и путь к сертификатам LetsEncrypt. Возможно ли настроить поддержку двух доменов — либо в конфигурации, либо через эти расширенные опции?