Sending Email (Flask-Mail)

Sending email means building a message with a subject, recipients, and a body, then handing it to an SMTP server that delivers it to the inbox.

Learn Sending Email (Flask-Mail) in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Flask course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll build real email payloads with Python's standard library, add HTML bodies and attachments, send one from a route, and see the Flask-Mail equivalent.

Every email is just structured data: a subject , a from address, one or more recipients , and a body . Flask-Mail's Message object holds exactly these fields. Under the hood it's the same structure as Python's standard-library EmailMessage , which we can build and inspect runnably.

The example below assembles a welcome email and prints its headers and body — this is precisely the payload that would be handed to an SMTP server.

The printout shows the subject, the from/to pair, and the body — the four pieces every message needs before it can be sent.

Real product emails are formatted. You send an HTML version for clients that render it and keep a plain-text version as a fallback. Technically this is a multipart/alternative message holding a text/plain and a text/html part.

The runnable example sets the plain body with set_content and adds the HTML with add_alternative , then prints the resulting multipart structure to prove both parts are present.

The common case is sending mail in response to a user action — a contact form, a password reset, an order confirmation. You read the form data, build the message, and send it. The runnable example does all of that against an in-memory "outbox" so you can see it work end to end, and even shows an attachment.

Complete the message below. Replace each ___ to set the recipient and the body.

Your MAIL_USERNAME / MAIL_PASSWORD are wrong, or the provider needs an app-specific password. For Gmail you must create an app password — your normal login won't work over SMTP.

You called mail.send() outside a request or app context (for example in a background thread). Wrap it in with app.app_context(): so Flask-Mail can read your config.

Build personalized newsletters for a list of subscribers.

Lesson complete — your app can reach the inbox!

You built real email payloads with subject, from, recipients, and body, added HTML with a text fallback and an attachment, sent one from a route, and saw the Flask-Mail API.

🚀 Up next: Logging & Monitoring — see what your app is doing in production.

Practice quiz

Which extension is commonly used to send email from Flask?

  • Flask-Mailer
  • Flask-Mail
  • Flask-SMTP
  • Flask-Inbox

Answer: Flask-Mail. Flask-Mail provides the Mail object and Message class for sending email.

What protocol delivers email between mail servers?

  • SMTP
  • HTTP
  • FTP
  • IMAP-send

Answer: SMTP. SMTP (Simple Mail Transfer Protocol) accepts and relays outgoing mail.

How do you create a message in Flask-Mail?

  • Mail(subject, ...)
  • Email(subject, ...)

Message(subject, recipients=[...]) builds the email; mail.send delivers it.

Which method actually delivers a Flask-Mail message?

  • msg.deliver()
  • msg.post()
  • Mail.dispatch(msg)
  • mail.send(msg)

Answer: mail.send(msg). mail.send(msg) hands the message to the configured SMTP server.

Which config key sets the SMTP host for Flask-Mail?

  • MAIL_SERVER
  • MAIL_HOST
  • SMTP_SERVER
  • MAIL_URL

Answer: MAIL_SERVER. MAIL_SERVER names the SMTP host, e.g. smtp.gmail.com.

How do you set the rich HTML body on a Flask-Mail Message?

  • msg.render = ...
  • msg.html = '<p>...</p>'
  • msg.content_html(...)
  • msg.set_html(...)

Answer: msg.html = '<p>...</p>'. msg.html holds the HTML version; msg.body holds the plain-text fallback.

Which Message attribute holds the plain-text fallback?

  • msg.text
  • msg.plain
  • msg.body
  • msg.content

Answer: msg.body. msg.body is the plain-text version shown by clients that do not render HTML.

How do you attach a file to a Flask-Mail message?

  • msg.file(name, data)
  • msg.add_file(data)
  • msg.append(name, data)
  • msg.attach(name, content_type, data)

Answer: msg.attach(name, content_type, data). msg.attach(filename, content_type, data) adds the file's bytes to the message.

Which port is typically used for SMTP over TLS?

  • 587
  • 21
  • 8080
  • 3306

Answer: 587. Port 587 is standard for SMTP with TLS (465 for SSL).

Why enqueue email as a background task for bulk sending?

  • SMTP is free only in background
  • email cannot run in a route
  • an SMTP send can take seconds and block the request
  • Flask-Mail requires Celery

Answer: an SMTP send can take seconds and block the request. Slow SMTP round-trips block the request; a worker lets the response return immediately.