Z tego artykułu dowiesz się, jak utworzyć w języku Python aplikację App Engine, która wysyła do użytkowników e-maile z adnotacjami z prośbą o potwierdzenie subskrypcji listy mailingowej bezpośrednio ze skrzynki odbiorczej i zbiera subskrypcje w Datastore.
Wymagania wstępne i konfigurowanie projektu
W tym przewodniku zakładamy, że masz już zainstalowany pakiet SDK App Engine i wiesz, jak tworzyć, uruchamiać i publikować projekty App Engine.
Najpierw utwórz katalog projektu. Umieść w tym katalogu wszystkie pliki aplikacji.
Skopiuj ten kod do pliku o nazwie app.yaml i zastąp symbol zastępczy {{ APPID }} unikalnym identyfikatorem aplikacji App Engine:
application: {{ APPID }}
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
Utwórz plik o nazwie main.py w folderze projektu App Engine i skopiuj do niego ten kod, aby skonfigurować moduły obsługi zbierania i wyświetlania subskrypcji oraz wysyłania e-maili z adnotacjami:
import webapp2
from emailsender import EmailSender
from subscribe import SubscribeHandler
app = webapp2.WSGIApplication([('/', SubscribeHandler), ('/email', EmailSender)], debug=True)
Dodawanie uporządkowanych danych do e-maila
Zacznijmy od bardzo prostego e-maila z prośbą o potwierdzenie subskrypcji listy mailingowej:
<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>
Możesz dodać uporządkowane dane w jednym z obsługiwanych formatów (JSON-LD lub mikrodane) do elementu head e-maila, aby zdefiniować restaurację i dodać OneClickAction. Gmail obsługuje OneClickAction i wyświetla użytkownikom specjalny interfejs, który umożliwia im potwierdzenie subskrypcji ze skrzynki odbiorczej.
Skopiuj ten kod do pliku o nazwie 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>
Mikrodane
<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>
Powyższe dane strukturalne opisują listę adresową o nazwie „XYZ” i ConfirmAction. Obsługa działania to HttpActionHandler, która wysyła żądania POST na adres URL określony we właściwości url.
Wysyłanie próśb o subskrypcję do użytkowników
Skopiuj ten kod do pliku o nazwie emailsender.py w folderze projektu 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)
Klasa EmailSender wymaga zalogowania się użytkownika, aby można było pobrać jego adres e-mail. Następnie wczytuje treść e-maila z mail_template.html, zastępuje w niej symbol zastępczy confirm_url adresem URL aplikacji App Engine (https://APP-ID.appspot.com) i wysyła e-maila do aktualnie zalogowanego użytkownika jako on sam.
Zbieranie i wyświetlanie subskrypcji
Skopiuj ten kod do pliku o nazwie subscribe.py w folderze projektu 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)
Parametr 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` odpowiadający użytkownikowi, jak w tym przykładzie:
https://subscribe.appspot.com/?user_id=123abcd
Obsługa żądania sprawdza tylko, czy zdefiniowano wymagany identyfikator użytkownika, a następnie zapisuje subskrypcję w Datastore. W ten sposób do Gmaila zostanie wysłany kod odpowiedzi HTTP 200, który sygnalizuje, że żądanie zostało zrealizowane. Jeśli żądanie nie zawiera wymaganego pola, moduł obsługujący żądanie zwróci kod odpowiedzi HTTP 400, sygnalizując nieprawidłowe żądanie.
GET żądania wysyłane do głównego adresu URL aplikacji służą do wyświetlania zebranych subskrypcji. Obsługa żądań najpierw pobiera wszystkie subskrypcje z Datastore, a następnie wyświetla je na stronie wraz z prostym licznikiem.
Testowanie aplikacji
Wdróż aplikację w App Engine i otwórz stronę https://APP-ID.appspot.com/email (zastąp APP-ID identyfikatorem aplikacji App Engine), aby wysłać do siebie e-maila z adnotacjami.

Po wdrożeniu aplikacji i dodaniu subskrypcji otwórz ją pod adresem https://APP-ID.appspot.com, aby wyświetlić stronę z podsumowaniem subskrypcji.