コードミスで自社メールサーバーを受信不能にした話
― たった4行を書かなかったせいで会社のメールが全滅した ―
この記事は
本番環境などでやらかしちゃった人 Advent Calendar 2025
の 9日目 の記事です。
今回は、
「4行の if 文を入れ忘れた結果、自社で契約しているメールサーバーを物理的に爆撃した話」
を供養します。
きっかけ
「メールアドレスなしでもアカウント登録できるようにしたい」
もともと本サービスでは、初回登録時に以下の情報が必須でした。
- メールアドレス
- ユーザー名
- 名前
- 初回ログインパスワード(6桁)
しかし、公的機関向けに提供する都合上、
- メールアドレスが 個人情報として取得しづらい
- 組織メール(特に高校など)が ほぼ運用されていない
という現実的な問題に直面しました。
大学生なら機構メールは使いますが、高校以下になると
「アカウントはあるけど誰も見ていない」
という状況が本当に多い。
つまり
「メールアドレスを登録必須にするとサービスが使えない」
という結論になり、
「それならメールなしで登録できるようにしよう」
と即決しました。
実装した仕組み(ここまでは平和)
実装自体はとても単純です。
if (email.endsWith('@no-address.example.com')) {
mail.certification(true);
}
このドメインを指定している場合は
「強制的にメール認証済み扱いにする」
という実装です。
ユーザー名の重複を防ぐため、
登録時には以下のようなダミーメールアドレスを自動生成していました。
g001_20250001@no-address.example.com
-
g001_20250001→ ユーザー名 -
@no-address.example.com→ 自社ドメイン
このドメインは Cloudflare Email Workers を使って、
さくらインターネットのメールサーバーに転送していました。
余談:さくらのメールは受信専用なら最強
メールボックスだけなら年間 2,000円ちょっと で使えるので、
「とりあえず受信用メールが欲しい」用途には本当に便利です。
※なぜかメールが弾かれやすいので、送信には向きません。
認証フローの問題点(ここが伏線)
本サービスは、
- 認証URLをメールで送信
- そのURLにアクセス
- パスワード等をユーザーが設定
という一般的なフローでした。
しかし今回のケースでは:
- 送信先は ユーザー本人が見ないダミーメール
- 認証URLは DBを直接見て取得する想定
だったので、
「メールは送られなくていい」という前提になっていました。
やらかし発生
前準備が整い、
アカウント発行処理を一括で実行しました。
すると――
さくらのメールサーバーが容量制限で死亡
社内の全メールが受信不能に
原因は単純でした。
先ほどのコードは
「認証を強制的に true にする」処理のみで、
👉 「認証メールを送らない」処理を書いていなかった
つまり、
- 認証済み扱い
- でも 認証メールは全件送信
という地獄の挙動になっていました。
追い打ち:現場猫ムーブ
さらに最悪だったのがこれ。
- 当該パッチは インターン生が実装
- コードレビューなし
- 「まあ大丈夫でしょ」という 現場猫判断
- そのまま 本番実行
結果、発行されたアカウント数は……
2,147,483,647 件
(※ 当時のコードが残っておらず、なぜこの数字になったのかは未だに不明です)
メールサーバーは、
- 大量送信
- 大量受信
- 容量上限に達する
- 会社全体のメールが 物理的に死亡
という完璧なコンボを決めました。
なお、なぜか アクセス制限やスロットリングは一切かからず、
「容量制限に当たるまで送られ続ける」 という地獄仕様でした。
どうすれば防げたのか
答えは、たったこれだけでした。
if (email.endsWith('@no-address.example.com')) {
certification = true;
}
else {
mail.send(certification_template(code));
}
たった 3 行の else 分岐。
これがあれば、
- ダミーメール → 認証のみ
- 通常メール → 認証メール送信
という正しい世界線に分岐できていました。
結論(血の教訓)
今回の事故から得た教訓はこれです。
- 仕様が変わる時は「既存フロー前提」で雑に継ぎ足さない
- 想定外の入力(今回で言うダミーメール)には 必ず分岐を書く
- どんなに急いでいてもコードレビューは省略しない
そして何より――
「送信系の処理は最悪“爆撃”になる」
ということを、身をもって学びました。
おわりに
なお、この事故は夜中に実行して、夜中に解消できたので開発陣営以外は知る由もありませんでした。
よって、誰にも怒られることなく闇に葬られました。
Advent Calendar らしく、
どこかの誰かが 同じ地雷を踏まないこと を願って、供養として公開します。