Bài viết này hướng dẫn 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 của họ và thu thập các gói thuê bao 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 SDK App Engine và biết cách tạo, chạy và phát hành 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ả tệp cho ứng dụng của bạn vào thư mục này.
Sao chép mã sau vào 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 main.py
trong thư mục dự án App Engine và sao chép mã sau để thiết lập trình xử lý thu thập và liệt kê các gói thuê bao 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 Microdata) vào head
của email để xác định nhà hàng và thêm OneClickAction. Gmail hỗ trợ OneClickAction
và hiển thị một giao diện người dùng cụ thể cho phép người dùng xác nhận gói thuê bao trong hộp thư đến.
Sao chép mã đánh dấu sau vào tệp có tên 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à HttpActionHandler
, gửi các 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 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 đó, ứng dụng này sẽ tải nội dung email từ mail_template.html
, thay thế phần giữ chỗ confirm_url
trong đó bằng URL gốc của ứng dụng App Engine (https://APP-ID.appspot.com
) và gửi email đến người dùng hiện đã đăng nhập dưới vai trò chính họ.
Thu thập và liệt kê gói thuê bao
Sao chép mã sau vào 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 để đảm bảo rằng user_id bắt buộc được xác định, 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 bao gồm trường bắt buộc, trình xử lý yêu cầu sẽ trả về mã phản hồi HTTP 400
, cho biết yêu cầu không hợp lệ.
Các yêu cầu GET
đến URL gốc của ứng dụng được dùng để liệt kê các 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 gói thuê bao từ Kho dữ liệu, sau đó in các gói thuê bao đó trong 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 rồi 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 bạn.
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