Help us understand the problem. What is going on with this article?

プロセスの終了時にGmailを送信する【Python】

More than 5 years have passed since last update.

今回は,少し前にPythonでGmailを使う方法を学んだので,それをまとめておきたいと思います.
それから,コマンドを実行し,その結果をGmailで送信するシェルスクリプトも作りましたので,その紹介も.

参考:

ベースとなったもの:unoh.github.com by unoh:
やりたいことそのもの:Pythonでプロセスを監視して終了したらgmailを使ってメール送信する | せかいらぼ:
画像の送信について:独学Linux : Python スクリプトでGmail経由のメールを送信する方法:
SMTPに関して:プログラミングと慶應通信 : Pythonでgmailの送受信:
日本語の扱いについて:Pythonで日本語メールを送る方法をいろいろ試した - Qiita:

Pythonを使ってGmailを送信する

まず,参考にしたコードをコピペしてみて,動くかどうか試しましたが,一応動きました.あとはこれを外から呼び出したりするときに使いやすいようにカスタマイズするだけです.また,日本語のエンコードの問題や,セキュリティ面を考えて,さらにいくつかのサイトを参考にして,改良しました.

いいとこ取りしただけですが,とりあえず載せておきます.

sendGmail.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import formatdate
from platform import python_version
import argparse
import getpass
import codecs

release = python_version()
if release > '2.6.2':
    from smtplib import SMTP_SSL
else:
    SMTP_SSL = None

def create_message(from_addr, sender_name, to_addr, subject, body, encoding):
    msg = MIMEText(body, 'plain', encoding)
    msg['Subject'] = Header(subject, encoding)
    form_jp = u"%s <%s>" % (str(Header(sender_name, encoding)), from_addr)
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Date'] = formatdate()
    return msg

def send_via_gmail(from_addr, to_addr, passwd, msg):
    if SMTP_SSL:
        print "send via SSL..."
        s = SMTP_SSL('smtp.gmail.com', 465)
        s.login(from_addr, passwd)
        s.sendmail(from_addr, [to_addr], msg.as_string())
        s.close()
        print 'mail sent!'
    else:
        print "send via TLS..."
        s = smtplib.SMTP('smtp.gmail.com', 587)
        if release < '2.6':
            s.ehlo()
        s.starttls()
        if release < '2.5':
            s.ehlo()
        s.login(from_addr, passwd)
        s.sendmail(from_addr, [to_addr], msg.as_string())
        s.close()
        print "mail sent!"

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Send Gmail.')
    parser.add_argument('-t', '--to', dest='to_addr', type=str,
                        default='デフォルトの送信先',
                        help='To address')
    parser.add_argument('-s', '--subject', dest='subject', type=str,
                        default='デフォルトのタイトル', help='Title')
    parser.add_argument('-b', '--body', dest='body', type=str,
                        default='no message', help='Body of the mail.')
    args = parser.parse_args()

    from_addr = "送信元のGmailアドレス"
    sender_name=u'送信元の名前'
    print "from: %s <%s>" % (sender_name, from_addr)
    passwd = getpass.getpass()
    to_addr = args.to_addr
    title = args.subject
    body = args.body
    msg = create_message(from_addr, sender_name, to_addr, title, body, 'utf-8')
    send_via_gmail(from_addr, to_addr, passwd, msg)

前半のバージョンチェックは,他の環境でも動くためにはこれくらい必要なのかもしれません(コピペですみません).argparseを使えば,オプションの扱いが楽になるようなので,今回はそれを導入しました.

ちなみに,argparseを使えばヘルプを表示させることも簡単で,

Selection_008.png

のように表示してくれます.

それ以外の基本の部分は,参考にしたサイトのものとほとんど同じです.SSLの方がTLSよりセキュリティ的には良いようです.また,Googleアカウントのパスワードを直で書くのには抵抗があると思うので,直接実行する場合には,キーボードからの入力を受け付け,getpassを使うことで打った内容が表示されないようにしてあります.

プロセスの終了を待って,メールでお知らせ

なぜわざわざPythonからメールを送りたいかというと,時間のかかる計算を研究室のパソコンでさせておいて,自分は家に帰って結果が出てきたらそれを受け取る,ということをしたかったからです.なんで?って,なんかかっこいいじゃないですか!

・・・ということで,今度はその部分をシェルスクリプトで書くことにします.基本的にはPythonスクリプトを対象にしているのですが,汎用性を考えて,コマンド自体を引数に与える形にしました.

コードはこちら.

psWatchMail.sh
if [ $# = 0 ]; then
    echo "need argument 'COMMAND'" 1>&2
    exit 0
else
    COMMAND=$1
fi
subject="command \"${COMMAND}\" done"

result=`${COMMAND}`

wait

sleep 1

python /スクリプトまでのパス/sendGmail.py -t "送信先メールアドレス" -s "${subject}" -b "${result}"

echo "${result}"

exit 0

これにより,

sh psWatchMail.sh "実行するコマンド"

とコマンドを指定することにより,そのコマンドが終了した時点で,スクリプト内で指定した宛先に,

「command "実行するコマンド" done」

という題名で,その標準出力を本文としたメールが送ることができます.最初はPIDなどを指定してプロセスが生きているかどうかの判定を行う方法を考えて,その方面で調べていたのですが,こっちの方がシンプルでわかりやすいので,こちらの方法を使うことにしました.どちらの場合にしろ,欠点はプロセスが完全に終了しないとメールが送れないということで,今まで作ったようなGUIのシミュレーションとは相性が悪いです.まぁ,初めから時間のかかるとわかっている部分があったら,逆にそのPythonスクリプトの内部でsendGmail.pyを呼び出すようにしておけば,任意のタイミングでメールを送ることができるので,それはそれでいいでしょう.もしくは,CPUの使用率をモニターして,ある閾値を下回ったら終了したと判定してもいいかもですね.これはおいおい考えることにします.

実行例は,

Selection_009.png

のようになります.Gmail側からも

Selection_010.png

と,メールが送信されていることが確認できます.

まとめ

PythonでGmailを使う方法をまとめました.しかし,これはGmailに限らず,他のメールクライアントからも送ることができます.その場合,メールサーバのアドレスとポート番号を変更してやればいいです.僕の場合,実際に大学のメールアカウントのバージョンも作っていて,ターミナルからメールを打つこともあります.便利かと言われると微妙ですが.でも,いちいちログイン認証とか,重たいサイトを開かないといけなくてイラッとする人には向いてると思います.(これじゃ僕が心の小さい人みたいじゃないか!)ともかく,これで家と研究室,両方のパソコンで放置プレイが可能になりました.重たい計算ももう怖くないですね!

ssh0
[興味]物理/数学/Python/Linux/ShellScript 編集リクエスト、コメント、フォロー等はお気軽に。
http://ssh0.hatenablog.com/
team-lab
最新のテクノロジーを活用したシステムやデジタルコンテンツの開発を行うウルトラテクノロジスト集団
https://www.team-lab.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした