발신 메일에 로컬 이메일 서버/sendmail을 사용해야 하나요?

우리는 자체 이메일 서버를 구축했고, Discourse Docker 컨테이너와 이를 가장 효율적으로 사용하는 방법에 대해 궁금했습니다.

물론 SMTP 세부 정보와 자격 증명을 설정하는 것만으로 충분하지만, SMTP 서버가 동일한 머신에서 실행되고 있으므로 불필요한 오버헤드처럼 느껴집니다.

sendmail은 작동하지만, Discourse는 컨테이너 내에서 실행되므로 호스트의 sendmail에 접근할 수 없습니다.

이 포럼에서 검색해 보면, DISCOURSE_SMTP_DOMAIN을 자격 증명 없이 사용한 예시가 하나 있습니다. 컨테이너 내에서 swaks를 사용하여 동일한 작업을 수행하면 작동합니다: How to get Discourse to work with Postfix - #18 by sonmicrosystems
아마도 그 경우에도 기본 포트에서 정상적인 SMTP 제출이 이루어지고, 요청이 localhost에서 온다는 이유로 Postfix가 인증 없이 이를 수용하는 것 같습니다.

다른 방법을 아시는 분이 있을까요? 사용 중인 Ruby 라이브러리가 일반적으로 모든 것을 지원한다는 것을 알 수 있습니다: GitHub - discourse/mail: A Really Ruby Mail Library · GitHub
Discourse 설정에서 눈길을 끈 것은 Delivery method(전달 방법) 필드입니다:

GUI에서 이 설정을 변경할 수 없는데, 아마도 컨테이너 YAML이 DISCOURSE_SMTP_ADDRESS 등을 통해 이를 강제하기 때문인 것 같습니다. 하지만 전달 방법에 대한 변수는 찾을 수 없습니다.

아마도 다른 방법을 아는 사람이 있을 것입니다. 그 때까지 저는 정상적인 SMTP 제출 포트 인증을 설정할 예정입니다.顺便说一下, 최근에 추가되었지만 아직 샘플에 포함되어 있지 않은(포함되어야 하지만) DISCOURSE_SMTP_FORCE_TLS에 감사드립니다. 저는 STARTTLS를 허용할 의도는 없으며, 암시적/즉시 TLS만 허용할 계획입니다.

어떤 면에서 불필요한 오버헤드인가요? 어쨌든 Discourse에서 SMTP 서버로 데이터를 전송해야 하지 않나요? 아니면 그렇지 않나요?

참고: 만약 다른 컨테이너라면, 이론적으로 브리지 네트워크를 사용하고 호스트명 대신 smtp 컨테이너 이름을 사용할 수 있지만, 이는 성능상의 이점을 제공하지 않습니다.

로컬 SMTP 서버를 통해 이메일을 보내는 방법에는 두 가지가 있습니다:

  1. 587 포트의 STARTTLS 또는 465 포트의 암시적/즉시 TLS와 같이 제출(submission) 포트에 연결하고 인증을 수행합니다. => 네트워크 요청이 발생하며 smtpd를 통해 검사 및 제한이 적용됩니다.
  2. sendmail 또는 유사한 도구를 사용하여 로컬 pickup 명령(Postfix의 경우)을 호출합니다. 이는 네트워크 연결을 수행하지 않으며 smtpd 제출 서비스에 구성된 모든 검사 및 제한을 우회합니다.

후자의 방식이 더 단순하고 빠르며, PHP 메일러와 Discourse에서 사용하는 이 Ruby 메일 라이브러리 같은 일반적인 런타임 시스템 및 프레임워크에 구현되어 있습니다. 또한 인증이 우회되므로 어디에도 평문 자격 증명을 저장할 필요가 없습니다. 다시 말해, 이 경우 SMTP 서버는 전혀 사용되지 않고 SMTP 클라이언트만 사용됩니다.

제 생각에는 제출 포트 연결 관련 작업이 Discourse가 일반적으로 수행하는 작업과 비교할 때 서버 부하에 상당한 영향을 미치지 않을 것입니다. 후자의 문제는 제출 포트에서 smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject 규칙을 사용하여 인증을 수행하기 전에 루프백 IP(기본값, mynetworks 설정)로부터의 제출을 허용함으로써 해결할 수 있습니다. 컨테이너에서 온 요청이 다른 IP로 식별된다면 mynetworks에 추가할 수 있습니다. 이전에 링크한 토픽의 경우 이것이 작동하는 방식이었을 것으로 추정합니다.

다음에 Discourse를 업데이트/재빌드하여 변경된 SMTP 설정이 적용될 때 확인해 보겠습니다. 작동 방식을 보고하겠습니다.

