Discourse Bounce Guard プラグイン

リポジトリ: GitHub - overgrow/discourse-bounce-guard · GitHub
ライセンス: MIT

&tldr; 概要: エラーログのクリーンアップ(無効なアドレスへの毎時リトライが停止します)。Discourse は届かないメールの送信を停止します。また、ユーザーの満足度も向上します。無効なアドレスが適時に有効なものと交換されるため、アカウントへの再ログインが可能になります。

送信メールが独自のリレー(Postfix、Exim、多くのセルフホスト環境など)を経由している場合、/logs に以下のようなペアが溜まっているのを見たことがあるかもしれません:

SMTP Error Net::SMTPServerBusy with message: 450 4.1.2 <someone@gone-domain.com>: Recipient address rejected: Domain not found
Job exception: Net::SMTPServerBusy

そのドメインは消滅しており、戻ってきません。しかし、リレーは理論上DNSルックアップが一時的に失敗し得るため、一時的なエラーコード(450)で応答します。Discourse は一時的なエラーをすべて「1時間後に再試行する」と解釈し、Sidekiq は数週間も再試行を続けます。コアのバウンス検知は決してトリガーされません。それはバウンスメッセージが返ってきた場合のみ反応するからです。バウンスメッセージはメール(VERP)またはメールプロバイダーからのWebhookとして返ってきますが、ここではメッセージがその場で拒否されるため、バウンスメッセージは存在しません。バウンススコアはゼロのまま、リトライは続き、ユーザーは何も受け取れないアドレス(パスワードリセットを含む)を保持したままになります。

これについて、組み込みの解決策なしで以前から何度か話題になっています。例えば Handling emails to non-existent domainDeactivate user with hard bounceHow to deactivate accounts of users who are not receiving emails などです。私たちのフォーラムでも同じ問題に苦しんでいたため、プラグインを作成しました。

機能

Bounce Guard は送信パス自体にフックし、すべてのSMTP拒否を分類します:

  • 無効な受信者拡張ステータス(5.1.15.1.25.2.1 など)を伴う 5xx レスポンスは、ハードフェイルとしてカウントされます。
  • 設定可能なフレーズリスト(“domain not found”、“user unknown” など)に一致する応答は、コードに関係なくハードフェイルとしてカウントされます。これにより、450 で永続的な条件をソフトフェイルとして扱うリレーも捕捉できます。
  • グレーリスティング、満杯のメールボックス、レート制限には手を加えません。コアのリトライ動作は変更されません。

記録されたハードフェイルは以下の階層を登っていきます:

  1. 各フェイルは、ハードバウンスとしてコアのバウンススコアに反映されます(デフォルトで有効)。2回で、コア独自の閾値がトリガーされ、Discourse はそのユーザーへのメール送信を停止します。これにより、ログのノイズはここで終了します。さらに何も有効にしなくても。
  2. 設定可能な期間内に設定可能な数のフェイルが発生した後(デフォルト:少なくとも48時間間隔で2回のフェイル。これにより、短時間の障害で誰かが除外されることはありません)、プラグインが動作します。デフォルトのアクションは log_only です。ユーザーが非アクティブ化されていたはずであることを記録するスタッフアクションログエントリを作成します。信頼できると思ったら deactivate に切り替えてください。
  3. 非アクティブ化により、ユーザーは次のログイン時に標準的なアクティベーションフローを経由し、そこでアドレスの変更が組み込まれています。有効なメールを検証し、アカウントを維持したまま続行できます。ポイントは回復可能性です:唯一の回復手段が死んだメールボックスであるアクティブなアカウントは、ロックアウト待ちの状態です。

サイトがバウンスを受信している場合(VERPまたはWebhook)、コアのバウンススコアがコアが送信を停止するスコアより高い、あなたが選んだレベルを超えたときにプラグインが動作するよう設定することもできます。どこでもいくつかの安全ルールが適用されます。スタッフとボットには決して手を加えません。1時間ごとにリトライする詰まったメール1通は、クールダウンウィンドウのおかげで単一のフェイルとしてカウントされます。フェイルは、サーバーが拒否したアドレスがそのユーザーの現在のアドレスである場合にのみ、ユーザーに対してカウントされます。また、記録されたすべてのフェイルは90日間保持されるため、何が起きたかを確認できます(READMEにData Explorerクエリを掲載)。

インストール

標準的なプラグインインストール

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/overgrow/discourse-bounce-guard.git

bounce_guard_enabled を有効にし、bounce_guard_action は1〜2週間 log_only のままにして、フラグが立てられた内容を確認してから、非アクティブ化について判断してください。設定の参照は README にあります。

サーバーサイドのみで、テーマやJSコンポーネントはありません。現在のコア(2026.8)に対して構築・テスト済み、31件のスペック、CIは標準的な discourse-plugin ワークフローを実行します。フィードバックを歓迎します。特に、デフォルトのフレーズリストが漏らしている他のリレーからの拒否フレーズについて。

「いいね!」 2