September 11, 2024

Python Sending Email using SMTP

Sending emails programmatically is a common task in many applications, such as sending notifications, alerts, or newsletters. Python provides the smtplib module to facilitate sending emails using the Simple Mail Transfer Protocol (SMTP). In this guide, we’ll walk you through the steps to send an email using Python’s smtplib and the email module.

1. Prerequisites

  • Python installed on your system.
  • An SMTP server to send emails. Common options include Gmail’s SMTP server, Outlook’s SMTP server, or any other email provider’s SMTP server.
  • Credentials for the SMTP server (email address and password).
Note: Some email providers, like Gmail, require you to enable “Less Secure Apps” or use an App Password to allow SMTP access. Refer to your email provider’s documentation for specific instructions.

2. Importing Necessary Modules

You’ll need to import the following modules:

  • smtplib: To handle the SMTP protocol.
  • email.mime modules: To construct the email content.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

3. Setting Up the SMTP Server

Different email providers have different SMTP server addresses and port numbers. Below are the SMTP settings for some popular email providers:

Email Provider SMTP Server Port Security
Gmail smtp.gmail.com 587 (STARTTLS) or 465 (SSL) STARTTLS or SSL
Outlook smtp.office365.com 587 STARTTLS
Yahoo smtp.mail.yahoo.com 587 STARTTLS
SMTP.com smtp.smtp.com 587 or 465 STARTTLS or SSL

4. Creating the Email Message

Use the MIMEMultipart class to create the email message. This allows you to add multiple parts to your email, such as plain text and HTML content.

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

# Create a multipart message
message = MIMEMultipart("alternative")
message["Subject"] = "Subject of the Email"
message["From"] = sender_email
message["To"] = receiver_email

# Create the plain-text and HTML version of your message
text = """\
Hi there,
This is a test email sent from Python.
Best regards,
Your Name
"""

html = """\

Hi there,
This is a test email sent from Python.
Best regards,
Your Name

 



"""

# Attach parts into message container
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")

message.attach(part1)
message.attach(part2)

5. Sending the Email

Use the smtplib module to connect to the SMTP server and send the email. It’s important to handle the connection securely using SSL or STARTTLS.

5.1 Using STARTTLS

STARTTLS upgrades the connection to a secure encrypted SSL/TLS connection.

try:
    # Connect to the SMTP server
    smtp_server = "smtp.gmail.com"
    port = 587  # For STARTTLS

    server = smtplib.SMTP(smtp_server, port)
    server.ehlo()  # Can be omitted
    server.starttls()  # Secure the connection
    server.ehlo()  # Can be omitted

    # Login to the server
    server.login(sender_email, password)

    # Send the email
    server.sendmail(sender_email, receiver_email, message.as_string())

    print("Email sent successfully!")

except Exception as e:
    print("Error sending email:", e)

finally:
    server.quit()

5.2 Using SSL

SSL creates a secure connection from the start.

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

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

# Create a multipart message
message = MIMEMultipart("alternative")
message["Subject"] = "Subject of the Email"
message["From"] = sender_email
message["To"] = receiver_email

# Create the plain-text and HTML version of your message
text = """\
Hi there,
This is a test email sent from Python.
Best regards,
Your Name
"""

html = """\

Hi there,
This is a test email sent from Python.
Best regards,
Your Name

 



"""

# Attach parts into message container
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")

message.attach(part1)
message.attach(part2)

try:
    # Connect to the SMTP server using SSL
    smtp_server = "smtp.gmail.com"
    port = 465  # For SSL

    with smtplib.SMTP_SSL(smtp_server, port) as server:
        server.login(sender_email, password)
        server.sendmail(sender_email, receiver_email, message.as_string())

    print("Email sent successfully!")

except Exception as e:
    print("Error sending email:", e)

6. Full Example Code

Below is a complete example that sends an email using SMTP with STARTTLS. Replace the placeholder values with your actual email credentials and recipient’s email address.

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

def send_email(sender_email, receiver_email, password, subject, body_text, body_html=None):
    # Create a multipart message
    message = MIMEMultipart("alternative")
    message["Subject"] = subject
    message["From"] = sender_email
    message["To"] = receiver_email

    # Attach the plain text part
    part1 = MIMEText(body_text, "plain")
    message.attach(part1)

    # Attach the HTML part if provided
    if body_html:
        part2 = MIMEText(body_html, "html")
        message.attach(part2)

    try:
        # Connect to the SMTP server
        smtp_server = "smtp.gmail.com"
        port = 587  # For STARTTLS

        server = smtplib.SMTP(smtp_server, port)
        server.ehlo()
        server.starttls()
        server.ehlo()

        # Login to the server
        server.login(sender_email, password)

        # Send the email
        server.sendmail(sender_email, receiver_email, message.as_string())

        print("Email sent successfully!")

    except Exception as e:
        print("Error sending email:", e)

    finally:
        server.quit()

