Есть ли способ опрашивать IMAP только на наличие входящих писем

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

Существует опрос по POP3, но наш Dovecot отключил POP3, используя только IMAP. Есть настройки для интервалов опроса IMAP, но нет параметров для включения опроса IMAP, определения хоста, порта, учетных данных и т. д., как для опроса POP3. Использует ли опрос IMAP те же настройки, что и POP3, и можно ли фактически отключить опрос POP3, установив его интервал в 0 минут или что-то подобное?

Этот вопрос уже задавался ранее, но ответа нет: Is there a way to use IMAP instead of POP3 for replies by email?
Я не планирую запускать второй Postfix в контейнере mail-receiver Discourse, да и это не сработает из-за использования порта 25 на хосте.

Лучшим вариантом, конечно, было бы напрямую использовать API входящей почты Discourse с нашим Postfix. Это даже не выглядит слишком сложным: mail-receiver/lib/mail_receiver/discourse_mail_receiver.rb at main · discourse/mail-receiver · GitHub

  • POST-запрос с системным пользователем, API-ключом и адресом отправителя в виде данных формы.
  • Но проверки на корректность данных на первый взгляд кажутся более сложными: https://github.com/discourse/mail-receiver/blob/main/lib/mail_receiver/fast_rejection.rb
  • Я мог бы реализовать это как shell-скрипт, который условно (при получении письма) перенаправлял бы данные, но поддерживать его в актуальном и рабочем состоянии, вероятно, нецелесообразно.

Таким образом, опрос только по IMAP был бы моим предпочтительным решением. Надеюсь, это возможно.

РЕДАКТИРОВАНИЕ: Или мы просто установим среду выполнения Ruby, скопируем библиотеки и исполняемые файлы mail-receiver и fast-reject на хост, как это делает Dockerfile, и вызовем их из нашего Postfix через transport_maps тем же способом: mail-receiver/Dockerfile at main · discourse/mail-receiver · GitHub
Кто-нибудь пробовал это сделать?

Хорошо, ещё один участник команды упомянул, что опрос IMAP никогда не работал должным образом, был частично удалён, и эти несколько настроек, похоже, являются остаточным мусором от времени, когда планировалась его реализация.
РЕДАКТИРОВАНИЕ: Нашёл соответствующее заявление: IMAP support for group inboxes - #39 by martin
Кажется, это шаг назад, поскольку для меня POP3 в наши дни устарел и непрактичен, учитывая, что люди обычно используют несколько почтовых клиентов (минимум телефон + ПК). Поэтому я не вижу смысла вообще включать слушателей POP3 в экземпляре Dovecot.

Однако мне удалось реализовать прямой API приёмника почты Discourse в нашем существующем Postfix без контейнера приёмника почты и даже без его Ruby-скриптов, следуя в основном интеграции Postfix, используемой в контейнере приёмника почты Discourse: mail-receiver/Dockerfile at main · discourse/mail-receiver · GitHub

/etc/postfix/main.cf:

# Для адреса ответа на электронную почту Discourse мы переопределяем транспорт по умолчанию через сопоставление транспорта
transport_maps=hash:/etc/postfix/transport

/etc/postfix/transport

# Служба с именем "discourse" используется как конечная точка транспорта для писем на определённый адрес ответа Discourse
forum.reply@dietpi.com discourse:

/etc/postfix/master.cf

# Мы определяем транспортную службу "discourse" как пайп-демон, передающий данные в curl, слушающий на (приватном) UNIX-сокете
# Она не может быть непривилегированной или работать в chroot, чтобы пайп в curl функционировал
discourse unix - n n - - pipe user=nobody:nogroup argv=/usr/bin/curl -X POST -F email=<- -H Api-Username:system -H Api-Key:fooooobaaaaarbaaaaaaz https://dietpi.com/forum/admin/email/handle_mail
  • Таким образом, сопоставление транспорта перенаправляет письма на адрес ответа в нашу пользовательскую службу discourse.
  • Лучшая производительность достигается при использовании UNIX-сокета, который может быть приватным (первый -), поскольку никто другой не должен его использовать. Под «приватным» подразумевается, что сокет расположен по адресу /var/spool/postfix/private/discourse, в каталоге, доступ к которому имеет только пользователь postfix, внутри chroot-каталога Postfix /var/spool/postfix.
  • Однако служба не может быть непривилегированной или работать в chroot для корректной работы pipe в curl (n n).
  • Затем мы минимизируем права доступа, используя пару пользователь:группа nobody:nogroup.
  • Следуя API приёмника, письмо должно быть прикреплено к полю формы email, что можно сделать через вызов STDIN curl с параметром <-. Необходимо добавить заголовки Api-Username и Api-Key: первый обычно равен system, второй можно сгенерировать в Discourse как гранулярный API-ключ с разрешениями только receive_emails. Затем используется соответствующий HTTP-эндпоинт.

Мы намеренно пропускаем проверки политики быстрого отклонения, выполняемые контейнером приёмника:

  • Он проверяет наличие заголовков From и To, является ли отправитель полным адресом с доменом, и находится ли он в чёрном списке, который можно опционально определить через переменную контейнера BLACKLISTED_SENDER_DOMAINS. Кроме того, он отправляет адреса отправителя и получателя на другой HTTP-эндпоинт Discourse, который проверяет, соответствует ли получатель настроенному шаблону адреса ответа, и принадлежит ли адрес отправителя зарегистрированному пользователю, если только форум не настроен на создание новых «устаревших» пользователей при входящих письмах, что странно было включено по умолчанию в нашем случае?
  • Большинство этих проверок, а также дополнительные, уже выполняются нашим публичным SMTP-сервисом приёмника Postfix, и всё проходит через rspamd, что подразумевает проверки DKIM, SPF и DMARC.
  • Но самое главное, те же самые проверки выполняются финальным бэкендом приёмника почты Discourse. Единственный недостаток: отправители не получают обратно письмо от почтового демона с отказом/откатом, а ошибки в случае некорректного отправителя/получателя вместо этого (или только) логируются в нашем Discourse. Однако, если отправитель и получатель корректны, но содержимое письма не соответствует ожиданиям (особенно отсутствует заголовок Message-ID), отправители получают корректное письмо от Discourse. Отсутствие SMTP-отказов/письм об откате в целом приемлемо, учитывая, что в противном случае реализация требует минимальных накладных расходов, одного сетевого запроса и обработки на бэкенде на письмо меньше и т. д.
  • Вообще: будьте осторожны с пробелами в аргументах команд в master.cf. Использование кавычек для сохранения пробелов в буквальном виде не работает. Вместо этого такой аргумент необходимо обернуть в фигурные скобки: {some arg with spaces}. Но в данном случае ни один аргумент не содержит пробелов; пробелы между ключом и значением заголовка также опциональны.

Работает отлично, и интеграция происходит бесшовно в нашу существующую настройку с виртуальным транспортом по умолчанию в Dovecot, а также с использованием сопоставления транспорта для ретрансляции некоторых писем на внешние адреса, поскольку не каждый член команды хочет/требует дополнительный почтовый ящик на нашем сервере. Если в таблице виртуальных алиасов определён адрес catch-all, адрес ответа Discourse необходимо добавить в эту таблицу, сопоставив его сам с собой (как и других локальных виртуальных пользователей/адресов).