하지만 여전히 다른 방법이 있는지, 그리고 이 “전달 방식(Delivery method)” 설정이 무엇에 관한 것인지 궁금합니다.

Postfix는 컨테이너 내부가 아니라 호스트에서 실행되지만, 네트워크 기반 인증이므로 큰 차이는 없을 것입니다.

잠시 생각해보니, sendmail 등이 컨테이너 내부에서 작동할 수 없는 것은 당연합니다. 이는 Postfix 실행 파일, 라이브러리, 설정의 광범위한 부분에 대한 직접적인 접근을 필요로 하기 때문입니다. 컨테이너에 바인드 마운트할 수 있는 일종의 마법 소켓이 있는 경우를 제외하고는 말입니다. :smile:

sendmail을 이렇게 깊이 파고든 지는 좀 됐다. VM 한 대에는 mailcow 스택을, 다른 한 대에는 Discourse를 돌리고 있다. 재미를 위해서가 아닌 한, 이렇게까지 깊이 파볼 가치가 있을지 모르겠다.

모두의 모험에 행운을 빈다. 배운 것을 공유해 주길 바란다.

아마도 그렇지 않겠죠 :sweat_smile:. 하지만 저는 특정 맥락에서 완벽주의자이고, 깊이 파고들어 모든 세부 사항을 배우는 것을 즐깁니다. Dovecot, Postfix, rspamd, dkimpy-milter, PostSRSd 등을 단계별로 설정하는 데 몇몇 저녁을 보냈습니다. 사용 가능한 거의 모든 설정, 기본값이 왜 그런지, 그리고 우리가 다르게 설정하고 싶은지, 그리고 왜 그런지 등을 배우면서요. 하지만 어쨌든, 이제 저는 인터넷에 있는 다양한 이메일 서버 가이드의 저자들보다 대부분의 것을 더 잘 이해하는 것 같습니다 :face_with_tongue:.

이 주제를 #installation:hosting으로 이동합니다. 공식 설치 지침을 읽어보셨다면 아시겠지만, 자체 이메일 서버 호스팅을 시도하는 것은 권장하지 않습니다. 이메일은 어렵습니다!

시스템이 추가로 이메일 서버를 호스팅할 수 있는지 여부에 Discourse가 어떤 관련이 있는지 잘 모르겠습니다. 물론, 이메일을 보내는 또 다른 경로가 이론적으로 열릴 수 있다는 점은 제외하고요.

다만 이메일 수신(다른 주제)의 경우 영향을 미칩니다. 이메일 수신기 컨테이너를 호스팅할 수 없기 때문이며, 적어도 포트 25에서 직접 수신하는 것은 불가능합니다. 하지만 Discourse의 이메일 수신기 API를 직접 사용하는 것은 Postfix 설정에서 불과 2~3줄에 불과한 것으로 나타났습니다: Is there a way to only IMAP polling for incoming emails - #2 by MichaIng

하지만 위에서 언급했듯이, 이메일 서버를 적절히 설정하는 일은 쉬운 작업은 아니었습니다. 하지만 배우는 과정은 매우 흥미로웠습니다 :slightly_smiling_face:.

네! 분명 도전적이고 흥미로울 거예요. 저도 예전에 다양한 서비스를 설치하고 직접 운영해보며 제 나름의 모험을 겪었거든요! :upside_down_face:

미래의 용감한 여행자들, 그리고 당신 자신을 위해 배운 내용을 이 주제에 업데이트해 주시면 좋겠습니다. 다만, Support 카테고리는 지원되는 설치 환경, Discourse 코어 및 공식 플러그인과 컴포넌트에 한해 사용한다는 점을 기억해 주세요.

무슨 소리야. Dovecot은 좋은데. 그럼 왜 Postfix를 쓰지? Dovecot에 Exim을 쓰면 안 돼?

Postfix에는 어떤 문제가 있는 것일까요? 제가 처음 읽은 메일 서버 설정 가이드에 포함되어 있었고, 파이프라인 초기 단계에서 스팸과 봇 접근을 줄이기 위한 내부 필터 옵션이 좋은 근거로 보였기 때문입니다.

자, 약간 주제에서 벗어난 이야기이지만, Discourse의 sendmail/pickup 사용에 대해 말씀드리자면.

이 문제를 해결/답변 완료로 표시하겠습니다. 어떤 서버를 사용하든 Discourse 컨테이너가 호스트의 sendmail에 접근할 수 없다는 것은 당연한 일입니다. 따라서 SMTP 제출(submission)을 사용해야 하며, 이를 위해 Postfix에서 Docker 컨테이너 IP 범위로 인증을 수행할 수 있고, Dovecot에서는 passdb/userdb 인증을 건너뛸 수 있습니다.