이 글을 어디에 올릴지 정확히 모르겠지만, 다른 분들도 같은 문제를 겪고 계신지 궁금합니다. DigitalOcean과 Mailgun을 사용하여 공식 설치 가이드를 따랐습니다. 그런데 최근 Jobs::UserEmail 작업 예외가 많이 발생하고 있으며, 테스트 이메일을 보내지 못하고 있습니다.
에러 로그
Message (20584 copies reported)
Job exception: execution expired
Backtrace
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-smtp-0.5.1/lib/net/smtp.rb:663:in `initialize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-smtp-0.5.1/lib/net/smtp.rb:663:in `open'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-smtp-0.5.1/lib/net/smtp.rb:663:in `tcp_socket'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-smtp-0.5.1/lib/net/smtp.rb:672:in `block in do_start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/timeout-0.4.3/lib/timeout.rb:185:in `block in timeout'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/timeout-0.4.3/lib/timeout.rb:192:in `timeout'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-smtp-0.5.1/lib/net/smtp.rb:671:in `do_start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-smtp-0.5.1/lib/net/smtp.rb:642:in `start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.8.1/lib/mail/network/delivery_methods/smtp.rb:109:in `start_smtp_session'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.8.1/lib/mail/network/delivery_methods/smtp.rb:100:in `deliver!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.8.1/lib/mail/message.rb:269:in `deliver!'
/usr/local/lib/ruby/3.3.0/delegate.rb:87:in `method_missing'
/var/www/discourse/lib/email/sender.rb:296:in `send'
/var/www/discourse/app/jobs/regular/user_email.rb:79:in `send_user_email'
/var/www/discourse/app/jobs/regular/user_email.rb:39:in `execute'
/var/www/discourse/app/jobs/base.rb:316:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `with_connection'
/var/www/discourse/app/jobs/base.rb:303:in `block in perform'
/var/www/discourse/app/jobs/base.rb:299:in `each'
/var/www/discourse/app/jobs/base.rb:299:in `perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:220:in `execute_job'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:185:in `block (4 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:180:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/pausable.rb:132:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job/interrupt_handler.rb:9:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:26:in `track'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:134:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:173:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:184:in `block (3 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:145:in `block (6 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:118:in `local'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:144:in `block (5 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/config.rb:39:in `block in <class:Config>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:139:in `block (4 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:281:in `stats'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:134:in `block (3 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:133:in `block (2 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:85:in `global'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:132:in `block in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:40:in `prepare'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:131:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:183:in `block (2 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `block in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:86:in `process_one'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:76:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:10:in `watchdog'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:19:in `block in safe_thread'
설정 변경이 없었고, 인스턴스는 최신 상태이며, Mailgun 계정은 무료 티어 사용량 범위 내에 있기 때문에 문제의 원인을 파악하지 못했습니다. 따라서 DigitalOcean에서 포트 587을 차단했을 것 같아 지원 티켓을 생성했는데, 결국 SMTP 트래픽에 제한을 두었으며 파트너사인 SendGrid 사용을 권장한다는 짧은 답변을 받았습니다.
DigitalOcean 이메일
계정에 적용된 SMTP 제한에 대한 우려를 이해합니다. DigitalOcean은 전용 이메일 호스트가 아니며 스팸 차단에는 지속적인 노력이 필요합니다. 이에 따라 모든 계정에 제한이 부과되었습니다.
이 문제에 대한 추가적인 배경을 설명드리고자 합니다. 클라우드 환경의 IP 주소는 매우 자주 사용되고 다시 사용 가능한 풀로 반환되므로 동적이고 신뢰할 수 없는 것으로 간주됩니다. 예를 들어, 현재 사용 중인 IP 주소는 책임감 있는 메일 사용자로, 모든 메일 모범 사례를 준수하며 스팸이나 부당한 메일을 보내지 않습니다. 나중에 해당 Droplet이 더 이상 필요하지 않아 삭제하면, 그 IP 주소는 다른 DigitalOcean 사용자에게 할당될 수 있습니다. 그 사용자는 보안 팀이 문제 계정에 조치를 취하기 전에 대량의 스팸을 보내는 기회를 노릴 수 있습니다.
Gmail, Microsoft 등 메일 제공업체는 IP에서 온 메일이 정당한 것인지 아닌지를 판단하기 위해 해당 IP가 나쁜 평판을 얻어야 합니다. 그 시점에는 이미 피해가 발생했을 것입니다. IP 주소가 동적으로 할당되고 본질적으로 위험한 인터넷 서비스 제공업체와 클라우드 호스팅 환경과 같은 플랫폼에서 오는 모든 메일을 차단하는 것이 더 안전합니다.
이 조치는 스팸 공격자가 이용할 수 있는 통로를 줄이는 데 도움이 되지만, 합법적인 사용자에도 영향을 미칩니다. 우리의 악용 방지 운영 팀은 SBL(스팸 블랙리스트)과 협력하여 해당 IP가 목록에서 제거되도록 노력하고 있습니다. 이에 따라 DigitalOcean 플랫폼 전반에서 SMTP 트래픽을 제한하고 있습니다. 이는 계정에 적용된 SMTP 제한을 해제할 수 없음을 의미합니다.
워크플로우에 이메일 관련 필요 사항이 있을 수 있음을 이해합니다. 이 제한에 대한 해결책으로, 우리는 SendGrid와 파트너십을 맺어 IP 평판과 블랙리스트에 대한 걱정 없이 더 나은 솔루션을 모든 고객에게 제공합니다. 이에 대한 자세한 내용은 이곳의 우리 기사에서 확인하실 수 있습니다. SendGrid를 통해 하루 100통의 무료 이메일을 보낼 수 있으며, 무료 티어를 초과하는 요구 사항이 있다면 SendGrid 지원에 문의하여 요구 사항을 충족할 수 있는 더 나은 플랜을 선택하실 수 있습니다.
추가 질문이 있으시면 항상 기꺼이 도와드리겠습니다. 주저하지 마시고 문의해 주시기 바랍니다.
----
이것은 필요한 모든 정보를 수집하여 서비스를 신속하게 처리하기 위한 자동 응답입니다. 추가 도움을 받으려면 이 이메일에 회신해야 합니다.
DigitalOcean Support Team
이런 우발적인 문제를 겪은 다른 분이 계신가요? 정당한 이유 없이 SendGrid로 전환하도록 강요당하고 싶지는 않습니다.
수정…
최근 이 주제 Looks like DO is disabling Smtp in their Discourse hosting plans 를 발견했는데, DigitalOcean을 사용하는 모든 사람이 문제를 겪을 수 있는 것으로 보입니다.
