このドキュメントでは、受信トレイから直接メーリング リストの登録を確認するようユーザーに求めるアノテーション付きメールを送信し、Datastore で登録を収集する Python の App Engine アプリを構築する方法について説明します。
前提条件とプロジェクトの設定
このガイドは、App Engine SDK がすでにインストールされており、App Engine プロジェクトの作成、実行、公開の方法を理解していることを前提としています。
まず、プロジェクト用のディレクトリを作成します。アプリケーションのすべてのファイルをこのディレクトリに配置します。
次のコードを app.yaml という名前のファイルにコピーし、{{ APPID }} プレースホルダを App Engine アプリの一意の ID に置き換えます。
application: {{ APPID }}
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
App Engine プロジェクト フォルダに main.py という名前のファイルを作成し、次のコードをコピーして、定期購入の収集と一覧表示、アノテーション付きメールの送信を行うハンドラを設定します。
import webapp2
from emailsender import EmailSender
from subscribe import SubscribeHandler
app = webapp2.WSGIApplication([('/', SubscribeHandler), ('/email', EmailSender)], debug=True)
メールに構造化データを追加する
まず、ユーザーにメーリング リストの登録を確認するよう求めるメールを送信します。
<html>
<head>
<title>Please confirm your subscription to Mailing-List XYZ?</title>
</head>
<body>
<p>
Dear John, please confirm that you wish to be subscribed to the
mailing list XYZ
</p>
</body>
</html>
サポートされている形式(JSON-LD または Microdata)のいずれかで構造化データをメールの head に追加して、メール メッセージを定義し、OneClickAction を追加できます。Gmail は OneClickAction をサポートしており、ユーザーが受信トレイから登録を確認できる UI 要素を表示します。
次のマークアップを mail_template.html という名前のファイルにコピーします。
JSON-LD
<html>
<head>
<title>Please confirm your subscription to Mailing-List XYZ?</title>
</head>
<body>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"potentialAction": {
"@type": "ConfirmAction",
"name": "Confirm Subscription",
"handler": {
"@type": "HttpActionHandler",
"url": "{{ confirm_url }}",
"method": "http://schema.org/HttpRequestMethod/POST"
}
},
"description": "Confirm subscription to mailing list XYZ"
}
</script>
<p>
Dear John, please confirm that you wish to be subscribed to the mailing list XYZ.
</p>
</body>
</html>
microdata
<html>
<head>
<title>Please confirm your subscription to Mailing-List XYZ?</title>
</head>
<body>
<div itemscope itemtype="http://schema.org/EmailMessage">
<div itemprop="potentialAction" itemscope itemtype="http://schema.org/ConfirmAction">
<meta itemprop="name" content="Confirm Subscription"/>
<div itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
<meta itemprop="url" content="{{ confirm_url }}"/>
<link itemprop="method" href="http://schema.org/HttpRequestMethod/POST"/>
</div>
</div>
<meta itemprop="description" content="Confirm subscription to mailing list XYZ"/>
</div>
<p>
Dear John, please confirm that you wish to be subscribed to the mailing list XYZ.
</p>
</body>
</html>
上記の構造化データは、「XYZ」というメーリング リストと ConfirmAction を記述しています。アクションのハンドラは、url プロパティで指定された URL に POST リクエストを送信する HttpActionHandler です。
重要: 上記のコードでは、メールを送信する前に、{{ confirm_url }} プレースホルダを App Engine アプリの URL(https://mailing-list.appspot.com など)に置き換えてください。次の手順で説明するコードは、この置換を処理します。
ユーザーに定期購入リクエストを送信する
次のコードを App Engine プロジェクト フォルダの emailsender.py という名前のファイルにコピーします。
import jinja2
import os
import webapp2
from google.appengine.api import mail
from google.appengine.api import users
from urlparse import urlparse
class EmailSender(webapp2.RequestHandler):
def get(self):
# require users to be logged in to send emails
user = users.get_current_user()
if not user:
self.redirect(users.create_login_url(self.request.uri))
return
email = user.email()
# The confirm url corresponds to the App Engine app url
pr = urlparse(self.request.url)
confirm_url = '%s://%s?user=%s' % (pr.scheme, pr.netloc, user.user_id())
# load the email template and replace the placeholder with the confirm url
jinja_environment = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
template = jinja_environment.get_template('mail_template.html')
email_body = template.render({'confirm_url': confirm_url})
message = mail.EmailMessage(
sender = email,
to = email,
subject = 'Please confirm your subscription to Mailing-List XYZ',
html = email_body)
try:
message.send()
self.response.write('OK')
except:
self.error(500)
EmailSender クラスでは、メールアドレスを取得できるように、ユーザーがログインしている必要があります。次に、mail_template.html からメールの本文を読み込み、その中の confirm_url プレースホルダを App Engine アプリのルート URL(https://APP-ID.appspot.com)に置き換えて、ログインしているユーザーにメールを送信します。
定期購入を収集して一覧表示する
次のコードを App Engine プロジェクト フォルダの subscribe.py という名前のファイルにコピーします。
import webapp2
from emailsender import EmailSender
from google.appengine.ext import db
class SubscribeHandler(webapp2.RequestHandler):
def post(self):
user_id = self.request.get('user')
# insert the subscription into the Datastore
subscription = Subscription(user_id=user_id)
subscription.put()
def get(self):
# retrieve up to 1000 subscriptions from the Datastore
subscriptions = Subscription.all().fetch(1000)
if not subscriptions:
self.response.write('No subscriptions')
return
count = len(subscriptions)
for s in subscriptions:
self.response.write('%s subscribed<br/>' % (s.user_id))
self.response.write('<br/>')
self.response.write('%d subscriptions.' % (count))
class Subscription(db.Model):
user_id = db.TextProperty(required=True)
SubscribeHandler クラスは、アプリのルート URL(https://APP-ID.appspot.com)に送信された POST リクエストと GET リクエストの両方を処理します。POST リクエストは、Gmail がユーザーに対応する user_id パラメータを含む新しいサブスクリプションを挿入するために使用されます。
https://subscribe.appspot.com/?user_id=123abcd
リクエスト ハンドラは、必要な user_id が定義されていることを確認し、サブスクリプションを Datastore に保存します。これにより、HTTP 200 レスポンス コードが Gmail に返され、リクエストが成功したことが通知されます。リクエストに必要なフィールドが含まれていない場合、リクエスト ハンドラは HTTP 400 レスポンス コードを返し、無効なリクエストであることを示します。
アプリのルート URL への GET リクエストは、収集されたサブスクリプションを一覧表示します。リクエスト ハンドラは、Datastore からすべてのサブスクリプションを取得し、カウンタとともにページに表示します。
アプリをテストする
App Engine にアプリをデプロイし、https://APP-ID.appspot.com/email(APP-ID は App Engine アプリ ID に置き換えます)にアクセスして、アノテーション付きメールを自分に送信します。

アプリをデプロイして定期購入を挿入したら、https://APP-ID.appspot.com でアプリにアクセスして、定期購入の概要ページを表示します。