مثال سرتاسر

این سند نشان می‌دهد چگونه در Python برنامه App Engine بسازید که ایمیل‌های حاشیه‌گذاری‌شده را برای کاربرانی که می‌خواهند اشتراک فهرست پستی را مستقیماً از صندوق ورودی‌شان تأیید کنند ارسال می‌کند و اشتراک‌ها را در Datastore جمع‌آوری می‌کند.

پیش‌نیازها و راه‌اندازی پروژه

این راهنما فرض می‌کند که قبلاً کیت توسعه نرم‌افزار App Engine را نصب کرده‌اید و می‌دانید چگونه پروژه‌های App Engine را ایجاد، اجرا، و منتشر کنید.

ابتدا، یک فهرست راهنما برای پروژه‌تان بسازید. همه فایل‌های برنامه‌تان را در این دایرکتوری قرار دهید.

کد زیر را در فایلی به‌نام app.yaml کپی کنید و جای‌بان {{ APPID }} را با شناسه برنامه یکتای App Engine خود جایگزین کنید:

application: {{ APPID }}
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: latest

فایلی به‌نام main.py در پوشه پروژه App Engine خود ایجاد کنید و کد زیر را برای راه‌اندازی کنترل‌کننده‌های جمع‌آوری و فهرست کردن اشتراک‌ها و برای ارسال ایمیل‌های حاشیه‌نویسی‌شده کپی کنید:

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 پشتیبانی می‌کند و عناصر رابط کاربری را نمایش می‌دهد که به کاربران امکان می‌دهد اشتراک خود را از صندوق ورودی‌شان تأیید کنند.

نشانه‌گذاری زیر را در فایلی به‌نام 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>

ریز داده

<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="Confirm Subscription"/>
        <div itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
          <meta itemprop="url" content="{{ confirm_url }}"/>
          <link itemprop="method" href="http://schema.org/HttpRequestMethod/POST"/>
        </div>
      </div>
      <meta itemprop="description" content="Confirm subscription to mailing list XYZ"/>
    </div>
    <p>
      Dear John, please confirm that you wish to be subscribed to the mailing list XYZ.
    </p>
  </body>
</html>

داده‌های ساختاریافته قبلی فهرست پستی به‌نام «XYZ» و ConfirmAction را توصیف می‌کند. گرداننده کنش HttpActionHandler است که درخواست‌های POST را به نشانی وب مشخص‌شده در دارایی url ارسال می‌کند.

مهم: در کد قبلی، قبل‌از ارسال ایمیل، {{ confirm_url }} جای‌بان را با نشانی وب برنامه App Engine خود (مثل https://mailing-list.appspot.com) جایگزین کنید. کد توضیح‌داده‌شده در مراحل زیر این جایگزینی را مدیریت می‌کند.

ارسال درخواست اشتراک به کاربران

کد زیر را در فایلی به‌نام emailsender.py در پوشه پروژه 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)

برای کلاس EmailSender لازم است کاربر به سیستم وارد شود تا نشانی ایمیل او قابل‌بازیابی باشد. سپس، بدنه ایمیل را از mail_template.html بار می‌کند، جای‌بان confirm_url را در آن با نشانی وب ریشه برنامه App Engine (https://APP-ID.appspot.com) جایگزین می‌کند، و ایمیل را به کاربر واردشده به سیستم ارسال می‌کند.

جمع‌آوری و فهرست کردن اشتراک‌ها

کد زیر را در فایلی به‌نام subscribe.py در پوشه پروژه 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)

کلاس SubscribeHandler درخواست‌های POST و GET ارسال‌شده به نشانی وب ریشه برنامه (https://APP-ID.appspot.com) را مدیریت می‌کند. درخواست‌های POST توسط Gmail برای درج اشتراک‌های جدید ازجمله پارامتر user_id که مربوط به کاربر است استفاده می‌شود، مانند مثال زیر:

https://subscribe.appspot.com/?user_id=123abcd

مدیر درخواست بررسی می‌کند که user_id موردنیاز تعریف شده باشد و اشتراک را در Datastore ذخیره می‌کند. این کار کد پاسخ HTTP 200 را به Gmail برمی‌گرداند تا درخواست موفق را نشان دهد. اگر درخواست شامل فیلد الزامی نباشد، مدیر درخواست کد پاسخ HTTP 400 را برمی‌گرداند و درخواست نامعتبر را اعلام می‌کند.

درخواست‌های GET به فهرست نشانی وب ریشه برنامه اشتراک‌هایی را که جمع‌آوری شده‌اند فهرست می‌کند. مدیر درخواست همه اشتراک‌ها را از Datastore واکشی می‌کند و آن‌ها را به‌همراه یک شمارنده در صفحه نمایش می‌دهد.

آزمایش برنامه

برنامه‌تان را در App Engine مستقر کنید و برای ارسال ایمیل حاشیه‌گذاری‌شده به خودتان، به https://APP-ID.appspot.com/email بروید (APP-ID را با شناسه برنامه App Engine خودتان جایگزین کنید).

کنش‌ها در Gmail

پس‌از استقرار برنامه و درج اشتراک‌ها، در https://APP-ID.appspot.com از برنامه‌تان بازدید کنید تا صفحه‌ای را که اشتراک‌ها را خلاصه می‌کند مشاهده کنید.