Twistedを利用してメールサーバーを立てる

Twistedを利用してメールサーバーを立てる
=========================

テストのためだけにsendmailやらpostfixやらqmailやら、
MTAを設定してconfigファイルを変更して、とか
大変だったりするし、だからといってゴミテストメールを
本番環境に対して送り付けるのもアレな気がする。
[Minimock](https://pypi.python.org/pypi/MiniMock)などのモックライブラリを使うという手もあるが、
サポートしていないライブラリを利用していたら、とか
だるいときに使いたい。

Twistedは万能なので、簡単にメールサーバーを立ちあげられる。

動作環境
--------

検証環境は以下のとおり。
(環境とソフトウェアが混ざってるのはご愛嬌)

|ソフトウェア|バージョン|
|:-----------|------------:|
|Mac OS X|10.8|
|Python|2.7.4|
|Twisted|0.13.0|

動作前準備
----------

- distributeはインストールしているか？

していない場合は、以下の手順でインストールしましょう。

```sh
> curl -O http://python-distribute.org/distribute_setup.py
> sudo python distribute_setup.py
```

- pipはインストールしているか？

していない場合は、以下の手順でインストールしましょう。

```sh
> sudo easy_install pip
```

- virtualenvはインストールしているか？

していない場合は、以下の手順でインストールをしましょう。

```sh
> pip install virtualenv
```

環境準備
-------

Twistedをグローバルでインストールするのもアレなんで、
以下の感じでSandbox環境を作成しましょう。

```sh
> mkdir -p ~/Sandbox/TwistedMail
> cd ~/Sandbox/TwistedMail
> virtualenv python
> source python/bin/activate
> pip install twisted
```

起動！
-----

以下で終わり

```sh
> twistd mail --maildirdbmdomain=example.com=/tmp/example.com --user=futoase=mogemoge
```

example.comのメールサーバーとして、且つ
ユーザーはfutoase、パスワードはmogemogeとして
設定、という形です。気楽ですね。

デフォルトたとSMTPのポートは8025、POP3のポートは8110となっています。
既存のMTAプロセスと衝突するとアレなんでポートはこのままが良いと思います。

動作の確認を行う
--------------

Pythonで簡易なメール送信テストスクリプトを書いて、
メールの送受信テストを行なってみましょう。

メールをfutoase@example.com側に送信する
===========================

Hello worldをfutoase@example.comに送り付けるスクリプトを書く。

```py 
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import smtplib

server = smtplib.SMTP('localhost', 8025)
server.set_debuglevel(1)
server.sendmail('futoase@localhost', 'futoase@example.com', 'Hello world')
server.quit()
```

スクリプトを実行するとRCPTコマンドなどを
相手側に送信する。

```sh
send: 'ehlo matsuzakipc.local\r\n'
reply: '500 Command not implemented\r\n'
reply: retcode (500); Msg: Command not implemented
send: 'helo matsuzakipc.local\r\n'
reply: '250 matsuzakipc.local Hello 127.0.0.1, nice to meet you\r\n'
reply: retcode (250); Msg: matsuzakipc.local Hello 127.0.0.1, nice to meet you
send: 'mail FROM:<futoase@localhost>\r\n'
reply: '250 Sender address accepted\r\n'
reply: retcode (250); Msg: Sender address accepted
send: 'rcpt TO:<futoase@example.com>\r\n'
reply: '250 Recipient address accepted\r\n'
reply: retcode (250); Msg: Recipient address accepted
send: 'data\r\n'
reply: '354 Continue\r\n'
reply: retcode (354); Msg: Continue
data: (354, 'Continue')
send: 'Hello world\r\n.\r\n'
reply: '250 Delivery in progress\r\n'
reply: retcode (250); Msg: Delivery in progress
data: (250, 'Delivery in progress')
send: 'quit\r\n'
reply: '221 See you later\r\n'
reply: retcode (221); Msg: See you later
```

futoase@example.comに送られたメールを受け取る
===============================

Hello worldをfutoase@example.comというユーザーとして受け取る
スクリプトを書く。(ついでにDELEコマンドを使ってメールを削除する)

```py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import poplib

client = poplib.POP3('localhost', 8110)
client.user('futoase@example.com')
client.pass_('mogemoge')
num_messages = len(client.list()[1])

for i in range(num_messages):
  for j in client.retr(i+1)[1]:
     print(j)

for i in range(num_messages):
  client.dele(i)
```

メールをPOP3を利用して取得するスクリプトを実行すると、
送信側で作成されたスクリプトの内容が表示される。

```py
Delivered-To: futoase@example.com
Received: from matsuzakipc.local ([127.0.0.1] helo=matsuzakipc.local)
        by matsuzakipc.local with esmtp ([twisted, version 13.0.0])
        for <futoase@example.com>; Tue, 30 Apr 2013 13:23:12 +0900

Hello world
```

モックライブラリを使わず、
とりあえずテスト用のメールサーバーを立ち上げる、という点であれば
Twistedが楽。何も考えなくて良い。

overSSLもサポートしていたりする。
Twistedは無敵な気がする。