수신된 이메일만 IMAP 폴링으로 처리하는 방법이 있나요?

좋아요, 다른 팀 멤버가 IMAP 폴링이 제대로 작동하지 않았고, 어느 정도 제거되었으며, 이 몇 가지 설정은 구현을 목표로 했을 때 남은 잔재처럼 보인다고 언급했습니다.
수정: 이에 대한 진술을 찾았습니다: IMAP support for group inboxes - #39 by martin
나에게는 POP3가 비추천(deprecated)되고 오늘날에는 실용적이지 않으므로, 이는 한 발 물러선 조치처럼 보입니다. 사람들은 보통 여러 메일 클라이언트(최소 폰 + PC)를 사용하니까요. 따라서 Dovecot 인스턴스에서 POP3 리스너를 활성화할 필요성을 전혀 보지 못합니다.

그럼에도 불구하고, 저는 메일 리시버 컨테이너와 그 Ruby 스크립트 없이도 기존 Postfix에 Discourse 직접 메일 리시버 API를 구현하는 데 성공했습니다. 대신 Discourse 메일 리시버 컨테이너에서 사용되는 Postfix 통합 방식을 대부분 따랐습니다: mail-receiver/Dockerfile at main · discourse/mail-receiver · GitHub

/etc/postfix/main.cf:

# Discourse 답장 이메일 주소를 위해, 전송 매핑(transport mapping)을 통해 기본 전송(transport)을 오버라이드합니다
transport_maps=hash:/etc/postfix/transport

/etc/postfix/transport

# "discourse"라는 이름의 서비스가 정의된 Discourse 답장 주소로 보내지는 이메일의 전송 엔드포인트로 사용됩니다
forum.reply@dietpi.com discourse:

/etc/postfix/master.cf

# "discourse" 전송 서비스를 (프라이빗) UNIX 소켓에서 대기하는 curl로 파이프하는 pipe 데몬으로 정의합니다
# curl로 파이프가 작동하려면 권한이 없거나(unprivileged) chrooted될 수 없습니다
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 사용자만 접근할 수 있는 디렉토리로, Postfix chroot 디렉터리 /var/spool/postfix 내에 있음을 의미합니다.
  • 그러나 curlpipe가 작동하려면 권한이 없거나(unprivileged) chrooted될 수 없습니다 (n n).
  • 그런 다음 nobody:nogroup 사용자:그룹을 사용하여 권한을 최소화합니다.
  • 리시버 API에 따라, 이메일은 email 폼 필드에 첨부되어야 하며, 이는 curl의 <- STDIN 호출을 통해 수행할 수 있습니다. Api-UsernameApi-Key 헤더를 추가해야 하는데, 전자는 보통 system이고, 후자는 Discourse에서 생성할 수 있으며, receive_emails 권한만 가진 세밀한(granular) API 키입니다. 그런 다음 해당 HTTP 엔드포인트를 사용합니다.

우리는 의도적으로 리시버 컨테이너가 수행하는 빠른 거부(fast rejection) 정책 검사를 건너뜁니다:

  • FromTo 헤더의 존재, 발신자가 도메인이 포함된 완전한 주소인지, 그리고 BLACKLISTED_SENDER_DOMAINS 컨테이너 변수를 통해 선택적으로 정의할 수 있는 블랙리스트에 포함되어 있는지 확인합니다. 그리고 발신자 및 수신자 주소를 다른 Discourse HTTP API 엔드포인트로 전송하여, 수신자가 구성된 답장 이메일 주소 템플릿과 일치하는지, 그리고 발신자 주소가 등록된 사용자에게 속하는지 확인합니다. 포럼이 수신 이메일에 대해 새로운 스테일(stale) 사용자를 생성하도록 구성되어 있는 경우를 제외하고, 이는 우리의 경우 이상하게도 기본적으로 활성화되어 있었습니다?
  • 이 중 대부분과 더 많은 것들은 우리의 공개 Postfix SMTP 리시버 서비스에서 어쨌든 검사되며, 모든 것이 rspamd를 통과하여 DKIM, SPF, DMARC 검사를 함축합니다.
  • 그러나 가장 중요하게는, 동일한 검사가 최종 Discourse 이메일 리시버 백엔드에서 어쨌든 수행됩니다. 약간 단점인 것은: 발신자는 메일러 데몬 거부/바운스 이메일을 받지 못하지만, 잘못된 발신자/수신자의 경우 오류는 대신/오직 우리의 Discourse에 기록됩니다. 그러나 발신자와 수신자가 올바르고, 오직 메일 콘텐츠가 예상대로(특히 Message-ID 헤더 누락) 아닌 경우, 발신자는 Discourse에서 적절한 이메일을 받습니다. 다른 경우와 비교할 때 구현이 최소한의 오버헤드를 가지고 있고, 메일당 네트워크 요청과 백엔드 처리가 하나씩 적으므로, 누락된 SMTP 거부/바운스 메일은 제 생각에는 전혀 문제가 되지 않습니다.
  • 일반적으로: master.cf 명령 인자에서 공백에 주의하세요. 공백을 문자 그대로 유지하기 위한 인용부호는 작동하지 않습니다. 대신 이러한 인자는 중괄호로 감싸야 합니다: {some arg with spaces}. 그러나 이 경우, 인자 중에는 공백이 포함되지 않으며, 헤더 키와 값 사이의 공백도 선택 사항입니다.

지금까지 잘 작동하며, Dovecot으로의 기본 가상 전송과, 팀의 모든 사람이 서버에서 추가 메일박스를 원하거나 필요로 하지 않기 때문에 일부 이메일을 외부 주소로 중계(relay)하는 데에도 전송 매핑이 사용되는 기존 설정에 무리 없이 통합됩니다. 가상 별칭 매핑에서 캐치올(catch-all) 주소가 정의된 경우, Discourse 답장 주소는 해당 테이블에 추가해야 하며, 자신을 가리키도록 매핑되어야 합니다(다른 로컬 가상 사용자/주소와 같이).