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
3.2 Store Gmail Password Securely
| import yagmail
yagmail.register('your_email@gmail.com', 'your_app_password')
|
3.3 Send a Simple Email
| 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
| yag.send(to="recipient@example.com",
subject="Report",
contents="Please find the attached report.",
attachments=["example.pdf"])
|
3.5 Sending to Multiple Recipients Dynamically
| 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:
| 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
| 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