Pythonを使ってGmail経由でメールを送る

「計算が終わった」とか「スクリプトが終わった」とか「コンパイルが終わった」とか,そういうときに通知が欲しい.
そこで,メールを使って通知させることにする.
作業が終わったら,サーバからメールを送ってそれをメーラで受け取ることで通知になるわけだ.


メールを送るといったらmailコマンドなのだけど,mailコマンドを使って外部にメールを飛ばすにはサーバを立ち上げないといけない.
それだとどこでも使えないので(そもそも職場や研究室のネットワークを勝手にいじれないし),sendmailで外部のSMTPサーバ,今回はGmail,を使って送信できるようにする.
このようなことは,Pythonでできるらしいので,以下のページを参考にやってみる.

独学Linux : Python スクリプトでGmail経由のメールを送信する方法
#junki::acoustic: PythonでGmailを送信
ウノウラボ by Zynga Japan: Pythonでメールを送信したい人のためのサンプル集



gmailsend.pyとsend_notify.pyをまとめてダウンロード

PythonGmail送信スクリプト

まずは,Gmailでメールを送るための関数などを定義.
ココのを参考にした.
解説はココに詳しい.
ダウンロード - gmailsend.py

#!/usr/bin/python

import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import formatdate

class sendGmail:
  def __init__(self, encoding, subject, body, from_addr, to_addr, login_addr, passwd):
	self.date = formatdate()
	self.encoding = encoding
	self.subject = subject
	self.body = body.encode('utf-8')
	self.from_addr = from_addr
	self.to_addr = to_addr
	self.login_addr = login_addr
	self.passwd = passwd

  def sendMail(self):
    msg = MIMEText(self.body, 'plain', self.encoding)
    msg['Subject'] = Header(self.subject, self.encoding)
    msg['From'] = self.from_addr
    msg['To'] = self.to_addr
    msg['Date'] = self.date

    s = smtplib.SMTP('smtp.gmail.com', 587)
    s.ehlo()
    s.starttls()
    s.ehlo()
    s.login(self.login_addr, self.passwd)
    s.sendmail(self.from_addr, self.to_addr, msg.as_string())
    s.close()

これらの関数を読みこめば,以下のようにメールを送信することが出来るはず(Macで実行した場合).

$ python
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import gmailsend *
>>> sg = sendGmail(encoding, subject, body, 'from_address@gmail.com', to_address@xxx.xxx, 'gmail_account@gmail.com', passwd)

解説すると

  • encoding: メールの文字セット
  • subject: 件名
  • from_address: 送信元アドレス(普通はxxx@gmail.com)
  • to_address: 送信先アドレス(任意)
  • gmail_account: Gmailのアカウント名(xxx@gmail.com)
  • passwd: Gmailアカウントのログイン

という感じ.

gmailsend.pyを使った通知スクリプト

gmailsend.pyを使って,作業が終わったら呼び出されて通知メールを送るスクリプト.
ダウンロード - send_notify.py

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

import sys

argvs = sys.argv # 引数のリスト
argc = len(argvs) # 引数の数

# 本文をつくるなど
import commands
pwd = commands.getoutput("pwd")
host = commands.getoutput("hostname")
date = commands.getoutput("date +%D-%T")

subject = '[Notification]'
if (argc < 2): # 宛先がない場合はエラー
	print 'Usage: python send_notify.py address subject body'
	quit()
if (argc < 3): # 件名なし
	subject = subject + ' ' + date
else:
	subject = subject + ' ' + argvs[2]  + ' ' + date 

print subject

if (argc < 4): # 本文なし
	lbody = ''
else:
	lbody = argvs[3]

body = lbody + '\nFrom ' + host + '\n' +  pwd + '\n' +  date

to_addr = argvs[1]
print 'Notify to %s.' % to_addr
print 'Subject: ' + subject
print body

# メールの送信
from sendgmail import *
sg = sendGmail('utf-8', subject, body, 'xxx@gmail.com', to_addr, 'xxx@gmail.com', 'passwd')
sg.sendMail()

最後から2番目の行の'xxx@gmail.com'と'passwd'には,送信に用いるGmailのアドレス,ユーザ名,パスワードをあらかじめ書いておく.
send_notify.pyの使い方は,

$ python send_notify.py to_addr@xxx.xx test "send notification, thank you."

というふうに,送信先アドレス,件名,本文の順に引数として渡します.
送信先アドレスだけ必須.
これを実行すると,

  • 宛先: to_addr@xxx.xx
  • 件名: [Nortification] test 01/31/12-13:19:10
  • 送信元: xxx@gmail.com
  • 本文:

send notification, thank you.
From hostname.com
/dev/pts/12
/hoge/users/dir1/dir2
01/31/12-13:19:10

というメールが来ます.
本文は

  • 1行目: 3番目の引数(ない場合は改行のみ)
  • 2行目: 送信元サーバのホストネーム
  • 3行目: 端末の名前
  • 4行目: 送信元のカレントディレクトリ
  • 5行目: 現在時間

という構成になっている.
commands.pyを使うとシェルコマンドの返り値を簡単に本文に入れられるので,けっこう便利だと思う.


Pythonはかなり素人なので,多分突っ込みどころ満載だと思う.
一応Mac(Snow leopard)とLinuxCentOS 5.5とUbuntu 11.10)で動作確認済み.