Mail API untuk Python 3

Halaman ini menjelaskan cara menggunakan Mail API, salah satu layanan paket versi lama, dengan runtime Python 3 untuk lingkungan standar. Aplikasi Anda dapat mengakses layanan yang dipaketkan melalui SDK layanan App Engine untuk Python 3.

Ringkasan

Di Python 3, fungsi penanganan email disertakan dalam modul google.appengine.api.mail. Ini berbeda dengan Python 2, dengan modul mail_handlers disediakan oleh webapp. Mail API untuk Python 3 dapat digunakan untuk menerima email dan notifikasi pantulan.

Menggunakan Mail API

Aplikasi Anda menerima email saat email dikirim sebagai isi permintaan dalam permintaan HTTP POST. Agar aplikasi dapat menangani email masuk, aplikasi harus mencocokkan URL dengan jalur /_ah/mail/[ADDRESS]. Bagian [ADDRESS] jalur biasanya adalah alamat email dengan akhiran @<Cloud-Project-ID>.appspotmail.com. Email yang dikirim ke aplikasi dalam format ini akan dirutekan ke fungsi.

Python 3 tidak mengharuskan aplikasi untuk menentukan skrip pengendali dalam file app.yaml, sehingga Anda dapat menghapus semua bagian handler di app.yaml.

File app.yaml Anda harus menyimpan baris berikut:

inbound_services:
- mail
- mail_bounce

Mengirim email

Anda tidak perlu mengubah konfigurasi aplikasi saat mengupgrade ke Python 3. Perilaku, fitur, dan petunjuk penyiapan untuk mengirim email tetap sama. Lihat panduan berikut untuk detail selengkapnya:

Menerima email

Untuk menerima email, Anda harus mengimpor modul google.appengine.api.mail dan menggunakan class InboundEmailMessage untuk mewakili email. Class ini perlu dibuat instance-nya untuk mengambil konten email dari permintaan HTTP yang masuk.

Sebelumnya di Python 2, aplikasi dapat mengakses class InboundEmailMessage dengan mengganti metode receive() di pengendali aplikasi web InboundEmailHandler. Hal ini tidak diperlukan di Python 3; sebagai gantinya, aplikasi perlu membuat instance objek baru.

Framework web

Saat menggunakan framework web Python, konstruktor InboundEmailMessage menggunakan byte isi permintaan HTTP. Ada beberapa cara untuk membuat objek InboundEmailMessage di Python 3. Berikut adalah contoh untuk aplikasi Flask dan Djago:

Python 3 (Flask)

Di Flask, request.get_data() memberikan byte permintaan.

@app.route("/_ah/bounce", methods=["POST"])
def receive_bounce():
    bounce_message = mail.BounceNotification(dict(request.form.lists()))

    # Do something with the message
    print("Bounce original: ", bounce_message.original)
    print("Bounce notification: ", bounce_message.notification)

    return "OK", 200

Python 3 (Django)

Di Django, request.body memberikan byte isi permintaan HTTP.

def receive_mail(request):
    message = mail.InboundEmailMessage(request.body)

    print(f"Received greeting for {message.to} at {message.date} from {message.sender}")
    for _, payload in message.bodies("text/plain"):
        print(f"Text/plain body: {payload.decode()}")
        break

    return HttpResponse("OK")

Untuk melihat contoh kode lengkap dari panduan ini, lihat GitHub.

Framework lain yang mematuhi WSGI

Untuk framework lainnya yang mematuhi WSGI, sebaiknya gunakan metode yang sama seperti contoh Flask dan Django untuk membuat InboundEmailMessage. Metode ini berfungsi saat byte isi permintaan HTTP tersedia secara langsung.

Aplikasi WSGI tanpa framework web

Jika aplikasi Anda adalah aplikasi WSGI yang tidak menggunakan framework web, ada kemungkinan bahwa byte isi permintaan HTTP tidak langsung tersedia. Jika byte isi permintaan HTTP tersedia secara langsung, sebaiknya gunakan framework web Python.

Dalam Python 3, metode factory bernama from_environ ditentukan untuk InboundEmailMessage. Metode ini adalah metode class yang menggunakan kamus environ WSGI sebagai input, dan dapat digunakan untuk aplikasi WSGI apa pun.

Pada contoh berikut, perhatikan bagaimana environ diambil sebagai input untuk mendapatkan mail_message:

Python 3 (aplikasi WSGI)

def HelloReceiver(environ, start_response):
    if environ["REQUEST_METHOD"] != "POST":
        return ("", http.HTTPStatus.METHOD_NOT_ALLOWED, [("Allow", "POST")])

    message = mail.InboundEmailMessage.from_environ(environ)

    print(f"Received greeting for {message.to} at {message.date} from {message.sender}")
    for content_type, payload in message.bodies("text/plain"):
        print(f"Text/plain body: {payload.decode()}")
        break

    response = http.HTTPStatus.OK
    start_response(f"{response.value} {response.phrase}", [])
    return ["success".encode("utf-8")]

Menerima notifikasi email tidak terkirim

