이메일 전송이 중단됨 - 파일 끝 도달

모두 안녕하세요. 이 오류를 언급한 다른 게시물과 유사한 내용이라면 죄송합니다.

최근 4일 동안 모든 이메일 전송이 중단되었고, 테스트 이메일도 실패합니다.

유사한 기존 주제들을 살펴봤지만, 제 경우 (제가 아는 한) 변경된 사항은 없으며, 수개월간 문제없이 작동하던 이메일이 갑자기 멈춘 상태입니다.

Digital Ocean 호스팅을 사용 중이며, Droplet의 IP 주소에서 이메일을 중계하도록 구성된 G Suite SMTP 릴레이를 사용하고 있습니다.

Sidekiq에 기록된 정확한 오류 메시지는 discourse-doctor에서 확인하는 것보다 더 자세한 내용을 담고 있습니다.

Jobs::HandledExceptionWrapper: Wrapped EOFError: end of file reached

discource-doctor는 단순히 UNEXPECTED ERROR: end of file reached라고만 표시합니다.

또한 다음 명령을 통해 서버에 연결할 수 있음을 확인했습니다:

telnet smtp-relay.gmail.com 587

수개월 전에도 이메일 전송이 잠시 중단된 적이 한 번 있었던 것 같지만, 당시 오류 메시지는 기억나지 않습니다(그때는 Sidekiq에서 재시도만 하면 문제가 해결되었습니다).

유사한 경험을 하신 분이나, 여전히 정상적으로 작동하는 유사한 구성을 사용 중인 분이 계신가요? 미리 감사드립니다!

아직 유용한 조언은 없지만, 정확히 같은 환경(DigitalOcean droplet, smtp-relay.gmail.com을 통해 이메일 전송)에서 동일한 EOFError 문제를 겪고 있습니다.

Sidekiq는 다음을 보고합니다:

Jobs::HandledExceptionWrapper: Wrapped EOFError: end of file reached

/logs를 확인하면 실패 시점에 트레이스백이 표시되지만, 즉시 유용해 보이는 내용은 없습니다.

정보:

Job exception: end of file reached

백트레이스:

