hogehoge foobar Blog Style Beta

Web,Mac,Linux,JavaScript,Perl,PHP,RegExp,Git,Vim,Redmineなど技術的なことのメモや、ちょっと便利そうなものの紹介をしています。

Google App Engineでメールを送信 & データストアを試してみる

Google App Engine(以下GAE) でメールを送信する処理を試してみたので、そのときのメモとして。

GAE では PythonJava が利用可能ですが、Pythonで試してみています。
(Pythonの方が色々とお手軽にできそうだったので。Python初心者ですけど。)

メール送信は mail.send_mail() 関数か? EmailMessageクラスか?

GAEでメールを贈る場合、「mail.send_mail() 関数」を使う方法と、「EmailMessageクラス」を使う方法があります。

mail.send_mail() 関数の使用例
from google.appengine.api import mail

mail.send_mail(sender="from@example.com",
              to="sendto@example.com",
              subject="テストメールの件名",
              body="""
メールの本文
""")
EmailMessage クラスの使用例
from google.appengine.api import mail

message = mail.EmailMessage(sender="from@example.com",
                            subject="テストメールの件名")

message.to = "sendto@example.com"
message.body = """
メールの本文
"""

message.send()

EmailMessage クラスの方が、オブジェクト指向チックに書けるので、今回は EmailMessage クラスを使ってみました。

日本語を使おうとすると UnicodeDecodeError が発生

message.body = "メールの本文"

上記のように、メールを送るのに件名や本文に日本語を使おうとすると

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 2: ordinal not in range(128)

というようなエラーが発生しました。

いろいろググってみた結果以下のようにして、文字列をUnicodeとして認識させたらエラーは発生しなくなりました。

#!-*- coding:utf-8 -*-

# 文字列の頭に「u」を付加して Unicode型 にする
message.body = "メールの本文"

詳しくは、PythonのUnicodeEncodeErrorを知る - HDEラボ がとても参考になりました。

データストアを試してみる

メール送信のついでにデータストアも試してみたかったので、送信先のメールアドレスをデータストアから取得出来るようにしてみました。

GAEででーたストアを操作するには、「データ モデリング API」を使用します。
具体的には、「google.appengine.ext.db」をインポートして、データモデル用のクラスを作ります

データモデル用クラスの例
# データ モデリング API をインポート
from google.appengine.ext import db

# メールアドレスを格納するのデータストアのモデルクラス
class Mail(db.Model):
    email = db.StringProperty(required=True)
    status = db.BooleanProperty(default=False)
    modified = db.DateTimeProperty(auto_now=True)
    created = db.DateTimeProperty(auto_now_add=True)

データストアからデータを取得する場合、モデルクラスの「all」メソッドなど使用します。
下記の例では、

  1. Mail に登録されているデータを全件取得(all)
  2. status=True のデータのみに絞り込み(filter('status =', True))
  3. データをメールアドレス昇順で並び替え(order('email'))

という処理を行っています。

データモデルでのデータ取得の例
mails = Mail.all().filter('status =', True).order('email')

今回作成したサンプルコード(全部)

以下が今回作成したサンプルコードの全文になります。
GAEはもとより、Pythonにも不慣れなところがあるので、よろしくない点が多々あると思いますので、ご参考までに。

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

from google.appengine.ext import webapp, db
from google.appengine.api import mail
from google.appengine.api import users
import os
import cgi
import datetime
import logging
import string
import locale

# メールアドレス格納用のデータストア
class Mail(db.Model):
    email = db.StringProperty(required=True)
    status = db.BooleanProperty(default=False)
    modified = db.DateTimeProperty(auto_now=True)
    created = db.DateTimeProperty(auto_now_add=True)

# メール送信用クラス
class SendMail(object):

    # コンストラクタ
    def __init__(self, sub='', from_ad='from@exsample.com'):
        # インスタンス変数にデータセット
        self.add_sub = sub
        self.from_addr = from_ad

    # メール送信
    def send(self):

        # データストアからデータを取得
        mails = Mail.all().filter('status =', True).order('email')
        
        # メールアドレスを取得して配列に格納
        to_addr = []
        for mailmodel in mails:
            to_addr.append(mailmodel.email)
        
        # EmailMessageのインスタンス生成
        message = mail.EmailMessage(sender=self.from_addr,
                                    subject=sub)

        # 送信先アドレスをセット
        message.to = ';'.join(to_addr)
        
        # メール本文のセット
        message.body = u"""
            メールの本文。
            ほげほげ。
        """
        
        # メール送信
        message.send()
        
# POSTで呼び出される処理
class MainHandler(webapp.RequestHandler):
    def post(self):
        mail = SendMail('テストメールの件名')
        mail.send()

def main():
    application = webapp.WSGIApplication([('/send', MainHandler)],
                                         debug=True)
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()