Python Sending Email
Python: Sending Email using SMTP
Section titled “Python: Sending Email using SMTP”The Simple Mail Transfer Protocol (SMTP) is the standard internet protocol for sending electronic mail (email). Python’s built-in smtplib module provides client-side functionality to connect to an SMTP server and send emails.
To construct email messages robustly (handling headers, different content types, attachments), the standard email.message module is highly recommended over manual string formatting.
Connecting to an SMTP Server
Section titled “Connecting to an SMTP Server”You create an SMTP client session object using smtplib.SMTP or smtplib.SMTP_SSL (for servers requiring an SSL connection from the start). It’s crucial to use encrypted connections (SSL/TLS) whenever possible.
import smtplib
# Option 1: Connect to standard SMTP port, then upgrade to TLS# smtp_server = smtplib.SMTP(host, port)# smtp_server.starttls() # Secure the connection
# Option 2: Connect directly using SSL# smtp_server = smtplib.SMTP_SSL(host, port)
# Example for Gmail (requires App Password if 2FA is enabled)# host = 'smtp.gmail.com'# port = 465 # For SSL# smtp_server = smtplib.SMTP_SSL(host, port)
# Example for local debugging server (no encryption)# python -m smtpd -c DebuggingServer -n localhost:1025# smtp_server = smtplib.SMTP('localhost', 1025)Parameters for SMTP() / SMTP_SSL():
After connecting, you typically need to authenticate:
# smtp_server.login(sender_email, password)Security Note: Avoid hardcoding credentials directly in your script. Use environment variables, configuration files, or secure secret management tools.
Sending a Simple Text Email
Section titled “Sending a Simple Text Email”Use the email.message.EmailMessage class to build the email structure.
import smtplibimport osfrom email.message import EmailMessage
# --- Configuration (Load securely, e.g., from environment variables) ---SMTP_HOST = 'smtp.example.com' # Replace with your SMTP hostSMTP_PORT = 587 # Replace with your SMTP port (TLS)SENDER_EMAIL = 'your_email@example.com' # ReplaceSENDER_PASSWORD = os.environ.get('EMAIL_PASSWORD') # Example: Get from env varRECEIVER_EMAIL = 'recipient@example.com' # Replace# --------------------------------------------------------------------
if not SENDER_PASSWORD: print("Error: Email password not set in environment variable EMAIL_PASSWORD") exit()
# Create the email message objectmsg = EmailMessage()msg['Subject'] = 'Test Email from Python'msg['From'] = SENDER_EMAILmsg['To'] = RECEIVER_EMAILmsg.set_content('This is a plain text email sent using Python.')
try: # Connect, login, and send with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() # Secure the connection (if using port 587) server.login(SENDER_EMAIL, SENDER_PASSWORD) server.send_message(msg) print("Email sent successfully!")
except smtplib.SMTPAuthenticationError: print("Authentication failed. Check email/password or app-specific password setting.")except smtplib.SMTPException as e: print(f"An SMTP error occurred: {e}")except Exception as e: print(f"An error occurred: {e}")Key steps:
Sending an HTML Email
Section titled “Sending an HTML Email”To send HTML content, use msg.add_alternative().
import smtplibimport osfrom email.message import EmailMessage
# --- Configuration (as before) ---SMTP_HOST = 'smtp.example.com'SMTP_PORT = 587SENDER_EMAIL = 'your_email@example.com'SENDER_PASSWORD = os.environ.get('EMAIL_PASSWORD')RECEIVER_EMAIL = 'recipient@example.com'# ----------------------------------
if not SENDER_PASSWORD: print("Error: Email password not set.") exit()
msg = EmailMessage()msg['Subject'] = 'HTML Email Test from Python'msg['From'] = SENDER_EMAILmsg['To'] = RECEIVER_EMAIL
# Set plain text content (fallback for clients that don't support HTML)msg.set_content('This is the plain text version.')
# Add HTML alternativehtml_content = """<html> <body> <p>This is an **HTML** email message.</p> <h1>Headline</h1> <p>Sent using Python's `smtplib` and `email.message` modules.</p> </body></html>"""msg.add_alternative(html_content, subtype='html')
try: with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() server.login(SENDER_EMAIL, SENDER_PASSWORD) server.send_message(msg) print("HTML email sent successfully!")except Exception as e: print(f"An error occurred: {e}")add_alternative() adds a different representation of the same content. Email clients will typically display the richest format they support (HTML in this case). Providing a plain text fallback is good practice.
Sending Email with Attachments
Section titled “Sending Email with Attachments”Use msg.add_attachment() to include files.
import smtplibimport osfrom email.message import EmailMessageimport mimetypes # To guess file type
# --- Configuration (as before) ---SMTP_HOST = 'smtp.example.com'SMTP_PORT = 587SENDER_EMAIL = 'your_email@example.com'SENDER_PASSWORD = os.environ.get('EMAIL_PASSWORD')RECEIVER_EMAIL = 'recipient@example.com'# ----------------------------------
if not SENDER_PASSWORD: print("Error: Email password not set.") exit()
ATTACHMENT_PATH = 'files/document.pdf' # Replace with your file path
if not os.path.exists(ATTACHMENT_PATH): print(f"Error: Attachment file not found at {ATTACHMENT_PATH}") exit()
msg = EmailMessage()msg['Subject'] = 'Email with Attachment from Python'msg['From'] = SENDER_EMAILmsg['To'] = RECEIVER_EMAILmsg.set_content('Please find the attached document.')
# --- Add Attachment ---# Guess the MIME typemime_type, _ = mimetypes.guess_type(ATTACHMENT_PATH)if mime_type is None: # Default to generic binary if type cannot be guessed mime_type = 'application/octet-stream'maintype, subtype = mime_type.split('/', 1)
with open(ATTACHMENT_PATH, 'rb') as fp: msg.add_attachment(fp.read(), maintype=maintype, subtype=subtype, filename=os.path.basename(ATTACHMENT_PATH))# ---------------------
try: with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() server.login(SENDER_EMAIL, SENDER_PASSWORD) server.send_message(msg) print("Email with attachment sent successfully!")except Exception as e: print(f"An error occurred: {e}")Key steps for attachments: