flask-mail

One of the most basic functions in a web application is the ability to send emails to your users.

The Flask-Mail extension provides a simple interface to set up SMTP with your Flask application and to send messages from your views and scripts.

Source code and issue tracking at Bitbucket.

Installing Flask-Mail

Install with pip and easy_install:

pip install Flask-Mail

or download the latest version from Bitbucket:

hg clone http://bitbucket.org/danjac/flask-mail

cd flask-mail

python setup.py install

If you are using virtualenv, it is assumed that you are installing flask-mail in the same virtualenv as your Flask application(s).

Configuring Flask-Mail

Flask-Mail is configured through the standard Flask config API. These are the available options (each is explained later in the documentation):

  • MAIL_SERVER : default ‘localhost’
  • MAIL_PORT : default 25
  • MAIL_USE_TLS : default False
  • MAIL_USE_SSL : default False
  • MAIL_DEBUG : default app.debug
  • MAIL_USERNAME : default None
  • MAIL_PASSWORD : default None
  • DEFAULT_MAIL_SENDER : default None

In addition the standard Flask TESTING configuration option is used by Flask-Nail in unit tests (see below).

Emails are managed through a Mail instance:

from flask import Flask
from flaskext.mail import Mail

app = Flask(__name__)
mail = Mail(app)

Alternatively you can set up your Mail instance later at configuration time, using the init_app method:

mail = Mail()

app = Flask(__name__)
mail.init_app(app)

Sending messages

To send a message first create a Message instance:

from flaskext.mail import Message

@app.route("/")
def index():

    msg = Message("Hello",
                  sender="from@example.com",
                  recipients=["to@example.com"])

You can set the recipient emails immediately, or individually:

msg.recipients = ["you@example.com"]
msg.add_recipient("somebodyelse@example.com")

If you have set DEFAULT_MAIL_SENDER you don’t need to set the message sender explicity, as it will use this configuration value by default:

msg = Message("Hello",
              recipients=["to@example.com"])

If the sender is a two-element tuple, this will be split into name and address:

msg = Message("Hello",
              sender=("Me", "me@example.com"))

assert msg.sender == "Me <me@example.com>"

The message can contain a body and/or HTML:

msg.body = "testing"
msg.html = "<b>testing</b>"

Finally, to send the message, you use the Mail instance configured with your Flask application:

mail.send(msg)

Bulk emails

Usually in a web application you will be sending one or two emails per request. In certain situations you might want to be able to send perhaps dozens or hundreds of emails in a single batch - probably in an external process such as a command-line script or cronjob.

In that case you do things slightly differently:

with mail.connect() as conn:
    for user in users:
        message = '...'
        subject = "hello, %s" % user.name
        msg = Message(recipients=[user.email],
                      body=message,
                      subject=subject)

        conn.send(msg)

The connection to your email host is kept alive and closed automatically once all the messages have been sent.

Attachments

Adding attachments is straightforward:

with app.open_resource("image.png") as fp:
    msg.attach("image.png", "image/png", fp.read())

See the API for details.

Unit tests

When you are sending messages inside of unit tests, or in a development environment, it’s useful to be able to suppress email sending.

If the setting TESTING is set to True, emails will be suppressed. Calling send() on your messages will not result in any messages being sent.

However, it’s still useful to track in your unit tests which emails have been sent.

When TESTING is on, an outbox list is attached to the thread local g object, so you can then inspect what emails are sent (or would be sent in production mode):

assert g.outbox[0].subject == "testing"

Header injection

To prevent header injection attempts to send a message with newlines in the subject, sender or recipient addresses will result in a BadHeaderError.

API

class flaskext.mail.Mail(app=None)

Manages email messaging

Parameters:
  • app – Flask instance
send(message)

Sends a single message instance. If TESTING then will add the message to g.outbox.

Parameters:
  • message – a Message instance.
connect(send_many=True)

Opens a connection to the mail host.

Parameters:
  • send_many – keep connection alive
class flaskext.mail.Connection(mail, testing=False, send_many=False)

Handles connection to host.

send(message)

Sends message.

Parameters:
  • message – Message instance.
class flaskext.mail.Message(subject, recipients=None, body=None, html=None, sender=None)

Encapsulates an email message.

Parameters:
  • subject – email subject header
  • recipients – list of email addresses
  • body – plain text message
  • html – HTML message
  • sender – email sender address, or DEFAULT_MAIL_SENDER by default
attach(filename=None, content_type=None, data=None, disposition=None)

Adds an attachment to the message.

Parameters:
  • filename – filename of attachment
  • content_type – file mimetype
  • data – the raw file data
  • disposition – content-disposition (if any)
add_recipient(recipient)

Adds another recipient to the message.

Parameters:
  • recipient – email address of recipient.