/usr/local/lib/ruby/2.7.0/net/protocol.rb:225:in `rbuf_fill'
/usr/local/lib/ruby/2.7.0/net/protocol.rb:191:in `readuntil'
/usr/local/lib/ruby/2.7.0/net/protocol.rb:201:in `readline'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:944:in `recv_response'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:929:in `block in getok'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:954:in `critical'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:927:in `getok'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:826:in `helo'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:600:in `do_helo'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:554:in `do_start'
/usr/local/lib/ruby/2.7.0/net/smtp.rb:518:in `start'
mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb:109:in `start_smtp_session'
mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb:100:in `deliver!'
mail-2.7.1/lib/mail/message.rb:2159:in `do_delivery'
mail-2.7.1/lib/mail/message.rb:260:in `block in deliver'
actionmailer-6.0.3.3/lib/action_mailer/base.rb:589:in `block in deliver_mail'
activesupport-6.0.3.3/lib/active_support/notifications.rb:180:in `block in instrument'
activesupport-6.0.3.3/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activesupport-6.0.3.3/lib/active_support/notifications.rb:180:in `instrument'
actionmailer-6.0.3.3/lib/action_mailer/base.rb:587:in `deliver_mail'
mail-2.7.1/lib/mail/message.rb:260:in `deliver'
actionmailer-6.0.3.3/lib/action_mailer/message_delivery.rb:115:in `block in deliver_now'
actionmailer-6.0.3.3/lib/action_mailer/rescuable.rb:17:in `handle_exceptions'
actionmailer-6.0.3.3/lib/action_mailer/message_delivery.rb:114:in `deliver_now'
/var/www/discourse/lib/email/sender.rb:234:in `send'
/var/www/discourse/app/jobs/regular/user_email.rb:70:in `send_user_email'
/var/www/discourse/app/jobs/regular/user_email.rb:25:in `execute'
/var/www/discourse/app/jobs/base.rb:232:in `block (2 levels) in perform'
rails_multisite-2.5.0/lib/rails_multisite/connection_management.rb:76:in `with_connection'
/var/www/discourse/app/jobs/base.rb:221:in `block in perform'
/var/www/discourse/app/jobs/base.rb:217:in `each'
/var/www/discourse/app/jobs/base.rb:217:in `perform'
sidekiq-6.1.2/lib/sidekiq/processor.rb:196:in `execute_job'
sidekiq-6.1.2/lib/sidekiq/processor.rb:164:in `block (2 levels) in process'
sidekiq-6.1.2/lib/sidekiq/middleware/chain.rb:138:in `block in invoke'
/var/www/discourse/lib/sidekiq/pausable.rb:138:in `call'
sidekiq-6.1.2/lib/sidekiq/middleware/chain.rb:140:in `block in invoke'
sidekiq-6.1.2/lib/sidekiq/middleware/chain.rb:143:in `invoke'
sidekiq-6.1.2/lib/sidekiq/processor.rb:163:in `block in process'
sidekiq-6.1.2/lib/sidekiq/processor.rb:136:in `block (6 levels) in dispatch'
sidekiq-6.1.2/lib/sidekiq/job_retry.rb:111:in `local'
sidekiq-6.1.2/lib/sidekiq/processor.rb:135:in `block (5 levels) in dispatch'
sidekiq-6.1.2/lib/sidekiq.rb:38:in `block in <module:Sidekiq>'
sidekiq-6.1.2/lib/sidekiq/processor.rb:131:in `block (4 levels) in dispatch'
sidekiq-6.1.2/lib/sidekiq/processor.rb:257:in `stats'
sidekiq-6.1.2/lib/sidekiq/processor.rb:126:in `block (3 levels) in dispatch'
sidekiq-6.1.2/lib/sidekiq/job_logger.rb:13:in `call'
sidekiq-6.1.2/lib/sidekiq/processor.rb:125:in `block (2 levels) in dispatch'
sidekiq-6.1.2/lib/sidekiq/job_retry.rb:78:in `global'
sidekiq-6.1.2/lib/sidekiq/processor.rb:124:in `block in dispatch'
sidekiq-6.1.2/lib/sidekiq/logger.rb:10:in `with'
sidekiq-6.1.2/lib/sidekiq/job_logger.rb:33:in `prepare'
sidekiq-6.1.2/lib/sidekiq/processor.rb:123:in `dispatch'
sidekiq-6.1.2/lib/sidekiq/processor.rb:162:in `process'
sidekiq-6.1.2/lib/sidekiq/processor.rb:78:in `process_one'
sidekiq-6.1.2/lib/sidekiq/processor.rb:68:in `run'
sidekiq-6.1.2/lib/sidekiq/util.rb:15:in `watchdog'
sidekiq-6.1.2/lib/sidekiq/util.rb:24:in `block in safe_thread'

환경:

hostname	conversation-app
process_id	736
application_version	e6bbe9b5df4d86fe711aa8b1d886489d30875633
current_db	default
current_hostname	conversation.sevarg.net
job	Jobs::UserEmail
problem_db	default
time	12:42 pm
opts	
type	digest
user_id	30
current_site_id	default

discourse-doctor도 동일한 일반적인 출력을 보입니다:

==================== MAIL TEST ====================
For a robust test, get an address from http://www.mail-tester.com/
Or just send a test message to yourself.
Email address for mail test? ('n' to skip) [[my email]]: 
Sending mail to [my email]. . . 
Testing sending to [my email] using smtp-relay.gmail.com:587.
======================================== ERROR ========================================
                                    UNEXPECTED ERROR

end of file reached

====================================== SOLUTION =======================================
This is not a common error. No recommended solution exists!

Please report the exact error message above to https://meta.discourse.org/
(And a solution, if you find one!)
=======================================================================================

또한 포트 587의 릴레이로 telnet 접속이 가능하며(수동으로 테스트 메시지를 전송해봄 - 십 년 만에 하는 일이라…), 최근 이메일 관련에 영향을 미칠 수 있는 설정을 변경한 적도 없습니다.

새로운 사용자 등록 등이 완전히 막혀 있어 문제가 조금 큽니다. 블로그 댓글에도 이 시스템을 사용 중이거든요. Google 로그에서도 큰 도움이 되는 내용을 찾지 못했고, 더 이상 트러블슈팅할 아이디어가 없습니다. 모든 것이 올바르게 설정된 것 같지만, 그냥 더 이상 작동하지 않습니다.

음, 제 설정이 그렇게 흔치 않은 것이 아니고, 이런 문제를 겪는 것이 저 혼자만은 아니라는 점이 분명히 위안이 됩니다. 궁금한 점이 있는데, 당신도 약 5일 전쯤에 문제가 시작되었나요? 어쩌면 우리 파이프라인에서 공통적으로 사용되는 어떤 부분에 업데이트가 있었을지도 모르겠네요.

상세 정보와 백트레이스를 공유해 주셔서 감사합니다. 제 경우에도 당신의 것과 매우 유사했고, 에러 메시지도 동일했습니다.

telnet으로 수동으로 이메일을 보내는 시도는 하지 않았지만, 당신에게도 작동했던 것처럼 저에게도 작동할 것이라 생각합니다.

저도 같은 상황이고, 당분간 새 사용자를 수동으로 활성화하고 있습니다(다행히 하루에 몇 명뿐입니다). g-suite, digital ocean, discourse 설정에서 아무것도 변경하지 않았기 때문에, 실제로 문제를 일으키는 원인을 좁혀내기 전까지는 아무것도 변경하기가 꺼려집니다. :confused:

Sidekiq에서 실제 실패 수가 급증한 시점은 1월 14일이었으니, 5일 전입니다. 그전에는 잘못된 이메일 주소 등으로 인한 무작위 실패가 있었지만, 급격히 증가하는 추세는 아니었습니다.

Google Admin Console에서 릴레이 설정을 재구성하고, 설정값을 조정해 보았지만(완전히 열려 있어야 할 것들 포함) 변화가 없었습니다. 메일 전송용 포트도 몇 가지 바꿔 보았지만 역시 변화가 없었습니다.

또한, 5일 전에 제가 의도적으로 변경한 내용은 기억나지 않습니다. :confused:

DigitalOcean → smtp-relay.gmail.com 관련 문제 보고

DigitalOcean이 아닌 VM에서 테스트를 쉽게 해볼 수 있는 분이 있을까요? GCE 같은 서비스에서요?

GCE에서 제 인증 정보를 사용하여 Discourse를 설치했는데, 릴레이를 인증에만 의존하도록 설정했음에도 동일한 오류가 발생했습니다.

======================================== ERROR ========================================
                                    UNEXPECTED ERROR

end of file reached

====================================== SOLUTION =======================================
This is not a common error. No recommended solution exists!

Please report the exact error message above to https://meta.discourse.org/
(And a solution, if you find one!)
=======================================================================================

릴레이에 IP 기반 인증을 설정해도 동일한 결과가 나왔습니다. 따라서 DigitalOcean에 특정한 문제라고 생각하지 않습니다…

불행히도 "Ruby/Rails 이메일 문제 해결"은 제 현재 기술 수준을 벗어납니다… 어떤 조언을 주실 수 있을까요?

이것이 Gmail SMTP 문제일 가능성이 있을까요?

그런 것 같습니다. 문제를 어떻게 해결해야 할지 모르겠고, 지금까지 시도한 수정 작업은 아무런 성과가 없었습니다. 아마도 무언가를 변경한 것 같은데, Discourse가 이를 처리하지 못하고 있고, 당연히 지원도 없습니다.

이 포럼에서는 문제를 추적하고 해결하는 데 도움을 주면서 좋은 결과를 얻은 적이 많습니다. 이번에는 왜 이렇게 조용한지 모르겠네요.

gmail/gsuite의 SMTP 문제일 가능성이 있지만, @Syonyk는 자신의 droplet에서 telnet을 통해 수동으로 이메일을 전송할 수 있었다고 언급했습니다.

g-suite가 사이트에서 전송된 트래픽과 수동으로 전송된 메시지를 어떻게 해석하는지에 대해 제가 충분히 경험이 많지 않아 정확한 판단은 어렵지만, 이 상황은 smtp-relay.gmail로 이메일을 전송하는 서비스 측에 문제가 있는 것처럼 보이게 하고, 릴레이 자체의 문제는 아닌 것으로 보입니다.

참고로, 저는 관리용 gsuite 설정에서 droplet의 IP 주소를 명시적으로 허용해 두었으며, 수개월간 어떤 서비스의 설정도 변경하지 않았습니다(현재도 변경하지 않은 상태입니다).

비슷한 상황이 일어난 적은 한 번 있었는데, 그 때는 하루(아마도 이틀 정도였을 것입니다. 당시에는 트래픽이 많지 않은 페이지였기 때문에 더 길게 지속되었더라도 인지하지 못했을 가능성이 큽니다) 정도만 지속되었고, 비교적 빠르게 스스로 해결되었습니다.

Discourse의 SMTP 대화에 대한 적절한 추적을 확보하지 못한 상태에서는 더 이상 문제를 해결할 방법을 알 수 없으며, 해당 추적을 어떻게 가져올지도 모릅니다.

디스코스에서 매월 보내는 이메일 수를 확인할 수 있는 방법이 있을까요? 다른 SMTP 릴레이로 전환해야 한다면 예산 규모를 파악해야 하는데, 이 문제가 정말 답답합니다.

인스턴스의 /admin/email/sent 경로에서 발송된 내역을 확인하고, 이를 통해 사용량을 추정할 수 있습니다.

음…

서버에 tcpdump를 설치하고 discourse-doctor를 실행해 보았습니다. 그리고 출력에서 이 내용을 발견했네요…

...
0x0030:  d10f f8e4 4548 4c4f 206c 6f63 616c 686f  ....EHLO.localho
	0x0040:  7374 0d0a                                st..
...
	0x0030:  de62 f0c3 3432 3120 342e 372e 3020 5472  .b..421.4.7.0.Tr
	0x0040:  7920 6167 6169 6e20 6c61 7465 722c 2063  y.again.later,.c
	0x0050:  6c6f 7369 6e67 2063 6f6e 6e65 6374 696f  losing.connectio
	0x0060:  6e2e 2028 4548 4c4f 2920 6a31 3673 6d34  n..(EHLO).j16sm4
	0x0070:  3831 3932 3976 736d 2e31 202d 2067 736d  81929vsm.1.-.gsm
	0x0080:  7470 0d0a                                tp..

그리고 중요한 점은, telnet을 사용하여 이 실패를 재현할 수 있다는 것입니다.

root@conversation:~# telnet smtp-relay.gmail.com 587
Trying 74.125.137.28...
Connected to smtp-relay.gmail.com.
Escape character is '^]'.
220 smtp-relay.gmail.com ESMTP ls8sm507258pjb.6 - gsmtp
ehlo localhost.localdomain
421 4.7.0 Try again later, closing connection. (EHLO) ls8sm507258pjb.6 - gsmtp
Connection closed by foreign host.

실제 도메인을 보내면 예상된 응답을 받습니다.

root@conversation:~# telnet smtp-relay.gmail.com 587
Trying 74.125.137.28...
Connected to smtp-relay.gmail.com.
Escape character is '^]'.
220 smtp-relay.gmail.com ESMTP p10sm668563uaw.3 - gsmtp
ehlo conversation.sevarg.net
250-smtp-relay.gmail.com at your service, [64.227.96.27]
250-SIZE 157286400
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8

따라서, 이제 질문은 Discourse가 ehlo에 올바른 도메인 문자열을 보내도록 어떻게 해야 하는가입니다.

이것이 유일한 문제인지 여부는 모르겠지만, 추적해 볼 가치가 있어 보입니다.

정말 이상하네요. 이게 갑자기 어디서 들어온 걸까요? 업데이트는 전혀 안 했는데요.

문제가 갑자기 생긴 것이 아니라, 처음부터 이런 상태였습니다. Google 쪽에서 무언가를 변경한 것 같습니다.

discourse-doctor는 이미지 내부에 있는 경우 /var/www/discourse/lib/tasks/emails.rake에 있는 테스트를 호출합니다.

저는 다음을 변경했습니다:

Net::SMTP.start(smtp[:address], smtp[:port], 'localhost', smtp[:user_name], smtp[:password], smtp[:authentication])

을

Net::SMTP.start(smtp[:address], smtp[:port], 'conversation.sevarg.net', smtp[:user_name], smtp[:password], smtp[:authentication])

이제 다른 오류가 발생합니다.

======================================== ERROR ========================================
                                    UNEXPECTED ERROR

503 5.5.1 bad sequence of commands e190sm562849qkd.9 - gsmtp


====================================== SOLUTION =======================================
This is not a common error. No recommended solution exists!

Please report the exact error message above to https://meta.discourse.org/
(And a solution, if you find one!)
=======================================================================================

그러나 중요한 점은, tcpdump가 다소 합리적인(ish) 흐름을 보여준다는 것입니다.

22:33:48.393862 IP 64.227.96.27.54610 > 74.125.137.28.587: Flags [P.], seq 1:31, ack 59, win 502, options [nop,nop,TS val 3732187266 ecr 3508646052], length 30
	0x0000:  4500 0052 d4d6 4000 3f06 f237 40e3 601b  E..R..@.?..7@.`.
	0x0010:  4a7d 891c d552 024b 01b4 04a4 94ce dcc7  J}...R.K........
	0x0020:  8018 01f6 74dc 0000 0101 080a de74 a882  ....t........t..
	0x0030:  d121 b0a4 4548 4c4f 2063 6f6e 7665 7273  .!..EHLO.convers
	0x0040:  6174 696f 6e2e 7365 7661 7267 2e6e 6574  ation.sevarg.net
	0x0050:  0d0a                                     ..
22:33:48.408832 IP 74.125.137.28.587 > 64.227.96.27.54610: Flags [.], ack 31, win 256, options [nop,nop,TS val 3508646067 ecr 3732187266], length 0
	0x0000:  4500 0034 5e5d 0000 2b06 bccf 4a7d 891c  E..4^]..+...J}..
	0x0010:  40e3 601b 024b d552 94ce dcc7 01b4 04c2  @.`..K.R........
	0x0020:  8010 0100 a8ae 0000 0101 080a d121 b0b3  .............!..
	0x0030:  de74 a882                                .t..
22:33:48.469560 IP 74.125.137.28.587 > 64.227.96.27.54610: Flags [P.], seq 59:234, ack 31, win 256, options [nop,nop,TS val 3508646128 ecr 3732187266], length 175
	0x0000:  4500 00e3 5e8a 0000 2b06 bbf3 4a7d 891c  E...^...+...J}..
	0x0010:  40e3 601b 024b d552 94ce dcc7 01b4 04c2  @.`..K.R........
	0x0020:  8018 0100 929f 0000 0101 080a d121 b0f0  .............!..
	0x0030:  de74 a882 3235 302d 736d 7470 2d72 656c  .t..250-smtp-rel
	0x0040:  6179 2e67 6d61 696c 2e63 6f6d 2061 7420  ay.gmail.com.at.
	0x0050:  796f 7572 2073 6572 7669 6365 2c20 5b36  your.service,.[6
	0x0060:  342e 3232 372e 3936 2e32 375d 0d0a 3235  4.227.96.27]..25
	0x0070:  302d 5349 5a45 2031 3537 3238 3634 3030  0-SIZE.157286400
	0x0080:  0d0a 3235 302d 3842 49544d49 4d45 0d0a  ..250-8BITMIME..
	0x0090:  3235 302d 5354 4152 5454 4c53 0d0a 3235  250-STARTTLS..25
	0x00a0:  302d 454e 4841 4e43 4544 5354 4154 5553  0-ENHANCEDSTATUS
	0x00b0:  434f 4445 530d 0a32 3530 2d50 4950 454c  CODES..250-PIPEL
	0x00c0:  494e 494e 470d 0a32 3530 2d43 4855 4e4b  INING..250-CHUNK
	0x00d0:  494e 470d 0a32 3530 2053 4d54 5055 5446  ING..250.SMTPUTF
	0x00e0:  380d 0a                                  8..

