How to send an email with Python?

Learn how to send an email with python? with practical examples, diagrams, and best practices. Covers python, email, function development techniques with visual explanations.

Sending Emails with Python: A Comprehensive Guide

Hero image for How to send an email with Python?

Learn how to send emails programmatically using Python's smtplib and email modules, covering plain text, HTML, and attachments.

Sending emails from your Python applications is a common requirement for various tasks, such as sending notifications, reports, or automated messages. Python provides powerful built-in modules, primarily smtplib for sending emails via an SMTP server and email for constructing email messages, including handling different content types and attachments.

Understanding the Core Modules: smtplib and email

Before diving into code, it's essential to understand the roles of the two main modules involved:

  • smtplib: This module defines an SMTP client session object that can be used to send mail to any Internet machine with an SMTP or ESMTP listener daemon. It handles the communication with the mail server.
  • email: This package is a library for managing email messages. It provides classes for creating, parsing, and modifying email messages, including support for MIME (Multipurpose Internet Mail Extensions) to handle various content types like plain text, HTML, and attachments.
flowchart TD
    A[Python Application] --> B{smtplib.SMTP()}
    B --> C{Connect to SMTP Server}
    C --> D{Login (if required)}
    D --> E{Construct Email (email module)}
    E --> F{Send Email (send_message)}
    F --> G[Recipient's Mailbox]

Basic Email Sending Process Flow in Python

Sending a Simple Plain Text Email

The simplest form of email involves sending plain text. This requires setting up the SMTP connection, logging in (if your server requires authentication), and then sending the message. We'll use smtplib directly for this basic example.

import smtplib

# Email configuration
SENDER_EMAIL = 'your_email@example.com'
SENDER_PASSWORD = 'your_email_password'
RECEIVER_EMAIL = 'recipient@example.com'
SMTP_SERVER = 'smtp.example.com' # e.g., 'smtp.gmail.com'
SMTP_PORT = 587 # or 465 for SSL

# Message content
subject = 'Hello from Python!'
body = 'This is a test email sent from a Python script.'
message = f'Subject: {subject}\n\n{body}'

try:
    # Establish a secure connection (TLS for port 587)
    with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
        server.starttls() # Upgrade the connection to a secure encrypted SSL/TLS connection
        server.login(SENDER_EMAIL, SENDER_PASSWORD)
        server.sendmail(SENDER_EMAIL, RECEIVER_EMAIL, message)
    print('Email sent successfully!')
except Exception as e:
    print(f'Error sending email: {e}')

Python code to send a basic plain text email.

Sending HTML Emails and Attachments with the email Module

For more complex emails, such as those with HTML content or attachments, the email module becomes indispensable. It allows you to construct MIME messages, which can contain multiple parts (e.g., a plain text version, an HTML version, and various attachments).

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

# Email configuration
SENDER_EMAIL = 'your_email@example.com'
SENDER_PASSWORD = 'your_email_password'
RECEIVER_EMAIL = 'recipient@example.com'
SMTP_SERVER = 'smtp.example.com'
SMTP_PORT = 587

# Create a multipart message and set headers
msg = MIMEMultipart()
msg['From'] = SENDER_EMAIL
msg['To'] = RECEIVER_EMAIL
msg['Subject'] = 'HTML Email with Attachment from Python'

# Add body to email
html_body = """
<html>
    <body>
        <p>Hi there,</p>
        <p>This is an <b>HTML email</b> sent from Python!</p>
        <p>It includes an attachment.</p>
    </body>
</html>
"""
msg.attach(MIMEText(html_body, 'html'))

# Attach a file
filename = 'example.txt' # In the same directory as your script
with open(filename, 'w') as f:
    f.write('This is the content of the attached file.')

attachment = open(filename, 'rb') # Open the file in binary mode

# Encode file in base64
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)

# Add header as key/value pair to attachment part
part.add_header('Content-Disposition', f'attachment; filename= {filename}')

msg.attach(part)

try:
    with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
        server.starttls()
        server.login(SENDER_EMAIL, SENDER_PASSWORD)
        server.send_message(msg)
    print('HTML email with attachment sent successfully!')
except Exception as e:
    print(f'Error sending email: {e}')
finally:
    attachment.close() # Close the file handle
    import os
    os.remove(filename) # Clean up the temporary file

Sending an HTML email with a file attachment using the email module.

Best Practices and Security Considerations

When sending emails programmatically, keep the following best practices and security measures in mind:

  1. Use TLS/SSL: Always use starttls() for port 587 or connect directly via SSL for port 465 to encrypt your communication with the SMTP server. This protects your credentials and message content.
  2. Handle Credentials Securely: As mentioned, avoid hardcoding passwords. Use environment variables (e.g., os.environ.get('EMAIL_PASSWORD')), a .env file with python-dotenv, or a dedicated secrets management service.
  3. Error Handling: Implement robust try-except blocks to catch potential smtplib.SMTPException errors, such as authentication failures or connection issues.
  4. Rate Limiting: Be mindful of your SMTP server's sending limits to avoid being flagged as spam or temporarily blocked.
  5. Sender Verification: Ensure your SENDER_EMAIL is a legitimate and verified email address to improve deliverability and avoid spam filters.
  6. MIME Types: When attaching files, use the correct MIME types (application/pdf, image/jpeg, text/plain, etc.) to help email clients render them correctly. The mimetypes module can assist with this.

1. Set up your email account

Ensure your sending email account allows programmatic access. For Gmail, this might involve generating an App Password if 2-Factor Authentication is enabled, or enabling 'Less secure app access' (though App Passwords are more secure).

2. Install necessary libraries (if any)

For basic email sending, smtplib and email are built-in. If you need more advanced features or a higher-level API, consider libraries like yagmail (pip install yagmail).

3. Configure SMTP details

Identify your email provider's SMTP server address (e.g., smtp.gmail.com, smtp.office365.com) and the correct port (usually 587 for TLS or 465 for SSL).

4. Construct your email message

Decide if you need a plain text, HTML, or multipart message with attachments. Use the email.mime classes for complex messages.

5. Establish connection and send

Use smtplib.SMTP() or smtplib.SMTP_SSL(), call starttls() if needed, log in with your credentials, and then use sendmail() or send_message().