Last active
November 13, 2017 09:01
-
-
Save dmendiza/fcde693de4f88a8547965f8622f78149 to your computer and use it in GitHub Desktop.
Sending Mail Asynchronously
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@app.route('/signup', methods=['GET', 'POST']) | |
def signup(): | |
error = None | |
if request.method == 'POST': | |
email = request.form['email'] | |
password = request.form['password'] | |
if not (email or password): | |
return signup_error('Email Address and Password are required.') | |
db = get_db() | |
c = db.cursor() | |
c.execute('SELECT * FROM users WHERE email=?;', (email,)) | |
if c.fetchone(): | |
return signup_error('Email Addres already has an account.') | |
c.execute('INSERT INTO users (email, password) VALUES (?, ?);', | |
(email, pbkdf2_sha256.hash(password))) | |
db.commit() | |
send_welcome_email(email) | |
flash('Account Created') | |
return redirect(url_for('login')) | |
else: | |
return render_template('signup.html') | |
def send_welcome_email(address): | |
res = requests.post( | |
"https://api.mailgun.net/v3/{}/messages".format(app.config['DOMAIN']), | |
auth=("api", MAILGUN_API_KEY), | |
data={"from": "Flaskr <noreply@{}>".format(app.config['DOMAIN']), | |
"to": [address], | |
"subject": "Welcome to Flaskr!", | |
"text": "Welcome to Flaskr, your account is now active!"} | |
) | |
if res.status_code != 200: | |
# Something terrible happened :-( | |
raise MailgunError("{}-{}".format(res.status_code, res.reason)) | |
def signup_error(error): | |
return render_template('signup.html', error=error) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def connect_queue(): | |
if not hasattr(g, 'rabbitmq'): | |
g.rabbitmq = pika.BlockingConnection( | |
pika.ConnectionParameters(app.config['RABBITMQ_HOST']) | |
) | |
return g.rabbitmq | |
def get_welcome_queue(): | |
if not hasattr(g, 'welcome_queue'): | |
conn = connect_queue() | |
channel = conn.channel() | |
channel.queue_declare(queue='welcome_queue', durable=True) | |
channel.queue_bind(exchange='amq.direct', queue='welcome_queue') | |
g.welcome_queue = channel | |
return g.welcome_queue | |
@app.teardown_appcontext | |
def close_queue(error) | |
if hasattr(g, 'rabbitmq'): | |
g.rabbitmq.close() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@app.route('/signup', methods=['GET', 'POST']) | |
def signup(): | |
error = None | |
if request.method == 'POST': | |
email = request.form['email'] | |
password = request.form['password'] | |
if not (email or password): | |
return signup_error('Email Address and Password are required.') | |
db = get_db() | |
c = db.cursor() | |
c.execute('SELECT * FROM users WHERE email=?;', (email,)) | |
if c.fetchone(): | |
return signup_error('Email Addres already has an account.') | |
c.execute('INSERT INTO users (email, password) VALUES (?, ?);', | |
(email, pbkdf2_sha256.hash(password))) | |
db.commit() | |
q = get_welcome_queue() | |
q.basic_publish( | |
exchange='amq.direct', | |
routing_key='welcome_queue', | |
body=email, | |
properties=pika.BasicProperties( | |
delivery_mode=_DELIVERY_MODE_PERSISTENT | |
) | |
) | |
flash('Account Created') | |
return redirect(url_for('login')) | |
else: | |
return render_template('signup.html') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pika | |
import requests | |
# Configuration | |
DOMAIN = 'example.com' | |
MAILGUN_API_KEY = 'YOUR_MAILGUN_API_KEY' | |
RABBITMQ_HOST = 'localhost' | |
connection = pika.BlockingConnection( | |
pika.ConnectionParameters(host=RABBITMQ_HOST) | |
) | |
channel = connection.channel() | |
channel.queue_declare(queue='welcome_queue', durable=True) | |
class Error(Exception): | |
pass | |
class MailgunError(Error): | |
def __init__(self, message): | |
self.message = message | |
def send_welcome_message(ch, method, properties, body): | |
address = body.decode('UTF-8') | |
print("Sending welcome email to {}".format(address)) | |
res = requests.post( | |
"https://api.mailgun.net/v3/{}/messages".format(DOMAIN), | |
auth=("api", MAILGUN_API_KEY), | |
data={"from": "Flaskr <noreply@{}>".format(DOMAIN), | |
"to": [address], | |
"subject": "Welcome to Flaskr!", | |
"text": "Welcome to Flaskr, your account is now active!"} | |
) | |
ch.basic_ack(delivery_tag=method.delivery_tag) | |
if res.status_code != 200: | |
# Something terrible happened :-O | |
raise MailgunError("{}-{}".format(res.status_code, res.reason)) | |
channel.basic_consume(send_welcome_message, queue='welcome_queue') | |
channel.start_consuming() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
retry_channel = connection.channel() | |
retry_channel.queue_declare( | |
queue='retry_queue', | |
durable=True, | |
arguments={ | |
'x-message-ttl': RETRY_DELAY_MS, | |
'x-dead-letter-exchange': 'amq.direct', | |
'x-dead-letter-routing-key': 'welcome_queue' | |
} | |
) | |
def send_welcome_message(ch, method, properties, body): | |
address = body.decode('UTF-8') | |
print("Sending welcome email to {}".format(address)) | |
res = requests.post( | |
"https://api.mailgun.net/v3/{}/messages".format(DOMAIN), | |
auth=("api", MAILGUN_API_KEY), | |
data={"from": "Flaskr <noreply@{}>".format(DOMAIN), | |
"to": [address], | |
"subject": "Welcome to Flaskr!", | |
"text": "Welcome to Flaskr, your account is now active!"} | |
) | |
ch.basic_ack(delivery_tag=method.delivery_tag) | |
if res.status_code != 200: | |
print("Error sending to {}. {} {}. Retrying...".format( | |
address, res.status_code, res.reason | |
)) | |
retry_channel.basic_publish( | |
exchange='', | |
routing_key='retry_queue', | |
body=address, | |
properties=pika.BasicProperties( | |
delivery_mode=_DELIVERY_MODE_PERSISTENT | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment