Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
Python ✦ Beginner ⏱ 30 minutes

💌 Send Automated Emails with Python

Automate your email workflow with Python. You'll use the built-in smtplib library to send plain text emails, styled HTML emails, and emails with file attachments — all without installing anything extra.

🎯 What You’ll Build

A Python script that sends a professional HTML email from your Gmail account — with a subject line, formatted body, and an attached PDF or image. Ready to plug into any automation pipeline.

📋 What You’ll Need

Email automation powers everything from welcome emails to weekly reports to alert systems. Python's smtplib is built-in — no pip install needed. Let's go.

1

Enable Gmail App Password

Gmail requires an App Password instead of your regular password when using SMTP. Here's how to set it up:

  1. Go to your Google Account → Security
  2. Enable 2-Step Verification (required)
  3. Go back to Security → search "App passwords"
  4. Select app: Mail, device: Other (name it "Python")
  5. Click Generate — copy the 16-character password
🔒 Keep it safe: Treat this App Password like your real password. Don't commit it to GitHub. Store it in an environment variable or a .env file.
2

Send your first plain text email

Create email_sender.py. Here's the minimum working email script:

import smtplib
from email.mime.text import MIMEText

SENDER = 'your.email@gmail.com'
PASSWORD = 'your-app-password'
RECIPIENT = 'recipient@example.com'

msg = MIMEText('Hello! This email was sent by Python.')
msg['Subject'] = 'Test from Python 🌟'
msg['From'] = SENDER
msg['To'] = RECIPIENT

with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login(SENDER, PASSWORD)
server.send_message(msg)
print('Email sent!')

Run this with python email_sender.py. Check your inbox — it should arrive within seconds.

3

Send a styled HTML email

Plain text works, but HTML emails look professional. Use MIMEMultipart to send both versions (email clients pick the best one):

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

msg = MIMEMultipart('alternative')
msg['Subject'] = 'Weekly Report 📊'
msg['From'] = SENDER
msg['To'] = RECIPIENT

plain = 'Your weekly report is ready.'
html = '''<html><body>
<h2 style="color:#162447">Weekly Report 📊</h2>
<p>Here is your summary for this week:</p>
<ul><li>Tasks completed: <strong>12</strong></li>
<li>Emails sent: <strong>47</strong></li></ul>
<a href="https://example.com" style="background:#F59C0D;color:#fff;padding:10px 20px;border-radius:6px;text-decoration:none">View Full Report</a>
</body></html>'''


msg.attach(MIMEText(plain, 'plain'))
msg.attach(MIMEText(html, 'html'))

The 'alternative' type tells email clients to show the HTML version if they support it, or fall back to plain text.

4

Add a file attachment

Send a file along with the email using MIMEBase:

from email.mime.base import MIMEBase
from email import encoders
import os

filename = 'report.pdf'
with open(filename, 'rb') as f:
part = MIMEBase('application', 'octet-stream')
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename={os.path.basename(filename)}')
msg.attach(part)
💡 Any file works: Change the filename to a .csv, .xlsx, .png or any other file type. The octet-stream MIME type works for everything.
5

Send to multiple recipients

Loop through a list of recipients to send personalised bulk emails:

recipients = [
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com'),
]

with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login(SENDER, PASSWORD)
for name, email in recipients:
msg['To'] = email
msg.replace_header('Subject', f'Hi {name}, your report is ready')
server.send_message(msg)
print(f'Sent to {name}')
Output
Sent to Alice
Sent to Bob
6

Store credentials safely with environment variables

Never hardcode passwords in your script. Use environment variables instead:

import os

SENDER = os.environ['EMAIL_SENDER']
PASSWORD = os.environ['EMAIL_PASSWORD']

Set them in your terminal before running:

# Windows (PowerShell)
$env:EMAIL_SENDER = "your@gmail.com"
$env:EMAIL_PASSWORD = "your-app-password"

# Mac/Linux
export EMAIL_SENDER="your@gmail.com"
export EMAIL_PASSWORD="your-app-password"
🔒 Even better: Use a .env file with the python-dotenv library (pip install python-dotenv) to load variables automatically.
7

Schedule emails to run automatically

Use Python's schedule library to send emails on a timer:

import schedule, time

def send_daily_report():
print('Sending daily report...')
# put your email code here

schedule.every().day.at('08:00').do(send_daily_report)

while True:
schedule.run_pending()
time.sleep(60)

Install it first: pip install schedule. Run the script and it will send your email automatically at 8am every day while it's running.

🎉

You did it!

You can now send plain text emails, styled HTML emails, file attachments, and bulk personalised emails — all from Python. This is the foundation of automated reports, alert systems, and marketing tools.

🚀 Take It Further

← All Tutorials

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.