How to Send Emails Using Python ?

Introduction

Sending emails from Python can be done in multiple ways:

  • Using Python’s built-in smtplib library
  • Using high-level packages like yagmail
  • Using APIs (SendGrid, Mailgun) for large-scale or no personal email

This tutorial covers all these approaches with examples.

2. Using smtplib (Built-in Python Library)

2.1 Simple Text Email

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import smtplib

sender_email = "your_email@example.com"
receiver_email = "recipient@example.com"
password = "your_password"  # Or App Password if 2FA enabled
subject = "Hello from Python"
body = "This is a test email sent from Python!"

message = f"Subject: {subject}\n\n{body}"

with smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls()  # Secure connection
    server.login(sender_email, password)
    server.sendmail(sender_email, receiver_email, message)

print("Email sent successfully!")

Notes:

  • For Gmail: SMTP server = smtp.gmail.com, port 587
  • Use App Passwords if you have 2FA

2.2 Email with Attachments

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

sender_email = "your_email@example.com"
receiver_email = "recipient@example.com"
password = "your_password"

msg = MIMEMultipart()
msg["From"] = sender_email
msg["To"] = receiver_email
msg["Subject"] = "Email with Attachment"

msg.attach(MIMEText("Hello! Here is your attachment.", "plain"))

filename = "example.pdf"
with open(filename, "rb") as f:
    attach = MIMEApplication(f.read(), _subtype="pdf")
    attach.add_header('Content-Disposition', 'attachment', filename=filename)
    msg.attach(attach)

with smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls()
    server.login(sender_email, password)
    server.sendmail(sender_email, receiver_email, msg.as_string())

print("Email with attachment sent!")

3. Using yagmail (Simpler and Cleaner)

3.1 Installation

1
pip install yagmail

3.2 Store Gmail Password Securely

1
2
3
import yagmail

yagmail.register('your_email@gmail.com', 'your_app_password')

3.3 Send a Simple Email

1
2
3
4
5
6
7
8
import yagmail

sender_email = "your_email@gmail.com"
receiver_email = "recipient@example.com"

yag = yagmail.SMTP(sender_email)
yag.send(to=receiver_email, subject="Hello!", contents="This is a test email with yagmail.")
print("Email sent successfully!")

3.4 Email with Attachments

1
2
3
4
yag.send(to="recipient@example.com",
         subject="Report",
         contents="Please find the attached report.",
         attachments=["example.pdf"])

3.5 Sending to Multiple Recipients Dynamically

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
emails = [
    {"to": "alice@example.com", "subject": "Hello Alice", "body": "Hi Alice!"},
    {"to": "bob@example.com", "subject": "Hello Bob", "body": "Hi Bob!", "attachments": ["report.pdf"]}
]

yag = yagmail.SMTP("your_email@gmail.com")

for email in emails:
    yag.send(to=email["to"], subject=email["subject"], contents=email["body"], attachments=email.get("attachments"))
    print(f"Email sent to {email['to']}")

3.6 Reading Emails from a CSV

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import pandas as pd

df = pd.read_csv("emails.csv")
yag = yagmail.SMTP("your_email@gmail.com")

for _, row in df.iterrows():
    to = row["to"]
    subject = row["subject"]
    body = row["body"]
    attachments = row.get("attachments", None)
    if pd.notna(attachments) and attachments.strip() != "":
        attachments = [att.strip() for att in attachments.split(";")]
    else:
        attachments = None
    yag.send(to=to, subject=subject, contents=body, attachments=attachments)
    print(f"Email sent to {to}")

CSV Format Example:

1
2
3
to,subject,body,attachments
alice@example.com,Hello Alice,"Hi Alice, this is your message!",
bob@example.com,Hello Bob,"Hi Bob, here is your update!","report.pdf"

3.7 Sending HTML Emails

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
html_content = """
<html>
  <body>
    <h1 style="color:blue;">Hello!</h1>
    <p>This is an <b>HTML email</b> sent from Python.</p>
  </body>
</html>
"""

yag.send(to="recipient@example.com", subject="HTML Email", contents=html_content)

4. Using Email APIs (Optional, No Personal Email Needed)

For large-scale or automated emails without using your own Gmail:

  • SendGrid
  • Mailgun
  • Amazon SES

SendGrid Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import requests

api_key = "YOUR_SENDGRID_API_KEY"
url = "https://api.sendgrid.com/v3/mail/send"

data = {
    "personalizations": [{"to": [{"email": "recipient@example.com"}]}],
    "from": {"email": "no-reply@mydomain.com"},
    "subject": "Hello from Python",
    "content": [{"type": "text/plain", "value": "This is a test email."}]
}

response = requests.post(url, json=data, headers={
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json"
})
print(response.status_code, response.text)

5. Security Tips

  • Never hardcode passwords. Use yagmail.register() or environment variables.
  • For Gmail, always use App Passwords if 2FA is enabled.
  • Avoid sending sensitive info over email.

6. Summary

  • smtplib: Built-in, low-level, requires manual setup.
  • yagmail: High-level, clean, supports attachments, HTML, and CSV automation.
  • APIs: Best for large-scale or senderless solutions.

This gives you a full toolkit to send emails using Python, from simple to advanced automated scenarios.

References

Links Site
Python smtplib — SMTP protocol client Official Python 3 documentation for the smtplib module. ([Python documentation][1])
yagmail Documentation Official documentation for the yagmail library. ([yagmail.readthedocs.io][2])
SendGrid v3 API Reference Official API reference for SendGrid’s v3 Email API. ([Twilio][3])