Notifikasi pantulan adalah pesan otomatis dari sistem email yang menunjukkan masalah pada pengiriman pesan aplikasi Anda. Untuk memproses notifikasi memantul, aplikasi Anda harus mencocokkan jalur URL yang masuk dengan jalur /_ah/bounce.

Seperti InboundEmailMessage, class BounceNotification untuk Python 2 dapat diakses dengan mengganti metode receive() di BounceNotificationHandler pengendali webapp.

Di Python 3, aplikasi perlu membuat instance objek BounceNotification yang dapat dibuat dengan beberapa cara, bergantung pada framework web Python yang digunakan.

Framework web

Objek BounceNotification diinisialisasi dengan nilai yang diambil dengan memanggil post_vars.get(key).

Saat menggunakan framework web Python, seperti Flask atau Django, konstruktor BounceNotification menggunakan kamus bernama post_vars, yang berisi permintaan POST dari data formulir. Untuk mengambil data, metode get() harus ditentukan pada objek input. key adalah daftar nilai input yang dapat dibaca dan diambil oleh BounceNotification, serta dapat berupa salah satu dari berikut ini:

original-to, original-cc, original-bcc, original-subject, original-text, notification-from, notification-to, notification-cc, notification-bcc, notification-subject, notification-text, raw-message

Di sebagian besar framework web, data ini tersedia sebagai multi-kamus di objek permintaan. Sebagian besar jenis ini dapat dikonversi menjadi kamus yang dikunci oleh string.

Untuk semua kunci kecuali raw-message, nilainya dapat berupa apa pun. Biasanya, nilainya berupa nilai tunggal seperti string, atau daftar nilai, seperti {'to': ['bob@example.com', 'alice@example.com']}. Nilai default untuk semua kolom adalah string kosong. Nilai ini akan mengisi properti original dan notification.

Untuk kunci raw-message, nilainya harus berupa input yang valid bagi konstruktor EmailMessage. Nilai dapat berupa nilai tunggal atau daftar bernilai tunggal. Kunci raw-message digunakan untuk menginisialisasi properti original_raw_message objek.

Python 2 (webapp2)

class LogBounceHandler(BounceNotificationHandler):
    def receive(self, bounce_message):
        logging.info('Received bounce post ... [%s]', self.request)
        logging.info('Bounce original: %s', bounce_message.original)
        logging.info('Bounce notification: %s', bounce_message.notification)

Python 3 (Flask)

Di Flask, request.form dari jenis werkzeug.datastructures.MultiDict memberikan variabel POST. Namun, metode get() untuk jenis ini hanya menampilkan nilai, meskipun ada beberapa nilai untuk kunci.

Untuk mendapatkan semua nilai yang terkait dengan sebuah kunci, aplikasi harus memanggil dict(request.form.lists()), yang menghasilkan kamus dengan setiap nilai berupa daftar.

@app.route("/_ah/bounce", methods=["POST"])
def receive_bounce():
    bounce_message = mail.BounceNotification(dict(request.form.lists()))

    # Do something with the message
    print("Bounce original: ", bounce_message.original)
    print("Bounce notification: ", bounce_message.notification)

    return "OK", 200

Python 3 (Django)

Di Django, request.POST dari jenis django.http.QueryDict memberikan variabel POST. Namun, metode get() untuk jenis ini hanya menampilkan nilai, meskipun ada beberapa nilai untuk kunci.

Untuk mendapatkan semua nilai yang terkait dengan sebuah kunci, aplikasi harus memanggil dict(request.POST.lists()) yang menghasilkan kamus dengan setiap nilai berupa daftar.

def receive_bounce(request):
    bounce_message = mail.BounceNotification(dict(request.POST.lists()))

    # Do something with the message
    print(f"Bounce original: {bounce_message.original}")
    print(f"Bounce notification: {bounce_message.notification}")

    return HttpResponse("OK")

Aplikasi WSGI tanpa framework web

Jika aplikasi Anda adalah aplikasi WSGI yang tidak menggunakan framework web, ada kemungkinan variabel bentuk permintaan HTTP POST tidak tersedia secara langsung dalam kamus.

Dalam Python 3, metode factory bernama from_environ ditentukan untuk BounceNotification. Metode ini adalah metode class yang menggunakan kamus environ WSGI sebagai input, dan dapat digunakan untuk aplikasi WSGI apa pun.

Pada contoh berikut, perhatikan bagaimana environ diambil sebagai input untuk mendapatkan bounce_message:

Python 3

def BounceReceiver(environ, start_response):
    if environ["REQUEST_METHOD"] != "POST":
        return ("", http.HTTPStatus.METHOD_NOT_ALLOWED, [("Allow", "POST")])

    bounce_message = mail.BounceNotification.from_environ(environ)

    # Do something with the message
    print("Bounce original: ", bounce_message.original)
    print("Bounce notification: ", bounce_message.notification)

    # Return suitable response
    response = http.HTTPStatus.OK
    start_response(f"{response.value} {response.phrase}", [])
    return ["success".encode("utf-8")]

Contoh kode

Untuk melihat contoh kode lengkap dari panduan ini, lihat GitHub.