0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【MailOrca 実装実況①】PythonだけでMailHogの代替ツールを作ってみた【個人開発】

0
Posted at

はじめに

 あけましておめでとうございます(あるいは、こんにちは)。

 皆さんは年末年始、いかがお過ごしでしたか?
 私はというと、暇を持て余していました。 いや、それはともかく!

 普段、Django や Flask で開発をしていると、メール送信のテストをしたくなること、ありますよね?
 そんな時、デファクトスタンダードとしてよく使われるのが MailHog だと思います。Go言語製で、バイナリ一つで動くし、Dockerコンテナもあって非常に便利なツールだと思います。

 しかし、使っていると「ここ、もうちょっとこうしたいな……」という細かい不満や、「この挙動、どうなってるんだ?」とソースを追いたくなる瞬間があります。でも、Go言語の環境をセットアップしてビルドし直すのは、Python使いとしてはちょっと敷居が高い。

「……せや、年末年始で暇やし Python で自分好みの MailHog 作ったろ」

 というわけで、年末年始の勢いに任せて、Python エコシステムだけで完結する SMTP サーバー兼 Web UI ツール 「MailOrca(メールオルカ)」 を作ってみました。

 今回はその紹介も兼ねて、技術的な構成についての話(全4回)です。

MailOrca とは?

 今回作成した MailOrca は、開発環境向けの軽量 SMTP サーバーです。

 アプリケーション(Djangoなど)から送信されたメールを SMTP プロトコルで受け取り、メモリ上に保存して、Web ブラウザから即座に確認できます。ようするに 「Python 版 MailHog」 です。

MailOrca UI Screenshot(※開発中の画面イメージ)

ここがポイント

  1. Python Native:
    • Go や Docker は不要です。
    • Python 3.9 以上があれば動きます。
    % pip install git+https://github.com/yynet2022/mailorca.git
    % mailorca
    
    で直接導入したり、リポジトリを clone して
    % git clone https://github.com/yynet2022/mailorca.git
    % cd mailorca
    % pip install -r requirements.txt
    % python runserver.py
    
    するだけですぐに使えます。(前者はコマンド mailorcaで、後者は runserver.pyが用意してあります)
    • 既存の Python プロジェクトの dev-dependencies に GitHub の URL を指定して追加することも可能です。
  2. 設定が楽:
    • 「ポート番号を変えたい」「表示するヘッダー項目を変えたい」といった要望に、JSONファイル一つで応えられるようにしました。
  3. モダンな非同期構成:
    • 最近の Python といえば asyncio かなと。SMTP サーバーも Web サーバーも非同期でサクサク動きます。

全体アーキテクチャ

 「Python だけで作る」といっても、ゼロからソケットプログラミングをするのは車輪の再発明すぎます。

 今回は、Python 界隈の強力なライブラリを組み合わせて実現しました。

 構成図はこんな感じです。

技術スタック

 これらを runserver.py という一つのスクリプト(cloneした場合)から起動するようにしています。

  • Web Framework: FastAPI
    • Web UI の提供と、API エンドポイントの実装に使用。
    • テンプレートエンジンには Jinja2 を採用。
  • ASGI Server: Uvicorn
    • FastAPI を動かすためのサーバー。
  • SMTP Server: aiosmtpd
    • Python 標準ライブラリ(だった) smtpd が非推奨になった今、モダンな代替として使われる非同期 SMTP サーバーライブラリ。
  • CLI: Click
    • コマンドライン引数の解析に使用。「ポート番号を引数で上書き」みたいな処理が爆速で実装できる。

なぜ作ったのか(もう少し詳しく)

 既存ツール(MailHogなど)は素晴らしいですが、Python プロジェクトの開発中に「ちょっと挙動を変えたい」と思った時、Python で書かれていれば 「モンキーパッチで強引に挙動を変える」 とか 「直接ソースをいじって pip install -e . で読み込ませる」 といったハックが容易になります。

「自分が一番慣れ親しんだ道具で、自分好みの道具を作る」

 これが最大のモチベーション。(あと、aiosmtpdFastAPI を組み合わせて何か作りたかった、という技術的興味も)

次回予告

 今回は「作った動機」と「全体像」についてお話ししました。
 次回からは、実際にどうやって実装したのか、コードレベルでの解説をしていきたいと思います。

  • ClickUvicorn をどうやって連携させたのか?
  • FastAPIlifespan でバックグラウンドタスク(SMTP)を走らせる方法
  • aiosmtpd でメールを受け取って解析する泥臭い部分

などなど、技術的な詳細を掘り下げていきます。

 Python でちょっとしたサーバーツールを作ってみたい方の参考になれば幸いです。

 それでは、また次回!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?