Bài viết này trình bày cách tạo một ứng dụng App Engine bằng Python để gửi email có chú thích cho người dùng yêu cầu xác nhận đăng ký danh sách gửi thư ngay trong hộp thư đến và thu thập các lượt đăng ký trong Datastore.
Điều kiện tiên quyết và cách thiết lập dự án
Hướng dẫn này giả định rằng bạn đã cài đặt App Engine SDK và biết cách tạo, chạy cũng như xuất bản các dự án App Engine.
Trước tiên, hãy tạo một thư mục cho dự án của bạn. Đặt tất cả các tệp cho ứng dụng của bạn vào thư mục này.
Sao chép mã sau vào một tệp có tên app.yaml
và thay thế phần giữ chỗ {{ APPID }}
bằng mã ứng dụng App Engine duy nhất của bạn:
application: {{ APPID }}
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
Tạo một tệp có tên là main.py
trong thư mục dự án App Engine rồi sao chép mã sau để thiết lập trình xử lý cho việc thu thập và liệt kê các lượt đăng ký, cũng như để gửi email có chú thích:
import webapp2
from emailsender import EmailSender
from subscribe import SubscribeHandler
app = webapp2.WSGIApplication([('/', SubscribeHandler), ('/email', EmailSender)], debug=True)
Thêm dữ liệu có cấu trúc vào email
Hãy bắt đầu bằng một email rất đơn giản yêu cầu người dùng xác nhận đăng ký danh sách gửi thư:
<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>
Bạn có thể thêm dữ liệu có cấu trúc ở một trong các định dạng được hỗ trợ (JSON-LD hoặc Vi dữ liệu) vào head
của email để xác định nhà hàng và thêm OneClickAction. Gmail hỗ trợ OneClickAction
và cho người dùng thấy một giao diện người dùng cụ thể để họ có thể xác nhận việc đăng ký ngay trong hộp thư đến.
Sao chép mã đánh dấu sau đây vào một tệp có tên là 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>
Vi dữ liệu
<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>
Dữ liệu có cấu trúc ở trên mô tả một danh sách gửi thư có tên là "XYZ" và một ConfirmAction
. Trình xử lý cho thao tác này là một HttpActionHandler
gửi yêu cầu POST đến URL được chỉ định trong thuộc tính url
.
Gửi yêu cầu đăng ký cho người dùng
Sao chép mã sau vào một tệp có tên emailsender.py
trong thư mục dự án 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)
Lớp EmailSender
yêu cầu người dùng phải đăng nhập để có thể truy xuất địa chỉ email của họ. Sau đó, hàm này tải nội dung email từ mail_template.html
, thay thế phần giữ chỗ confirm_url
trong nội dung đó bằng URL gốc của ứng dụng App Engine (https://APP-ID.appspot.com
) và gửi email cho người dùng hiện đang đăng nhập dưới tên của chính họ.
Thu thập và liệt kê các gói thuê bao
Sao chép mã sau vào một tệp có tên subscribe.py
trong thư mục dự án 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)
Tham số 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` tương ứng với người dùng, như trong ví dụ sau:
https://subscribe.appspot.com/?user_id=123abcd
Trình xử lý yêu cầu chỉ cần kiểm tra xem user_id bắt buộc đã được xác định hay chưa, sau đó lưu trữ gói thuê bao trong Datastore. Điều này dẫn đến việc mã phản hồi HTTP 200
được gửi lại cho Gmail để báo hiệu yêu cầu thành công. Trong trường hợp yêu cầu không có trường bắt buộc, trình xử lý yêu cầu sẽ trả về mã phản hồi HTTP 400
, báo hiệu yêu cầu không hợp lệ.
Các yêu cầu GET
đối với URL gốc của ứng dụng được dùng để liệt kê những gói thuê bao đã được thu thập. Trước tiên, trình xử lý yêu cầu sẽ tìm nạp tất cả các lượt đăng ký từ Datastore rồi in chúng trên trang, cùng với một bộ đếm đơn giản.
Kiểm thử ứng dụng
Triển khai ứng dụng của bạn lên App Engine và truy cập vào https://APP-ID.appspot.com/email
(thay thế APP-ID
bằng mã ứng dụng App Engine của bạn) để gửi email có chú thích cho chính mình.
Sau khi bạn triển khai ứng dụng và chèn một số gói thuê bao, hãy truy cập vào ứng dụng của bạn tại https://APP-ID.appspot.com
để xem trang tóm tắt các gói thuê bao