メールのような書き言葉において、「.」で示されるピリオドは文末を示したり、数の区切りを示したりといった重要な働きがあります。エンジニアのTjaart氏が、かつて自分が修正に携わった「メール本文のピリオドが欠落してしまう現象」について振り返りました。

The curious case of the missing period - Tjaart’s Substack

https://tjaart.substack.com/p/the-curious-case-of-the-missing-period



2016年当時のTjaart氏は、全てのドキュメントテンプレートを1つのシステムに統合できるクライアント向けソリューションを構築するプロジェクトに携わっていました。Tjaart氏らの開発によって、PDFドキュメントやテキストメッセージ、および電子メールの本文の作成に使用される全てのテンプレートをクライアント側が一元的に管理できるソリューションが開発されました。

開発したソリューションがリリースされてから数カ月後、このシステムを使用しているユーザーの1人から「顧客に送信した電子メールの1つで、本文中のピリオドが欠落するケースがあった」との報告がTjaart氏らの元に届きました。また、「ピリオドの欠落は特定の顧客にのみ発生し、同じメールでも別の顧客に送信された際はピリオドの欠落が発生しなかった」ことも報告されたとのこと。

以下は正しく送信されたメールの例。「family」の直後にピリオドが置かれています。



一方で以下の画像では、「family」直後のピリオドが欠落してしまっています。



Tjaart氏が該当のメールのソースコードを確認すると、欠落しているはずのピリオドが実際にはソースコードに含まれていることが確認されました。Tjaart氏はただちに、本番環境で使用されているテンプレートのソースコードをローカルバージョンのソフトウェアにコピーし、プレビューとしてメール本文を作成しました。その際、プレビュー段階ではピリオドの欠落は確認されなかったほか、本文テンプレートをプリントアウトしてもピリオドは欠落していませんでした。

頭を抱えたTjaart氏らでしたが、コードに含まれるプレースホルダーを「ピリオドが欠落した」とされる顧客の氏名に変更したところ、報告があったとおりピリオドが欠落することが確認されました。

この結果、特定の内容のメールが特定の顧客に送信された場合、ピリオドの欠落が発生することが判明。また、さらなる調査の末、テンプレート内でピリオドの位置が変更されると、本文中のピリオドが再度表示されることも明らかとなりました。



Tjaar氏らはコードのデバックを開始し、電子メールを作成してローカルデータベースに保存するコードを段階ごとに実行。このコードでは、メールが「送信予定」としてデータベースに追加されると、送信が必要なメールを定期的にピックアップして送信するCronジョブが含まれています。

今回問題の焦点が当てられたのはこのCronジョブによって呼び出されているコードです。このコードの一部には、該当のソリューション以前に進められたプロジェクトの一部を流用した、SMTPクライアントが実装されています。

Tjaar氏らがこのコードを確認すると、コード内の関数の1つが、電子メール本文の各行が特定の文字数を超えないようにしていることが明らかとなりました。つまり、本文中のある行が文字数制限を超えると、新しい行が作成され、残りの文章がその行に移動するというわけです。

SMTPの仕様では、改行を指示する「CRLF」を含むテキスト行は最長1000文字と定められているほか、先頭のドットは1000文字の制限にカウントされないとのこと。



Tjaar氏はコードを何度も実行する中で、ピリオドが欠落した次の行の文は、ピリオドで始まっていることを突き止めました。これは前の行が特定の文字数を超え、新しい行が作成された結果、ピリオドが次の行の文頭に移動したことを示しています。

以下の例では「family」の直後にピリオドが適切に表示されています。



しかし、カスタムSMTPクライアントで本文を書式設定すると、本文5行目の文頭にピリオドが表示され、「family」の直後のピリオドは欠落しています。



Tjaar氏がSMTPクライアントとSMTPサーバーの仕様を確認すると、SMTPクライアントには「メール本文の行を送信する前に、SMTPクライアントはその行の最初の文字をチェックする。それがピリオドであれば、行頭にさらにピリオドが1つ挿入される」、SMTPサーバーには「最初の文字がピリオドで、その行に他の文字がある場合、最初の文字は削除される」との記載がありました。

Tjaar氏らはただちに、「SMTPサーバーが行頭のピリオドを削除しても、実際にはピリオドは削除されない」との修正を実施し、問題が解決したことをユーザーに報告したとのこと。

修正パッチの適用をもってこの問題は一見解決したように見えましたが、その後別のユーザーから「毎月の保険料を通知するためのメールで、一部のユーザーの小数点が欠落している」との報告が上がりました。

以下は小数点を示すピリオドが正しく表示されたメールの例。



以下のメールでは「$27.00」が「$2700」と表示されてしまっています。



しかし、これまでの経験を基に、Tjaar氏らはバグの発生原因について「メール本文の各行の長さ」とすぐに特定しました。入力した顧客の氏名などが特定の文字数だった場合、ピリオドが次の行の最初の文字に移動し、削除されてしまったことが要因とのこと。ただちにコードには修正パッチが適用され、これらの問題は解決しました。