Skip to content

Flask - Mail

Sending emails is a common requirement for web applications, used for notifications, password resets, confirmations, newsletters, and more. The Flask-Mail extension simplifies integrating email sending capabilities into your Flask application by providing an interface to SMTP (Simple Mail Transfer Protocol) servers.

First, install the Flask-Mail extension:

pip install Flask-Mail

Next, you need to configure Flask-Mail with the details of the SMTP server you want to use. This is done by setting specific configuration variables on your Flask app object.

Sr.NoConfiguration KeyDescription
1MAIL_SERVERHostname or IP address of the SMTP email server (e.g., ‘smtp.googlemail.com’).
2MAIL_PORTPort number of the SMTP server (e.g., 587 for TLS, 465 for SSL).
3MAIL_USE_TLSBoolean. Set to True to enable Transport Layer Security (TLS). Usually used with port 587.
4MAIL_USE_SSLBoolean. Set to True to enable Secure Sockets Layer (SSL). Usually used with port 465. Note: MAIL_USE_TLS and MAIL_USE_SSL are mutually exclusive.
5MAIL_USERNAMEYour email account username for authentication.
6MAIL_PASSWORDYour email account password or app-specific password.
7MAIL_DEFAULT_SENDEROptional. A default email address to use as the sender if not specified when creating a message. Can be a string ‘Sender Name email@example.com’ or just ‘email@example.com’.
8MAIL_DEBUGBoolean. If True, prints detailed SMTP debugging information. Defaults to app.debug.
9MAIL_MAX_EMAILSOptional. Maximum number of emails to send in one connection. Default is usually None (unlimited).
10MAIL_SUPPRESS_SENDBoolean. If True (often set during testing, e.g., if app.testing is True), emails are suppressed instead of being sent.
11MAIL_ASCII_ATTACHMENTSBoolean. If True, converts attachment filenames to ASCII.

Security Note: Never hardcode sensitive credentials like MAIL_PASSWORD directly in your source code. Use environment variables or a secure configuration management system.

Flask-Mail provides two main classes:

This class manages the connection to the mail server and the sending process. You typically initialize it once with your Flask app.

from flask_mail import Mail
mail = Mail(app) # Pass your Flask app object

Key Methods of Mail class:

Sr.NoMethodDescription
1send(message)Sends a single Message object.
2send_message(...)A shortcut to create and send a simple message in one call (less flexible than creating a Message object).
3connect()Opens a connection to the mail host (often handled automatically by send).

This class represents a single email message, encapsulating its components like subject, recipients, sender, body, etc.

from flask_mail import Message
msg = Message(
subject="Hello from Flask-Mail!",
sender="you@example.com", # Or use MAIL_DEFAULT_SENDER
recipients=["recipient1@example.com", "recipient2@example.com"],
body="This is the plain text body.",
html="**This is the HTML body**" # Optional HTML version
# cc=[...], bcc=[...], reply_to=..., etc.
)

Key Parameters for Message constructor:

  • subject: The email subject line.
  • recipients: A list of recipient email addresses.
  • body: The plain text content of the email.
  • html: Optional. The HTML content of the email.
  • sender: The sender’s email address. Defaults to MAIL_DEFAULT_SENDER if set.
  • cc: List of CC recipients.
  • bcc: List of BCC recipients.
  • attachments: List of attachments (see below).
  • reply_to: Optional reply-to address.
  • attach(filename, content_type, data, disposition=None, headers=None): Adds an attachment to the message. You provide the filename, MIME type (e.g., ‘image/png’), and the raw file data.
  • add_recipient(recipient): Adds another recipient to the list.

Example: Sending a simple email using Gmail

Section titled “Example: Sending a simple email using Gmail”

Important Note on Gmail: Google has increased security measures. Using your regular Gmail password with MAIL_PASSWORD might not work and is discouraged. You typically need to enable 2-Step Verification for your Google account and then generate an “App Password” specifically for Flask-Mail. Use this App Password as your MAIL_PASSWORD. Alternatively, consider using transactional email services like SendGrid, Mailgun, or AWS SES, which are designed for application email sending.

Here’s the full example code (app.py):

import os
from flask import Flask
from flask_mail import Mail, Message
app = Flask(__name__)
# --- Configuration ---
# Load credentials securely from environment variables
# Example using os.environ.get('VARIABLE_NAME', 'default_value')
app.config['MAIL_SERVER'] = os.environ.get('MAIL_SERVER', 'smtp.googlemail.com')
app.config['MAIL_PORT'] = int(os.environ.get('MAIL_PORT', 587))
app.config['MAIL_USE_TLS'] = os.environ.get('MAIL_USE_TLS', 'true').lower() == 'true'
app.config['MAIL_USE_SSL'] = os.environ.get('MAIL_USE_SSL', 'false').lower() == 'true'
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') # Your Gmail address or App Username
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') # Your Gmail App Password
app.config['MAIL_DEFAULT_SENDER'] = os.environ.get('MAIL_DEFAULT_SENDER', app.config['MAIL_USERNAME'])
# Check if essential config is missing (optional but good practice)
if not app.config['MAIL_USERNAME'] or not app.config['MAIL_PASSWORD']:
print("Warning: MAIL_USERNAME or MAIL_PASSWORD environment variables not set.")
# Handle this case appropriately, maybe disable mail sending
# --- Initialize Mail ---
mail = Mail(app)
# --- Route to Send Email ---
@app.route("/")
def index():
# Check if mail sending is configured before trying
if not app.config['MAIL_USERNAME'] or not app.config['MAIL_PASSWORD']:
return "Mail configuration missing. Cannot send email.", 500
try:
# Create the message
msg = Message(
subject='Hello From Flask-Mail',
# Sender uses MAIL_DEFAULT_SENDER if configured, else MAIL_USERNAME
# sender=app.config['MAIL_DEFAULT_SENDER'] or app.config['MAIL_USERNAME'],
recipients=['recipient@example.com'] # Replace with a valid recipient
)
msg.body = "This is a test email sent from a Flask application using Flask-Mail."
msg.html = "**This is a test email** sent from a <i>Flask application</i> using Flask-Mail."
# Example: Adding an attachment (optional)
# with app.open_resource("static/some_image.png") as fp:
# msg.attach("logo.png", "image/png", fp.read())
# Send the message
mail.send(msg)
return "Email sent successfully!"
except Exception as e:
# Log the error for debugging
app.logger.error(f"Mail sending failed: {e}")
return f"Failed to send email: {e}", 500
if __name__ == '__main__':
# Set environment variables before running for testing:
# export MAIL_USERNAME='your_email@gmail.com'
# export MAIL_PASSWORD='your_app_password'
# export MAIL_DEFAULT_SENDER='Friendly Name <your_email@gmail.com>'
app.run(debug=True)

Before running:

  • Replace 'recipient@example.com' with an actual email address you can check.
  • Set the environment variables MAIL_USERNAME and MAIL_PASSWORD (and optionally others) in your terminal before running the script (see comments in the code).
  • Ensure you are using an App Password if using Gmail with 2-Step Verification.

Run the script (python app.py) and visit http://localhost:5000/. This will trigger the index function, attempt to create and send the email using the configured settings, and display a success or failure message.

Development Tip: During development, you might not want to send real emails. Consider using Python’s built-in debugging SMTP server (python -m smtpd -c DebuggingServer -n localhost:1025) and configure Flask-Mail to use localhost and port 1025 with no authentication. Emails will be printed to the console instead of being sent. Alternatively, use tools like MailHog or Mailtrap.