# Usage
sender = "your_email@gmail.com"
recipient = "recipient@example.com"
password = "your_password"  # Consider using environment variables or secure storage
subject = "Test Email from Python"
text = "Hi there,\nThis is a test email sent from Python."
html = """\

Hi there,
This is a test email sent from Python.
Best regards,
Your Name

 



"""

send_email(sender, recipient, password, subject, text, html)

7. Sending Emails with Attachments

To send emails with attachments, you can use the email.mime modules such as MIMEBase and encoders.

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

def send_email_with_attachment(sender_email, receiver_email, password, subject, body, filename):
    # Create a multipart message
    message = MIMEMultipart()
    message["From"] = sender_email
    message["To"] = receiver_email
    message["Subject"] = subject

    # Attach the body with the msg instance
    message.attach(MIMEText(body, "plain"))

    # Open the file to be sent
    with open(filename, "rb") as attachment:
        # Instance of MIMEBase and named as part
        part = MIMEBase("application", "octet-stream")
        part.set_payload(attachment.read())

    # Encode file in ASCII characters to send by email
    encoders.encode_base64(part)

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

    # Attach the attachment to the MIMEMultipart object
    message.attach(part)

    try:
        # Connect to the SMTP server
        smtp_server = "smtp.gmail.com"
        port = 587  # For STARTTLS

        server = smtplib.SMTP(smtp_server, port)
        server.ehlo()
        server.starttls()
        server.ehlo()

        # Login to the server
        server.login(sender_email, password)

        # Convert the message to a string and send it
        server.sendmail(sender_email, receiver_email, message.as_string())

        print("Email with attachment sent successfully!")

    except Exception as e:
        print("Error sending email:", e)

    finally:
        server.quit()

# Usage
sender = "your_email@gmail.com"
recipient = "recipient@example.com"
password = "your_password"
subject = "Test Email with Attachment"
body = "Hi there,\nThis email contains an attachment."
filename = "example.pdf"  # Replace with your file path

send_email_with_attachment(sender, recipient, password, subject, body, filename)

8. Best Practices and Security

  • Do Not Hardcode Credentials: Avoid hardcoding your email password in the script. Instead, use environment variables or a configuration file that’s not checked into version control.
  • Use App Passwords: If your email provider supports it (like Gmail), use app-specific passwords instead of your main account password.
  • Handle Exceptions: Always handle potential exceptions to prevent your application from crashing and to provide meaningful error messages.
  • Limit Access: Ensure that your SMTP credentials have the least privilege necessary. For example, create a separate account for sending automated emails.
  • Secure Connections: Always use secure connections (SSL/TLS) when connecting to the SMTP server to protect your credentials and email content.

9. Using Environment Variables for Credentials

Storing sensitive information like email passwords in environment variables enhances security.

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

def send_secure_email():
    # Retrieve credentials from environment variables
    sender_email = os.getenv("SENDER_EMAIL")
    receiver_email = os.getenv("RECEIVER_EMAIL")
    password = os.getenv("EMAIL_PASSWORD")
    subject = "Secure Email from Python"
    body = "This email is sent securely using environment variables."

    # Create the email message
    message = MIMEMultipart("alternative")
    message["Subject"] = subject
    message["From"] = sender_email
    message["To"] = receiver_email

    # Attach the plain text
    part1 = MIMEText(body, "plain")
    message.attach(part1)

    try:
        smtp_server = "smtp.gmail.com"
        port = 587

        server = smtplib.SMTP(smtp_server, port)
        server.ehlo()
        server.starttls()
        server.ehlo()
        server.login(sender_email, password)
        server.sendmail(sender_email, receiver_email, message.as_string())
        print("Secure email sent successfully!")

    except Exception as e:
        print("Error sending secure email:", e)

    finally:
        server.quit()

# Ensure to set the environment variables before running the script
# Example (Unix):
# export SENDER_EMAIL="your_email@gmail.com"
# export RECEIVER_EMAIL="recipient@example.com"
# export EMAIL_PASSWORD="your_password"

send_secure_email()

10. Conclusion

Sending emails using Python’s smtplib and email modules is a straightforward process that can be integrated into various applications for automated communication. By following best practices and ensuring the security of your credentials, you can efficiently manage email sending tasks within your Python projects.