はじめに
前回は、メールの生データをパースしてメモリに蓄えるところまでを解説しました。
最終回となる今回は、そのデータをブラウザで見やすく表示する Web UI 部分 についてお話しようと思います。
1. FastAPI + Jinja2 の王道構成
MailOrca の画面は、FastAPI 標準の Jinja2Templates を使ってレンダリングしています。
@app.get("/", response_class=HTMLResponse)
async def index(request: Request) -> Response:
"""Render the main page listing received emails."""
return templates.TemplateResponse(
request=request,
name="list.html",
context={
"mails": STORE.mails,
"columns": CONFIG["ui"]["list_columns"],
},
)
さりげないこだわりは、一覧画面の「カラム」を固定せず、config.json で制御可能な変数 CONFIG から動的に生成している点です。「Date」「Subject」「To」など、ユーザーが見たい項目を自由に入れ替えられるようにしています。
2. HTML メールの「CSS汚染」を防ぐ iframe
もしかしたら、これが今回一番の工夫かもしれません。
HTML メールを表示する際、そのままページ内に埋め込むと、メール内の CSS が管理画面全体のデザインを壊してしまう ことがあります(いわゆる CSS 汚染)。
これを防ぐため、詳細画面では <iframe> の srcdoc 属性を使っています。
<!-- detail.html -->
<iframe
srcdoc="{{ mail.parsed.body_html }}"
style="width: 100%; height: 500px; border: none;"
></iframe>
こうすることで、メールのコンテンツを完全に隔離されたサンドボックス内で表示でき、管理画面の Bootstrap が崩れる心配もありません。
ただし、一つ注意点があります。そのメールにリンクがあり、それをクリックした場合、相手先が iframe 内は不可と拒否される場合があります。そのリンクが target="_blank" となっていれば、別タブで開くので大丈夫でしょう。
3. 地味に便利な「URLリンク化」フィルタ
プレーンテキストのメールを表示するとき、URL がただの文字列だと不便ですよね。そこで、Jinja2 のカスタムフィルタを作って、URL を自動的に <a> タグで囲うようにしました。
def urlize_text(text: str) -> str:
# XSS対策で一旦エスケープ
escaped = html.escape(text)
# 正規表現でURLを置換
return re.sub(r'(https?://[^\s]+)', r'<a href="\1" target="_blank">\1</a>', escaped)
templates.env.filters["urlize"] = urlize_text
これをテンプレート側で {{ mail.parsed.body_text | urlize | safe }} と呼び出すだけで、使い勝手がグッと上がります。
4. API も生データダウンロードも
Web UI だけでなく、自動化テストなどでも使いやすいように JSON API を生やしています。
また、「やっぱりメーラーで確認したい」という時のために、受け取ったデータをそのまま .eml ファイルとしてダウンロードできる機能も実装しました。
@app.get("/mail/{mail_id}/download")
async def download_raw(mail_id: str):
# 生の bytes をそのままレスポンスとして返す
return Response(
content=mail["raw"],
media_type="message/rfc822",
headers={"Content-Disposition": f"attachment; filename={mail_id}.eml"}
)
おわりに
年末年始に始めた MailOrca 開発は良い暇潰し……もとい、勉強になりました。実際に作ってみると、使い慣れた Python でも「非同期サーバーの共存」や「メールパースの泥臭さ」など、新しい発見がたくさんありました。
「ここをもっとこうしたい!」というアイディアはまだまだ尽きませんが、ひとまず「自分が(Django などでの)開発で使いたいツール」としては満足のいく形になったと思います。
もし興味を持っていただけたら、ぜひ GitHub を覗いてみてください。そして、皆さんも自分だけの「オレ得ツール」を作って、快適な開発ライフを!
- MailOrca - GitHub: https://github.com/yynet2022/mailorca
全4回、お付き合いいただきありがとうございました!
