1 ポイント 投稿者 GN⁺ 2024-05-22 | 2件のコメント | WhatsAppで共有

メール本文から消えたピリオドの謎

単純ではない Simple Mail Transfer Protocol

  • Tjaart
    • 2024年2月20日

問題の発生

  • ある顧客に送ったメール本文からピリオドが消えたという報告を受けた。
  • 同じメールを別の顧客に送ったときは、ピリオドは消えなかった。

プロジェクトの振り返り

  • 約7年前、文書テンプレートを単一システムに統合するソリューションを開発した。
  • クライアントは Microsoft Word テンプレートを使い、文書内にプレースホルダーを入れていた。
  • スタッフがメールで文書を送るたびに、プレースホルダーを実際の内容に置き換える必要があった。

テンプレート管理の問題

  • テンプレートのバージョンが複数存在し、管理が難しかった。
  • 一部のテンプレートでは古い利用規約、ロゴ、フォントなどが使われていた。
  • すべてのテンプレートを中央で管理できるソリューションを開発した。

ソリューションの実装

  • クライアントは PDF 文書、テキストメッセージ、メール本文を生成するテンプレートを中央で管理できた。
  • たとえば、新規顧客に送るウェルカムレターのテンプレートを設定できた。
  • 各配信方法(メール、テキストメッセージ、郵便)ごとに異なるテンプレートを構成できた。

問題の再現

  • 特定の顧客に送ったメールでのみ、ピリオドが消える問題が発生した。
  • テンプレートのソースコードにはピリオドが含まれていた。
  • ローカル環境でメール本文をプレビューしたときは、ピリオドが表示されていた。

原因の分析

  • メール本文を生成する際、各行の長さを制限するコードがあった。
  • 行がその長さを超えると、新しい行を作成して残りの内容を移動していた。
  • SMTP 仕様では、行がピリオドで始まる場合は追加のピリオドを挿入し、サーバーは先頭のピリオドを削除する。

解決策

  • コードを修正し、行がピリオドで始まる場合は追加のピリオドを挿入して、サーバーが削除してもピリオドが残るようにした。
  • 修正したコードをテストした結果、ピリオドが消えないことを確認した。
  • 問題を解決し、ほかのチームにもこのバグを知らせた。

その後の問題

  • 数か月後、別のチームが同じバグを修正していなかったため、重要なメールでピリオドが消えた。
  • 一部の顧客には、新しい月額料金が $27.00 ではなく $2700 と表示されたメールが送られた。
  • すぐにコードをパッチし、問題を解決した。

GN⁺の意見

  1. SMTP 仕様を理解する重要性: メール送信時に起こりうる問題を解決するには、SMTP 仕様を深く理解することが重要。
  2. テンプレート管理の複雑さ: 複数バージョンのテンプレート管理は複雑になりうるため、中央管理システムが必要。
  3. デバッグ技術: 問題を再現し、原因を分析するデバッグ技術が重要。
  4. チーム間コミュニケーション: 問題を解決した後は、ほかのチームと情報を共有することが重要。
  5. 自動テスト: このような問題を防ぐために、自動テストを導入するのが望ましい。

2件のコメント

 
surfindia 2024-05-22

タイトルの period をピリオドではなく期間として解釈したみたいですね(笑)

 
GN⁺ 2024-05-22
Hacker News の意見

Hacker News コメントまとめ要約

  • SMTP クライアント実装の難しさ

    • SMTP クライアントの実装は難しく、適切に実装されていないとバグが発生しやすい。テンプレート層は SMTP を意識すべきではない。
    • 多くの人がターミナルを通じて基本プロトコルを学ばないため、このような問題が発生する。メッセージを「単一のドット」で終了するルールは重要である。
    • 多くのプログラマーはエスケープの概念を理解していない。「単一のドット」を含むメールを送る状況を考慮していない。
  • ドイツの推薦状の話

    • ドイツでは雇用終了時に推薦状を受け取るのが一般的である。推薦状の最後の文に句点がないと、否定的な意味を含んでいる。
    • 弁護士に推薦状を確認してもらった際、最後の文に句点がなく、それが問題になっていた。
  • cron ジョブと SMTP クライアント

    • メールを送る cron ジョブが独自の SMTP クライアントを実装する必要はない。mailutils のようなプログラムを使えばよい。
    • ソケット経由で基本的な SMTP のやり取りを実装するのは非効率である。TLS 接続と認証が必要になる。
    • cron にはすでにメール送信機能がある。MAILTO 変数を使ってメールアドレスを設定できる。
  • 2つの悪い習慣

    • 標準を雑に実装してはいけない。必要な注意を払うか、あらかじめ用意されたライブラリを使うべきである。
    • 依存関係をベンダリングしてはいけない。ライブラリは定期的に更新すべきである。更新を先延ばしにすると大きな問題になる可能性がある。
  • ドットスタッフィングが必要

    • SMTP と POP3 ではドットスタッフィングが必要である。関連する RFC 文書を参照できる。
  • HTML MIME 添付ファイルの問題

    • "We are happy to welcome you to our family." という文は行制限に引っかからない。HTML MIME 添付ファイルである可能性がある。
    • HTML を無造作に行単位で分割すると、タグが壊れる可能性がある。
  • 最初の文字がドットの場合

    • 最初の文字がドットで、ほかに文字がある場合、最初の文字は削除される。単一のドットがメールの終わりを意味するためである。
    • なぜドットを削除するのか理解しづらい。次の文字を確認するために 1 バイト保存できるはずである。
  • バグ修正の通知

    • SMTP クライアントのコードが以前のプロジェクトから持ち込まれたものだったため、別のチームにこのバグを知らせた。
    • 別のチームがこのバグを修正していない可能性がある。
  • NNTP サーバー実装経験

    • RFC 仕様に基づいて NNTP サーバーを実装した際、ドットスタッフィングの問題をすぐに理解した。80年代のプロトコルである。