즉, 최소한 “EHLO localhost” 또는 "EHLO localhost.localdomain"을 보내는 것이 문제의 일부입니다.

그렇다면 실제 개발자에게 P0 문제를 보고하는 방법은 무엇일까요?

나는 포럼에서 이 사람들을 분명히 본 적이 있습니다. 제가 파악한 바로는, 그들은 포럼을 꽤 꼼꼼하게 모니터링하고 있습니다. github라고 말하고 싶지만, 해당 저장소에서는 이슈가 비활성화된 것 같습니다.

알겠습니다.

This is a test email from

https://conversation.sevarg.net

Email deliverability is complicated. Here are a few important things you should check first:

방금 수정 방법을 시연했지만, 이를 업스트림에 반영하는 방법은 모릅니다.

cd /var/discourse
./launcher enter app
vim ./vendor/bundle/ruby/2.7.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb

다음 섹션을 찾아야 합니다:

    DEFAULTS = {
      :address              => 'localhost',
      :port                 => 25,
      :domain               => 'localhost.localdomain',
      :user_name            => nil,
      :password             => nil,
      :authentication       => nil,
      :enable_starttls      => nil,
      :enable_starttls_auto => true,
      :openssl_verify_mode  => nil,
      :ssl                  => nil,
      :tls                  => nil,
      :open_timeout         => nil,
      :read_timeout         => nil
    }

