Sending Email with Flask

Sending Email with Flask

Yuri Andropov was once beset with negative thoughts concerning the postal service.

The appeal of microframework is the directness of the code written. As opposed to a classic MVC Framework which automatically creates a project folder with several files to be customized before the project is up and running, a microframework can easily exist as a single file.

Using the microframework Flask to automatically sending an email after a triggered event occurs on the website can illustrate the benefits of this approach. Whenever a user signs up to the website or commenting on an article, Flask automatically generates an email to website’s administrator.

By leveraging Flask and plugging in Flask-mail into the framework, creating a web service to automatically send emails can be completed in a nine steps. In this tutorial I also use Flask-WTF to create a very basic form as well as Flask-Script to do a quick verification that things are installed correctly.


1)   Create a virtualenv

This creates a separate environment for your code that isolates all your code from another instance.

virtualenv factotum
cd factotum
source bin/activate
The first command creates the virtual environment. The second command moves you into the project's folder. The third command activates the virutal environment



2)    Installing Flask, Flask-mail, and Flask-WTF

pip install flask
pip install flask-mail
pip install Flask-WTF
pip install flask-script
flask is the web framework. flask-mail is a programming that enables flask to send emails. Flask-WTF enables form creation in Flask. For this exercise, Flask-WTF will be used to trigger flask-mail to send emails


3)    Create a basic Flask application

Within the factotum folder place a file to initialize the Flask application. For example:

factotum/factotum.py

from flask import Flask

app = Flask(__name__)
 

if __name__ == '__main__':
    app.run(debug=True)

 

4)   Add configuration for Flask-mail and Flask-WTF

Add the following to the iniitialization file to set the necessary settings for Flask-mail. The example will use a gmail account to work with Flask-mail.

factotum/factotum.py

import os
from flask import Flask, render_template, redirect
from flask.ext.mail import Mail, Message
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField


app = Flask(__name__)

app.config['MAIL_SERVER'] = 'smtp.googlemail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')
app.config['DEFAULT_MAIL_SUBJECT'] = '[Politburo Voting Results]'
app.config['DEFAULT_MAIL_SENDER'] = 'Admin <admin@example.com>'
app.config['SECRET_KEY'] = 'random_string'
app.config['DEFAULT_ADMIN'] = 'Admin <admin@example.com>'

mail = Mail(app)


class PolitburoForm(Form):
    name = StringField('Who is your favorite member of the Politburo circa 1980?')
    submit = SubmitField('Submit')

if __name__ == '__main__':
    app.run(debug=True)
All the components required for Flask-WTF and Flask-mail are imported. Next the configuration settings are set for the email. Lastly, class NameForm creates the form to enter a name.


5)    Run things from the shell

In order to verify that everything is setup correctly to send email as well as to better grasp how flask-mail works, an email will be sent from the shell.

export MAIL_USERNAME=user@gmail.com
export MAIL_PASSWORD=userpwd
python manage.py shell

>>>from flask.ext.mail import Message
>>>from app.__init__ import mail
>>>msg = Message('test subject', sender='user@gmail.com',
>>>recipients=['user@gmail.com'])
>>>msg.body = 'text body'
>>>msg.html = '<b>HTML</b> body'
>>>with app.app_context():
mail.send(msg)

6)    Create template to hold form

Now that things are working, a template to house the form can now be created.
Since the only function is to retrieve a name from the user, a single template with only the orm will work as the only page on the site.

templates/index.html

<h1>The Presidium</h1>

<form method="POST" action="/">
    {{ form.csrf_token }}
    {{ form.name.label }} {{ form.name(size=20) }}
    <input type="submit" value="Submit">
</form>


7)    Create send_email function

This is the function that will be used to trigger the email. Add this to
factotum/factotum.py

import os
from flask import Flask, render_template, redirect
from flask.ext.script import Shell
from flask.ext.mail import Mail, Message
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField


app = Flask(__name__)

app.config['MAIL_SERVER'] = 'smtp.googlemail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')
app.config['DEFAULT_MAIL_SUBJECT'] = '[Politburo Voting Results]'
app.config['DEFAULT_MAIL_SENDER'] = 'Admin <admin@example.com>'
app.config['SECRET_KEY'] = 'random_string'
app.config['DEFAULT_ADMIN'] = 'Admin <hypnopompicindex@gmail.com>'

mail = Mail(app)


class PolitburoForm(Form):
    name = StringField('Who is your favorite member of the Politburo circa 1980?')
    submit = SubmitField('Submit')


def send_email(to, subject, template, **kwargs):
    msg = Message(app.config['DEFAULT_MAIL_SUBJECT'] + ' ' + subject,
        sender=app.config['DEFAULT_MAIL_SENDER'], recipients=[to])
    msg.html = render_template(template + '.html', **kwargs)
    mail.send(msg)


if __name__ == '__main__':
    app.run(debug=True)
send_email creates a message & sends the email to the recipient.


8) Create template to handle emails

templates/mail/new_user.html

<b>{{ user.username }}</b> is the first among equals in the Politburo
These will be used to hold the email sent to the recipient


9)    Create send_mail function

send_mail will be invoked by clicking on the following form:

import os
from flask import Flask, render_template, redirect
from flask.ext.script import Shell
from flask.ext.mail import Mail, Message
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField


app = Flask(__name__)

app.config['MAIL_SERVER'] = 'smtp.googlemail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')
app.config['DEFAULT_MAIL_SUBJECT'] = '[Politburo Voting Results]'
app.config['DEFAULT_MAIL_SENDER'] = 'Admin <admin@example.com>'
app.config['SECRET_KEY'] = 'random_string'
app.config['DEFAULT_ADMIN'] = 'Admin <hypnopompicindex@gmail.com>'

mail = Mail(app)


class PolitburoForm(Form):
    name = StringField('Who is your favorite member of the Politburo circa 1980?')
    submit = SubmitField('Submit')


def send_email(to, subject, template, **kwargs):
    msg = Message(app.config['DEFAULT_MAIL_SUBJECT'] + ' ' + subject,
        sender=app.config['DEFAULT_MAIL_SENDER'], recipients=[to])
    msg.html = render_template(template + '.html', **kwargs)
    mail.send(msg)


@app.route('/', methods=('GET', 'POST'))
def submit():
    form = PolitburoForm()
    if form.validate_on_submit():
        name = form.name.data
        send_email(app.config['DEFAULT_ADMIN'], 'Button clicked', 'mail/favorite', name=name)
        return redirect('/')
    return render_template('index.html', form=form)


if __name__ == '__main__':
    app.run(debug=True)
The submit function will use the send_email function to send an email to the recipient and then return to the only page on the website.

Given enough time, the program will put an end to the long-standing debate of who is the most talented Politburo member in the eyes of the people.

Comments

Comments are closed.