مثال على الخدمة الشاملة

توضح هذه المقالة كيفية إنشاء تطبيق App Engine في لغة بايثون والذي يُرسل رسائل إلكترونية تتضمن تعليقات توضيحية إلى المستخدمين يطلبون تأكيد اشتراكهم في القائمة البريدية مباشرةً من البريد الوارد ويجمع الاشتراكات في Datastore.

المتطلبات الأساسية وإعداد المشروع

يفترض هذا الدليل أنك ثبّت App Engine SDK وتعرف كيفية إنشاء مشاريع 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 أو بيانات جزئية) إلى 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="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>

تصف البيانات المنظَّمة أعلاه قائمة بريدية اسمها "XYZ" وConfirmAction. معالج الإجراء هو HttpActionHandler الذي يرسل طلبات POST إلى عنوان URL المحدّد في السمة url.

إرسال طلبات الاشتراك إلى المستخدمين

انسخ الرمز التالي في ملف باسم 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 بعنوان 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)

مَعلمة 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` التي تقابل المستخدم، كما في المثال التالي:

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

يتحقق معالج الطلب ببساطة من تحديد user_id المطلوب، ثم يخزِّن الاشتراك في مخزن البيانات. ويؤدي ذلك إلى إرسال رمز الاستجابة HTTP 200 إلى Gmail مرة أخرى للإشارة إلى الطلب الناجح. وفي حال عدم اشتمال الطلب على الحقل المطلوب، سيعرض معالج الطلب رمز الاستجابة HTTP 400، ما يشير إلى أنّ الطلب غير صالح.

يتم استخدام طلبات GET المُرسَلة إلى عنوان URL الجذر للتطبيق لإدراج الاشتراكات التي تم جمعها. يجلب معالج الطلب أولاً جميع الاشتراكات من مخزن البيانات ثم يطبعها في الصفحة مع عدّاد بسيط.

اختبار التطبيق

انشر تطبيقك في App Engine وانتقل إلى https://APP-ID.appspot.com/email (استبدِل APP-ID بمعرّف تطبيق App Engine) لإرسال الرسالة الإلكترونية التي تحتوي على تعليقات توضيحية إلى نفسك.

الإجراءات في Gmail

بعد نشر التطبيق وإدراج بعض الاشتراكات، يمكنك الانتقال إلى تطبيقك على https://APP-ID.appspot.com للحصول على صفحة تلخص الاشتراكات.