この記事では、App Engine アプリを Python で構築し、ユーザーにメールを送信して、受信トレイから直接メーリング リストの登録を確認してもらい、その登録をデータストアに収集する方法について説明します。
前提条件とプロジェクトの設定
このガイドでは、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="Approve Expense"/>
<div itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
<link itemprop="url" href="https://myexpenses.com/approve?expenseId=abc123"/>
<meta itemprop="url" content="{{ confirm_url }}"/>
<link itemprop="method" href="http://schema.org/HttpRequestMethod/POST"/>
</div>
</div>
<meta itemprop="description" content="Approval request for John's $10.13 expense for office supplies"/>
</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 です。
登録リクエストをユーザーに送信する
次のコードを 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)
SubscribeHandlerclass listens to bothPOSTandGETrequests sent to the app root url (https://APP-ID.appspot.com).POSTrequests are used by Gmail to insert new subscriptions including theuser_id` パラメータを含む新しい登録を挿入するために Gmail によって使用されます。
https://subscribe.appspot.com/?user_id=123abcd
リクエスト ハンドラは、必要な user_id が定義されていることを確認し、登録を データストア に保存します。これにより、リクエストが成功したことを示す HTTP 200 レスポンス コードが Gmail に返されます。リクエストに必要なフィールドが含まれていない場合、リクエスト ハンドラは HTTP 400 レスポンス コードを返して、リクエストが無効であることを示します。
アプリのルート URL への GET リクエストは、収集された登録の一覧表示に使用されます。リクエスト
ハンドラは、まずデータストアからすべての登録を取得し、簡単なカウンタとともにページに出力します。
アプリのテスト
App Engine にアプリをデプロイし、https://APP-ID.appspot.com/email にアクセスして(APP-ID は App Engine アプリ ID に置き換えます)、アノテーション付きメールを自分に送信します。

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