Uçtan uca örneği

Bu makalede, Python'da bir App Engine uygulamasının nasıl oluşturulacağı açıklanmaktadır. Bu uygulama, kullanıcılara doğrudan gelen kutularından bir posta listesi aboneliğini onaylamalarını isteyen ek açıklamalı e-postalar gönderir ve abonelikleri Datastore'da toplar.

Ön koşullar ve proje kurulumu

Bu kılavuzda, App Engine SDK'sını daha önce yüklediğiniz ve App Engine projelerini nasıl oluşturacağınızı, çalıştıracağınızı ve yayınlayacağınızı bildiğiniz varsayılmaktadır.

Öncelikle projeniz için bir dizin oluşturun. Uygulamanızla ilgili tüm dosyaları bu dizine yerleştirin.

Aşağıdaki kodu app.yaml adlı bir dosyaya kopyalayın ve {{ APPID }} yer tutucusunu benzersiz App Engine uygulama kimliğinizle değiştirin:

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

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

libraries:
- name: jinja2
  version: latest

App Engine proje klasörünüzde main.py adlı bir dosya oluşturun ve abonelikleri toplama ve listeleme, ayrıca açıklama eklenmiş e-postalar gönderme işleyicilerini ayarlamak için aşağıdaki kodu kopyalayın:

import webapp2

from emailsender import EmailSender
from subscribe import SubscribeHandler

app = webapp2.WSGIApplication([('/', SubscribeHandler), ('/email', EmailSender)], debug=True)

E-postaya yapılandırılmış veri ekleme

Kullanıcıdan bir posta listesi aboneliğini onaylamasını isteyen çok basit bir e-postayla başlayalım:

<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>

Restoranı tanımlamak ve OneClickAction eklemek için e-postanın head bölümüne desteklenen biçimlerden birinde (JSON-LD veya Microdata) yapılandırılmış veri ekleyebilirsiniz. Gmail, OneClickAction özelliğini destekler ve kullanıcılara aboneliklerini gelen kutularından onaylamalarına olanak tanıyan özel bir kullanıcı arayüzü gösterir.

Aşağıdaki işaretlemeyi mail_template.html adlı bir dosyaya kopyalayın:

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>

Mikro veri

<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>

Yukarıdaki yapılandırılmış veriler, "XYZ" adlı bir posta listesini ve ConfirmAction'yı tanımlamaktadır. İşlemin işleyicisi, url özelliğinde belirtilen URL'ye POST istekleri gönderen bir HttpActionHandler'dır.

Kullanıcılara abonelik istekleri gönderme

Aşağıdaki kodu App Engine proje klasöründe emailsender.py adlı bir dosyaya kopyalayın:

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 sınıfı, e-posta adresinin alınabilmesi için kullanıcının oturum açmasını gerektirir. Ardından, e-posta gövdesini mail_template.html konumundan yükler, içindeki confirm_url yer tutucusunu App Engine uygulamasının kök URL'siyle (https://APP-ID.appspot.com) değiştirir ve e-postayı şu anda oturum açmış kullanıcıya kendisi göndermiş gibi gönderir.

Abonelikleri toplama ve listeleme

Aşağıdaki kodu App Engine proje klasöründe subscribe.py adlı bir dosyaya kopyalayın:

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)

Aşağıdaki örnekte gösterildiği gibi, kullanıcıya karşılık gelen 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` parametresi:

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

İstek işleyici, yalnızca gerekli user_id'nin tanımlanıp tanımlanmadığını kontrol eder ve ardından aboneliği Datastore'da saklar. Bu işlem, başarılı isteği belirtmek için Gmail'e HTTP 200 yanıt kodunun geri gönderilmesine neden olur. İstek gerekli alanı içermiyorsa istek işleyici, geçersiz isteği belirten bir HTTP 400 yanıt kodu döndürür.

GET Toplanan abonelikleri listelemek için uygulamanın kök URL'sine yapılan istekler kullanılır. İstek işleyici önce tüm abonelikleri Datastore'dan getirir, ardından bunları sayfada basit bir sayaçla birlikte yazdırır.

Uygulamayı test etme

Uygulamanızı App Engine'e dağıtın ve https://APP-ID.appspot.com/email adresini ziyaret ederek (APP-ID yerine App Engine uygulama kimliğinizi girin) açıklama eklenmiş e-postayı kendinize gönderin.

Gmail&#39;deki işlemler

Uygulamanızı dağıtıp bazı abonelikler ekledikten sonra, abonelikleri özetleyen bir sayfa almak için https://APP-ID.appspot.com adresinden uygulamanızı ziyaret edin.