メールの改訂:テストrakeタスクの出力

メール:タスクと関連コードを確認し、各障害コードパスをテストしてエラーテキストを修正しました。

また、DISCOURSE_SMTP_ENABLE_STARTTLS=false の設定の影響は(ほとんど)ないことを発見しました。これを設定しても STARTTLS は無効にならず、実際には接続時に TLS と共存できます(DISCOURSE_SMTP_FORCE_TLS=true)。

そのため、以下の対応を行いました。

これをマージする前に、ダッシュボードで DISCOURSE_SMTP_ENABLE_STARTTLS=false が設定されている場合に管理者に警告を表示するのが適切だと思います。これを設定したが、実際には必要なく STARTTLS に依存しているセルフホスティングユーザーが少なくとも一人いると想像しています。

「いいね!」 4

それは良い仕事のように聞こえます!私が(気づいたと思う)一つのことは、レイクタスクが実際には実際の送信と同じコードを使用していないことです(たとえば、/admin/emailテストページから)。UXでは機能したがレイクタスクでは機能しなかった(またはその逆だった?)ケースがあったと確信しています。

それがあなたの心に新鮮なうちに、実際に送信するときにDiscourseと同じコードを使用していることを確認できれば、それは素晴らしいことです。

「いいね!」 2

それについても取り組んでおり、キューに入れられたメールジョブが失敗した際のログの改善にも取り組んでいます。:+1:

「いいね!」 4

フォーラムで何か私が行うべきことはありますか?

「いいね!」 4

いいえ、このアラートはホスティングには表示されないはずです。修正します。いつもご報告ありがとうございます。

「いいね!」 5

@supermathie この変数が設定されているすべてのサイトのすべての管理者にPMを送信する価値はありますか?現在の問題チェックシステムがそれを行いますが、ほとんどの場合、これはnilの効果しかないため、ここで正当化されるかどうかはわかりません。理想的には、管理ユーザーにpingを送信せずにダッシュボードにのみ表示したいのですが、現在の問題チェックの構造がこのユースケースをサポートしているかどうかわかりません。

多くの管理者がメール設定について混乱していることを考えると、実際に STARTTLS に依存しているのに、この変数が設定されている可能性が非常に高いと思います。

おそらく、誰もこれを設定すべきではありません。

誤検知の警告がある方が、誰かのメール設定がサイレントに壊れるよりも良いです。

代替案は、チェックを削除して、変数が何も行わないように無力化することです。

「いいね!」 1

発信SMTPサーバーがlocalhost(つまりDiscourseドメイン名と一致する)の場合、TLSは同じマシンであるDockerコンテナとホスト間で不要なため、警告が表示されないようになると良いでしょう。

「いいね!」 1

この場合、環境から変数を削除できます。

STARTTLSが提供されている場合にのみ使用されます。

「いいね!」 1

現在のバージョンでは、コメントアウトされた行(デフォルトはtrue)が force_tls と一緒にメール送信を妨げるケースがありました。そのため、コメントアウトを解除し、false に設定しました。これでメール送信は機能するようになりましたが、バックエンドに以下のメッセージが表示されます…

これは、メールプロバイダーがどのポートで動作しているかに多少依存します… 両方が機能しない場合があり、間違いなく影響があります。

私もこれを認識しました。11月28日にDiscourseを更新した後、エラーメッセージJob exception: :enable_starttls and :tls are mutually exclusive. Set :tls if you're on an SMTPS connection. Set :enable_starttls if you're on an SMTP connection and using STARTTLS for secure TLS upgrade.を伴うメール配信エラーが発生し始めました。

バックトレース
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/lib/mail/network/delivery_methods/smtp.rb:159:in `build_smtp_session'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/lib/mail/network/delivery_methods/smtp.rb:154:in `start_smtp_session'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/lib/mail/network/delivery_methods/smtp.rb:108:in `deliver!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/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:80:in `send_user_email'
/var/www/discourse/app/jobs/regular/user_email.rb:40:in `execute'
/var/www/discourse/app/jobs/base.rb:318:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-7.0.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-7.0.0/lib/rails_multisite/connection_management.rb:17:in `with_connection'
/var/www/discourse/app/jobs/base.rb:305:in `block in perform'
/var/www/discourse/app/jobs/base.rb:301:in `each'
/var/www/discourse/app/jobs/base.rb:301: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/suppress_user_email_errors.rb:6: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/lib/sidekiq/discourse_event.rb:6: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/lib/sidekiq/pausable.rb:131: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'

ヨハン・クリストフと同様に、私も以前はDISCOURSE_SMTP_ENABLE_START_TLSをコメントアウトし、暗黙的なTLSのためにDISCOURSE_SMTP_FORCE_TLStrueに設定していましたが、これは問題なく機能していました。しかし、現在は、メール配信を機能させるためにはDISCOURSE_SMTP_ENABLE_START_TLSを明示的にfalseに設定する必要があり、もちろんこれにより管理ダッシュボードで前述のメッセージが表示されます。

「いいね!」 1

メール送信を妨げているのは force_tls です。これは接続時に TLS を強制するため、ポート 465 にのみ適している可能性が高いです。

ユニコーンですね!

使用している SMTP パラメータは何ですか(ユーザー名とパスワードは除く)?

ENABLE_START_TLS=falseFORCE_TLS=trueOPEN_TIMEOUT=10のポート465を使用しています。最後のものは、約3年前にシステムアップデートを行った後に見始めた奇妙なタイムアウトエラーによるものですが、それが上記の問題に関連しているなら私は帽子を食べるでしょう。

その間にコミット履歴を確認したところ、問題が私の環境で発生したアップデートのわずか3日前に、mail gemがバージョン2.9.0に更新されていることに気づきました(#36254)。そのリリースノートには、「SMTP: refactor and accept starttls :always and :auto by @eval in #1536」という記述があります。Rubyについてはあまり詳しくありませんが、参照されているプルリクエストのこの変更は私には少し怪しく見えます。

DISCOURSE_SMTP_ENABLE_START_TLSはデフォルトでtrue(つまりコメントアウトされている場合はtrue)であると文書化されていることを考えると、これが問題の根本原因である可能性はありますか?

書いたように、force_TLS を設定しました。

DISCOURSE_SMTP_FORCE_TLS = true

そして ENABLE_START_TLS を明示的に false に設定すると、メールサーバーが 465 で動作している限り、メール送信は機能します。

567 で動作するメールサーバーの場合は、その逆にする必要があります。

それ以来、バックエンドのダッシュボードに警告が表示されますが、メール送信は問題なく動作しています。

DISCOURSE_SMTP_ENABLE_START_TLS を false に設定するには、デフォルトで true になっているため、コメントアウトする必要があります。まさにそれが、最新のビルド (2025.12.0-latest) で私に問題を引き起こした原因でした。

うわー、これはひどい変更だ。

enable_starttlsstarttls の使用を要求しますが、enable_starttls_auto は日和見的です。提供されていれば TLS をネゴシエートするだけです。

そして、メールサーバーに初期 TLS 経由で接続していた場合、starttls は提供されません。

○ → openssl s_client -connect localhost:5587 -starttls smtp
250 CHUNKING
EHLO localhost
250-testmailrelay
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 CHUNKING

なぜ彼らはそんなことをしたのでしょうか?:facepalm:
ここでの難しさは、そもそもこの設定を提供するべきではなかったということです。次のようなものであったはずです。

DISCOURSE_SMTP_TLS_MODE = starttls_auto # [ none | starttls | starttls_auto (デフォルト) | tls ]

設定を増やすのではなく、減らすという観点から、このアプローチが最善だと思います。

「いいね!」 1

これはマージされました。TLSが有効になっている場合、Discourseが自動的に処理するため、STARTTLSを明示的に無効にする必要はなくなりました。