Discourse doctor에서 SMTP 자격 증명 파싱이 작동하지 않음 (+ 관리자 등록 이메일도 작동하지 않음)

자, 먼저 말씀드리자면 현재 프로덕션 환경인데, 첫 번째 가입 안내 이메일을 보내지 못하고 있습니다.

SMTP 설정이 정확하다고 확신합니다.
사용 중인 포트로 메일 서버에 ping과 telnet을 수행할 수는 있지만, "EHLO mailserver"를 실행하는 즉시 외부 호스트에 의해 연결이 닫힙니다.

로그의 하단에는 다음과 같은 내용이 표시됩니다:

  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.2ms | Allocations: 32)
Delivered mail f3853b94-b772-48c2-b1b7-a78bbcbfc5c1@discourse.mywebsite.com (60177.6ms)
Job exception: Net::ReadTimeout

그리고 SMTP 설정이 정확한지 확인하려고 /var/discourse/discourse-doctor를 실행해 보았지만, 설정을 검증하지 못했습니다. 다음과 같은 메시지가 표시됩니다:

==================== YML SETTINGS ====================
awk: not an option: --field-separator=:
DISCOURSE_HOSTNAME=
awk: not an option: --field-separator=:
SMTP_ADDRESS=
awk: not an option: --field-separator=:
DEVELOPER_EMAILS=
awk: not an option: --field-separator=:
SMTP_PASSWORD=
awk: not an option: --field-separator=:
SMTP_PORT=
awk: not an option: --field-separator=:
SMTP_USER_NAME=
awk: not an option: --field-separator=:
LETSENCRYPT_ACCOUNT_EMAIL=

하지만 제 YAML 파일(./containers/app.yml)은 완벽하게 포맷된 것 같습니다.

  ## TODO: The SMTP mail server used to validate new accounts and send notifications
  # SMTP ADDRESS, username, and password are required
  # WARNING the char '#' in SMTP password can cause problems!
  DISCOURSE_SMTP_ADDRESS: mail.redacted.com
  DISCOURSE_SMTP_PORT: 465
  DISCOURSE_SMTP_USER_NAME: redacted@redacted.com
  DISCOURSE_SMTP_PASSWORD: "redacted"
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)

  ## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
  LETSENCRYPT_ACCOUNT_EMAIL: redacted@redacted.com

해결해야 할 문제처럼 보입니다. 이는 귀하가 설명한 네트워크 오류와 일치합니다.

제 추측은 비밀번호의 특수 문자가 Discourse-doctor를 혼란스럽게 하고 있다는 것입니다.

이 주소는 SMTP 주소처럼 보이지 않습니다.
"mail.redacted.com"은 HTTP 주소일 것 같습니다.
확인해 보시는 것이 좋겠습니다.

@irwinstar, 공개 포럼에서 제 메일 서버를 노출하지 않기 위해 실제 메일 서버 주소를 삭제했습니다. 하지만 제 메일 클라이언트(정상 작동 중)에서 설정을 복사해 왔고, 실제 메일 서버의 SMTP 설정과도 비교해 보았으므로 설정이 정확하다고 보증할 수 있습니다.

도와주겠다는 말씀에 감사드립니다. 문제는 SPF/DKIM 기록에 있는 것 같아서 현재 수정을 시도하고 있습니다.

그럼에도 불구하고, discourse-doctor는 이를 올바르게 파싱해야 합니다. 제가 vim/nano로 파일을 직접 편집한 적이 없기 때문에 무슨 일이 일어나고 있는지 잘 모르겠습니다. 명확히 하자면, 해당 YAML은 discourse-setup을 사용하여 생성되었습니다.

현재 Discourse가 465 포트를 지원하지 않는다고 생각합니다. 메일 서버가 587 포트를 지원한다면, 587로 변경할 수 있습니다.
불행히도 제 메일 서버에서는 587 포트를 사용할 수 없어서, Discourse 외부에 메일 프록시를 추가했습니다.

@irwinstar, 이 정보가 맞다면 매우 중요한 내용이며, 제 이메일 설정이 작동하지 않는 이유를 설명해 줄 수 있을 것 같습니다. 이 정보에 대한 출처가 있으신가요?

확신은 없지만, 465 포트를 몇 번 시도해 보았습니다.
결국 이 “hieulq/mailproxy” Docker 이미지를 메일 프록시로 사용했습니다.
그리고 이 app.yml 설정을 Discourse에 적용했습니다.
이 사용법은 별로 좋아 보이지 않지만, 작동은 합니다.
오늘 메일 플러그인을 찾아보려고 했지만, 아무것도 찾지 못했습니다.

  DISCOURSE_SMTP_ADDRESS: x.x.x.x
  DISCOURSE_SMTP_PORT: 2525
  DISCOURSE_SMTP_AUTHENTICATION: none
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_SMTP_ENABLE_START_TLS: false

안녕하세요 @simbleau

제 경험상 SendGrid는 잘 작동합니다(포트 587).

SendGrid를 무료로 테스트해 볼 수도 있습니다!

제안해 주신 내용 감사합니다.

저는 이미 호스트게이터(HostGator)에 메일 서버를 가지고 있는데, 클라우드 메일 서버를 구매하거나 프록시를 사용(원하는 것이 더러운 해결책이라면, 지금쯤 관리자 계정을 긁어모으고 있을 것입니다)하는 것을 피하려고 합니다.

