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


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

Postfixの起動

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

/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>
<key>QueueDirectories</key>
<array>
    <string>/var/spool/postfix/maildrop</string>
</array>

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

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

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

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

$ sudo postfix start

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

@@ -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の設定

試しに何も設定しないで

$ 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の「端末を選択」で「その他(名前を入力)でPostfixなどと入力して取得する。

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

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

設定したら

$ sudo postmap gmail_passwd

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

$ 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 に書いてあるように安全性の低いアプリがアカウントにアクセスするのを許可する必要があるので、許可をする。

ちなみに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 メールアドレス

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