Macでコマンドラインやプログラムからmailを送る

MacにはPostfixというメール転送エージェントが入っているのでこれを使用する。

Postfixの起動
=============

Postfixの起動の設定が `/System/Library/LaunchDaemons/org.postfix.master.plist` に書いてあって、Yosemiteだと以下のようになっている。

```xml:/System/Library/LaunchDaemons/org.postfix.master.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>org.postfix.master</string>
	<key>Program</key>
	<string>/usr/libexec/postfix/master</string>
	<key>ProgramArguments</key>
	<array>
		<string>master</string>
		<string>-e</string>
		<string>60</string>
	</array>
	<key>QueueDirectories</key>
	<array>
		<string>/var/spool/postfix/maildrop</string>
	</array>
	<key>AbandonProcessGroup</key>
	<true/>
</dict>
</plist>
```

```xml
<key>QueueDirectories</key>
<array>
    <string>/var/spool/postfix/maildrop</string>
</array>
```

の部分で<string>で設定されたディレクトリを監視していて、mailコマンドでファイルが生成されると

```xml
<key>ProgramArguments</key>
<array>
<string>master</string>
<string>-e</string>
<string>60</string>
</array>
```

の設定で自動的にPostfixが立ち上がり、mailを送信して、オプション`-e 60`によって、60秒後に終了する。

しかし、これはmailコマンドではうまく起動してくれたが、Pythonからメールを送ろうとした時に失敗したので、Pythonから使う前には

```sh
$ sudo postfix start
```

して、起動するか、Mac起動時に立ち上げるようにするには`/System/Library/LaunchDaemons/org.postfix.master.plist`を

```diff
@@ -9,8 +9,6 @@
        <key>ProgramArguments</key>
        <array>
                <string>master</string>
-               <string>-e</string>
-               <string>60</string>
        </array>
        <key>QueueDirectories</key>
        <array>
@@ -18,5 +16,7 @@
        </array>
        <key>AbandonProcessGroup</key>
        <true/>
+    <key>OnDemand</key>
+    <false/>
 </dict>
 </plist>
```


のように変更して、

```
$ sudo launchctl stop org.postfix.master # すでにlaunchctl startしている場合
$ sudo launchctl start org.postfix.master
```

してやる。[^1]

Postfixの設定
=============

試しに何も設定しないで

```sh
$ date | mail -s test アカウント@gmail.com
```

して、ログ(`/var/log/mail.log`)を見てみると

```
connect to gmail-smtp-in.l.google.com[74.125.25.27]:25: Operation timed out
```

といったエラーが出た。これはスパム対策として、ISP側で許可した特定のサーバ以外のSMTP（通常使用されるTCPポートの25番）の送信をブロックする処置(Outbound Port 25 Blocking)が行われているかららしい。[^2]

そこでGmailをSMTPサーバとして利用して、メール送信をするように設定する。他にもmail.me.comを使ったり[^3]、プロバイダのSMTPサーバを使う方法[^4]がある。

/private/etc/postfix/main.cfに以下の設定を追加する

```:/private/etc/postfix/main.cf
# Posifix Configuratoins
relayhost = smtp.gmail.com:587

# SASL Authentication
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/gmail_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_mechanism_filter = plain

# TLS Settings
smtp_use_tls = yes
smtp_tls_security_level = encrypt
tls_random_source = dev:/dev/urandom
```

はじめ、`smtp_sasl_mechanism_filter = plain`を書いてなくて

```
SASL authentication failed; cannot authenticate to server smtp.gmail.com[173.194.72.108]: generic failure
```

というエラーが出たので追加した。

パスワードの設定
================

パスワードは2段階認証の設定をしている場合はアプリ パスワードを使用し、してない場合は通常のパスワードを使う。

アプリ パスワードは[https://security.google.com/settings/security/apppasswords](https://security.google.com/settings/security/apppasswords)の「端末を選択」で「その他（名前を入力）でPostfixなどと入力して取得する。

パスワードはmain.cfのsmtp_sasl_password_mapsで設定したファイル(`/private/etc/postfix/gmail_passwd`)に以下の形式で書く。

```plain:/private/etc/postfix/gmail_passwd
smtp.gmail.com:587 アカウント@gmail.com:パスワード
```

設定したら

```sh
$ sudo postmap gmail_passwd
```

して`gmail_passwd.db`を作る。作ったら`gmail_passwd`はいらなくなるので、削除する。

```sh
$ sudo postfix reload
```

して、設定を読み込む。


2段階認証してない場合はさらに設定が必要で、試しにメールを送信してみると

```
Please log in via your web browser and then try again.?534-5.7.14 Learn more at?534 5.7.14 https://support.google.com/mail/bin/answer.py?answer=78754
```

と出てくる。https://support.google.com/mail/bin/answer.py?answer=78754 に書いてあるように[安全性の低いアプリがアカウントにアクセスするのを許可する](https://support.google.com/accounts/answer/6010255)必要があるので、許可をする。

ちなみに2段階認証をしている時に、普通のパスワードを使用していると

```
SASL authentication failed; server smtp.gmail.com[173.194.72.109] said: 534-5.7.9 Application-specific password required. Learn more at?534 5.7.9 http://support.google.com/accounts/bin/answer.py?answer=185833
```

というエラーがでる。

これで設定は終わり。

```
$ date | mail -s test メールアドレス
```

などで、送信されるか確かめよう。


[^1]: [Mac OSXでPostfixが勝手に起動する仕組み - こせきの技術日記](http://koseki.hatenablog.com/entry/20090901/MacPostfix) とそのリンク先参照
[^2]: [Outbound Port 25 Blocking - Wikipedia](http://ja.wikipedia.org/wiki/Outbound_Port_25_Blocking)
[^3]: [Mac OS X (Mountain Lion)で、Postfix(sendmail)の設定を行いコマンドからgmail/icloudアドレスでメールを送る | Roguer](http://roguer.info/2012/11/21/6094/)
[^4]: [自分のための日記: Mac OS X で mail コマンドでメールを送る](http://yasuwagon.blogspot.jp/2011/05/mac-os-x-mail.html)