제 디스커스(Discourse) 서버 IP에 대한 SPF 레코드가 설정되어 있을 것이라고 확신합니다. 지금은 정말로 DKIM 레코드만 검증하려고 하는 것입니다.

누군가가 465 포트가 허용되지 않는다고 확인해 주신다면, 이는 환상적인 뉴스가 될 것입니다. 비(非)문제가 될 수 있는 토끼굴에 너무 깊이 빠져드는 것을 막아줄 테니까요. 465 포트가 문제가 되었고, 아래 게시글에 기록해 두었습니다.

설치 과정에서 일부 여지를 두었습니다.

포트 587을 사용하면 전체 이메일을 telnet으로 성공적으로 전송하고 인증도 정상적으로 완료됩니다. 그래서 설정을 변경했습니다.

이제 이메일이 전송될 때 다음과 같은 오류가 발생합니다:

Delivered mail d86b48cc-b0f4-4df3-8960-ab5ff96613a0@discourse.imbleau.com (251.0ms)
Job exception: hostname "mail.redacted.com" does not match the server certificate

그런데 주목할 점은, 이제 더 이상 연결 타임아웃(60초가 지난 후 발생)이 아니라, 250ms 만에 발생하는 다른 예외라는 것입니다.

이것은 system@discourse.redacted.com이라는 이메일을 사용했지만, 해당 이메일이 내부적으로 mail.redacted.com을 이메일 서버로 사용하기 때문일 가능성이 높습니다.

솔직히 어떻게 수정해야 할지 모르겠습니다. 다음을 시도해 보았습니다:

./launcher enter app
rails r "SiteSetting.notification_email = 'system@mail.redacted.com'"
exit

그리고 한 번만 사용하기 위해 재빌드도 해보았습니다. 그래도 소용이 없습니다. 동일한 오류가 나옵니다.

이메일 문제를 해결했습니다! (discourse-doctor는 여전히 올바르게 파싱하지 못함)

ruby와 이 오류가 백그라운드에서 발생하는 이유에 대해 조금 더 조사한 끝에 이 stackoverflow 질문에 도달하게 되었습니다.

원인은 바로 이것이었죠. 해결책은 SSL 협상을 변경하는 것이었고, 이를 통해 app.yml 파일에서 해당 설정을 꺼야 한다는 직감이 생겼습니다.
DISCOURSE_SMTP_ENABLE_START_TLS: false # (선택 사항, 기본값 true)

그 후, 성공했습니다!

이 설정은 TLS 암호화를 비활성화합니다. 그러나 유일한 문제는 잘못된 호스트명을 사용했다는 것이며, 즉 메일 서버가 mail.redacted.com이 아닌 다른 내용을 나타내는 인증서를 제시하고 있다는 것입니다. 많은 메일 서버는 여러 다른 호스트명으로 알려져 있으며, 인증서에 사용된 호스트명을 찾아내는 것만 필요합니다.

서버가 어떤 호스트명이라고 표시하는지 확인하고 설정을 그에 맞게 조정해 볼 수 있습니다.

echo | openssl s_client -connect mail.redacted.com:587 -starttls smtp -servername mail.redacted.com 2>/dev/null |openssl x509 -noout -subject

이 명령이 작동하지 않는 경우, TLS 암호화는 활성화한 채로 인증서 검증만 비활성화할 수 있습니다:

DISCOURSE_SMTP_ENABLE_START_TLS: true
DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: false

@RGJ님 감사합니다! 이상하게도 CN이 메일과 전혀 관련 없는 제 서브도메인 중 하나라고 표시되고 있네요. 이 부분은 확인해 볼 가치가 있습니다. 조언해 주셔서 감사합니다.

모든 사용자에게 동일한 정보가 제공될 것입니다.

app.yml 파일을 비공개로 공유해 주시면, discourse-doctor가 혼란을 겪고 있는 원인을 찾아보겠습니다.

보냈어. 한번 해봐.

아, 문제는 GNU awk가 아닌 다른 버전의 awk를 사용 중이라는 점이고, 해당 awk에서는 --field-separator 옵션이 다른 이름으로 불린다는 것입니다.

사용 중인 awk 버전은 무엇이며, 어떤 운영 체제를 사용 중입니까?

man awk를 실행하면 Version 1.3.4 2019-12-31 MAWK(1)이라고 표시됩니다.

cat /etc/os-release 명령의 출력은 다음과 같습니다:

~$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

discourse-doctor를 수정해서 --field-separator를 -F로 대체해 보시겠어요?

그렇게 하면 문제가 해결될 것 같습니다. 확인해 주시면 PR을 제출하겠습니다.

부분적으로 작동했습니다. 에러는 사라졌지만 더 이상 아무것도 반환하지 않습니다.

==================== YML 설정 ====================
DISCOURSE_HOSTNAME=
SMTP_ADDRESS=
DEVELOPER_EMAILS=
SMTP_PASSWORD=
SMTP_PORT=
SMTP_USER_NAME=
LETSENCRYPT_ACCOUNT_EMAIL=

해결했습니다.

discourse-doctor에서 213번째 줄을 다음과 같이 변경하세요:

  read_config_result=$(echo $config_line | awk  -F ":" '{print $2}')

mawk는 -F=":"를 싫어하기 때문에, -F ":"처럼 공백을 반드시 요구합니다. :roll_eyes:

PR을 열었습니다: Changed awk config command to be more cross platform - Pull Request #513 - discourse/discourse_docker - GitHub