Index Ai Academy
Phase 0 · ToolsTalking to APIs

Sending email and text messages

About 40 minLooking ahead: some prerequisites aren't done yet

Why this matters

Programs that tell people things are some of the most useful you can write: an order shipped, a price dropped, rain is forecast for Saturday's hike. Email and text messages are how those messages reach people. They're also easy to get badly wrong: the wrong name in a thousand emails, or a password pasted into code that ends up online. This lesson teaches the code and the care.

  • Build an email with EmailMessage, including an HTML version and an attachment
  • Send it with smtplib: connect, starttls, log in with an app password, send
  • Fill a message template for many people with string.Template, without sending anyone the wrong thing
  • Send a text message through an API, with the keys kept out of your code

An email is a message object

Python's email package builds messages and smtplib sends them. Start with EmailMessage: set its headers like dictionary keys, then its body:

from email.message import EmailMessage

msg = EmailMessage()
msg["From"] = "Trail Club <club@shop.example.com>"
msg["To"] = "ada@example.com"
msg["Subject"] = "Your order has shipped"
msg.set_content("Hi Ada,\n\nYour Ridgeline tent is on its way. It should arrive by Friday.\n\nThe shop team")

print(msg["Subject"])
print(msg.as_string()[:300])

as_string() shows the message as it travels: headers first, a blank line, then the body. The headers have to look exactly like this, which is why you let EmailMessage write them rather than gluing strings together yourself.

This lesson uses example.com addresses. That domain is reserved for examples, so it can never reach a real person by accident.

Sending: the practice outbox

To send, a program connects to a mail server with SMTP, the protocol mail servers speak. The steps are always the same:

import os
import smtplib
from email.message import EmailMessage

PASSWORD = os.environ.get("SMTP_PASSWORD", "practice-app-password")

msg = EmailMessage()
msg["From"] = "club@shop.example.com"
msg["To"] = "ada@example.com"
msg["Subject"] = "Your order has shipped"
msg.set_content("Your Ridgeline tent is on its way.")

with smtplib.SMTP("smtp.example.com", 587) as server:
    server.starttls()
    server.login("club@shop.example.com", PASSWORD)
    server.send_message(msg)
print("sent")
  1. Connect to the server on port 587.
  2. starttls() switches the connection to encryption, so the password isn't sent as plain text. (smtplib.SMTP_SSL(host, 465) is encrypted from the start instead.)
  3. Log in. Mail providers like Gmail and Outlook don't accept your normal password from a program. You create an app password in your account's security settings: a separate password that can only send mail, and that you can cancel at any time.
  4. Send, then the with block closes the connection.

The academy can't send real email, so here smtplib is swapped for a practice outbox. It checks the same steps, and the message appears under the output instead of in someone's inbox. Try deleting the starttls() line: the practice server refuses the password, just as a real one would.