도메인 관련 줄을 변경합니다.

    DEFAULTS = {
      :address              => 'conversation.sevarg.net',
      :port                 => 25,
      :domain               => 'conversation.sevarg.net',
      :user_name            => nil,
      :password             => nil,
      :authentication       => nil,
      :enable_starttls      => nil,
      :enable_starttls_auto => true,
      :openssl_verify_mode  => nil,
      :ssl                  => nil,
      :tls                  => nil,
      :open_timeout         => nil,
      :read_timeout         => nil
    }

어느 쪽이 중요한지 모르지만, 둘 다 변경하니 문제가 해결되었습니다. 당연히 자신의 도메인을 사용해야 합니다…

앱 환경을 종료합니다.

./launcher restart app

이제 이메일을 보낼 수 있어야 합니다.

이 수정 사항은 업그레이드 후 유지되지 않을 것으로 예상됩니다.

하지만 이제 예상대로 이메일을 주고받을 수 있습니다.

개발자분들? 수정 부탁드립니다?

제가 등록한 버그에 따라 다음을 시도해 주세요:

아래 내용을 추가하세요.

DISCOURSE_SMTP_DOMAIN: [your install domain]

이를 app.yml 파일(대부분 /var/discourse/containers/app.yml)에 추가한 후, 앱을 다시 빌드하고(cd /var/discourse; ./launcher rebuild app) 이메일 전송을 시도해 보세요.

정확히 이해하기 위해 여쭤봅니다. DISCOURSE_SMTP_DOMAIN은 제 Discourse 서버의 도메인인가요, 아니면 이메일의 도메인인가요?

예를 들어, 제 서버는 서브도메인 community.acescentral.com에 위치해 있고, 이메일은 admin@acescentral.com에서 발송됩니다. 그렇다면 DISCOURSE_SMTP_DOMAIN은 상위 도메인인 acescentral.com인가요, 아니면 community 서브도메인인가요?

이 문제를 끈질기게 추적해 주셔서 정말 감사합니다.