Sanic: Sanic have any interface to send email asynchronously?

Created on 16 Feb 2017  ·  9Comments  ·  Source: sanic-org/sanic

How should I use the smtplib library or other to send email's asynchronously with sanic?

Most helpful comment

Looks like there's an async implementation of smtplib that you can use send emails asynchronously: https://github.com/cole/aiosmtplib

All 9 comments

Looks like there's an async implementation of smtplib that you can use send emails asynchronously: https://github.com/cole/aiosmtplib

you can use celery, a task queue.
something like this in flask:

# a celery task: send async email
@celery.task(default_retry_delay=30)
def send_async_email(msg):
    with app.app_context():
        """send async email in application context"""
        mail.send(msg)

@neo1218 does celery work with asyncio?

Depending on your needs, you might not need a separate task runner like Celery with Sanic, since the asyncio event loop intelligently handles dispatching tasks without blocking the web application. You typically need a task runner with Flask because email sending would block the web application from serving other requests.

Just keep everything async and you should be fine :)

Awesome I think this question has been answered sufficiently. Will re-open if necessary.

aiosmtplib seems to be the easiest/best choice for that.

I have done the job of sending email asynchronously by aiosmtplib+apscheduler:

import asyncio
import aiosmtplib
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from email.mime.text import MIMEText
from sanic.response import json

@app.post('/sendemail')
async def send_email(request):
    scheduler = AsyncIOScheduler()
    scheduler.add_job(_send_email,args=[request])
    scheduler.start()  #run one-off job, so the client not need to wait
    return json({"success": True})

async def _send_email(request):
    new_obj = request.json

    #Thanks: https://github.com/cole/aiosmtplib/issues/1
    host = os.environ.get('MAIL_SERVER_HOST')
    port = os.environ.get('MAIL_SERVER_PORT')
    user = os.environ.get('MAIL_SERVER_USER')
    password = os.environ.get('MAIL_SERVER_PASSWORD')

    loop = asyncio.get_event_loop()

    server = aiosmtplib.SMTP(host, port, loop=loop, use_tls=False)
    await server.connect()

    await server.starttls()
    await server.login(user, password)

    async def send_a_message():
        message = MIMEText(new_obj.get('body'))
        message['From'] = get_env('MAIL_SERVER_USER')
        message['To'] = ','.join(new_obj.get('email_to'))
        message['Subject'] = new_obj.get('subject')
        await server.send_message(message)

    await send_a_message()

You can test the code just like this:

#!/bin/bash
DATA='{"body":"testfrompy3","email_to":["[email protected]"],"subject":"test"}'
curl http://dserver:9901/sendemail -X POST -H "Content-Type: application/json" -H "Accept: text/html,application/json" -d ${DATA}

you can use celery, a task queue.
something like this in flask:

# a celery task: send async email
@celery.task(default_retry_delay=30)
def send_async_email(msg):
    with app.app_context():
        """send async email in application context"""
        mail.send(msg)

how to get the app_context in celery?

@oubeichen I am not sure app_context is. That is not a sanic construct that I am familiar with, and not something you would need to integrate celery with sanic. I do this without any sort of context. In fact, celery tends to work best if you pass simple data structures to the queue and not objects.

On a different note, it would be best to bring up questions like this on our community forums where it will be easier for everyone to find and share. We're trying to keep help questions organized and centralized. If you need more help on potential ways you can implement a task queue, I would be happy to help. Just jump over to the forums and start a new thread there.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mobdim picture mobdim  ·  4Comments

graingert picture graingert  ·  3Comments

misakar picture misakar  ·  4Comments

fiecato picture fiecato  ·  3Comments

jasonab picture jasonab  ·  3Comments