Artikel ini menunjukkan cara mem-build aplikasi App Engine di Python yang mengirimkan email teranotasi ke pengguna yang meminta konfirmasi langganan milis langsung dari kotak masuk mereka dan mengumpulkan langganan di Datastore.
Prasyarat dan penyiapan project
Panduan ini mengasumsikan bahwa Anda telah menginstal App Engine SDK dan mengetahui cara membuat, menjalankan, dan memublikasikan project App Engine.
Pertama, buat direktori untuk project Anda. Masukkan semua file untuk aplikasi Anda di direktori ini.
Salin kode berikut ke file bernama app.yaml
dan ganti placeholder {{ APPID }}
dengan ID aplikasi App Engine Anda yang unik:
application: {{ APPID }}
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
Buat file bernama main.py
di folder project App Engine dan salin kode berikut guna menyiapkan pengendali untuk mengumpulkan dan mencantumkan langganan, dan untuk mengirim email yang dianotasi:
import webapp2
from emailsender import EmailSender
from subscribe import SubscribeHandler
app = webapp2.WSGIApplication([('/', SubscribeHandler), ('/email', EmailSender)], debug=True)
Menambahkan data terstruktur ke email
Mari kita mulai dengan email yang sangat sederhana yang meminta pengguna untuk mengonfirmasi langganan milis:
<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>
Anda dapat menambahkan data terstruktur dalam salah satu format yang didukung (JSON-LD atau Microdata) ke head
email untuk menentukan restoran dan menambahkan OneClickAction. Gmail mendukung OneClickAction
dan menampilkan UI tertentu kepada pengguna untuk memungkinkan mereka mengonfirmasi langganan dari kotak masuk.
Salin markup berikut ke dalam file bernama 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>
Data terstruktur di atas menjelaskan milis yang disebut "XYZ" dan ConfirmAction
. Pengendali untuk tindakan ini adalah HttpActionHandler
yang mengirim permintaan POST ke URL yang ditentukan di properti url
.
Mengirim permintaan langganan ke pengguna
Salin kode berikut ke file bernama emailsender.py
di folder project App Engine:
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)
Class EmailSender
mengharuskan pengguna untuk login agar alamat email mereka dapat diambil. Kemudian, aplikasi akan memuat isi email dari mail_template.html
, mengganti placeholder confirm_url
di dalamnya dengan URL root aplikasi App Engine (https://APP-ID.appspot.com
), dan mengirimkan email ke pengguna yang saat ini login sebagai diri mereka sendiri.
Mengumpulkan dan mencantumkan langganan
Salin kode berikut ke file bernama subscribe.py
di folder project App Engine:
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)
Parameter SubscribeHandlerclass listens to both
POSTand
GETrequests sent to the app root url (
https://APP-ID.appspot.com).
POSTrequests are used by Gmail to insert new subscriptions including the
user_id` yang sesuai dengan pengguna, seperti dalam contoh berikut:
https://subscribe.appspot.com/?user_id=123abcd
Pengendali permintaan hanya memeriksa apakah user_id yang diperlukan telah ditentukan, lalu menyimpan langganan di Datastore. Hal ini menyebabkan kode respons HTTP 200
dikirim kembali ke Gmail untuk menandakan permintaan yang berhasil. Jika permintaan tidak menyertakan kolom yang diperlukan, pengendali permintaan akan menampilkan kode respons HTTP 400
, yang menandakan permintaan yang tidak valid.
Permintaan GET
ke URL root aplikasi digunakan untuk mencantumkan langganan yang telah dikumpulkan. Pengendali permintaan pertama-tama mengambil semua langganan dari Datastore, lalu mencetaknya di halaman, bersama dengan penghitung sederhana.
Menguji aplikasi
Deploy aplikasi Anda ke App Engine dan buka https://APP-ID.appspot.com/email
(ganti APP-ID
dengan ID aplikasi App Engine Anda) untuk mengirim email yang telah dianotasi ke diri Anda sendiri.
Setelah Anda men-deploy aplikasi dan memasukkan beberapa langganan, buka aplikasi Anda di https://APP-ID.appspot.com
untuk mendapatkan halaman yang merangkum langganan