2026-07-15

Failing to send email with the Python example

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

Failing to send email with the Python example

Decoding SMTP Failures: Troubleshooting Email Sending in Python

I've been trying (and failing) to figure out how to send email via Python. The process of setting up secure connections using smtplib often feels like navigating a minefield of protocol versions, ports, and SSL handshake errors. If you’ve encountered frustrating timeouts or cryptic SSLError messages while trying to connect to services like Gmail or other SMTP servers, you are certainly not alone. As senior developers, we know that the issue is rarely just the code; it’s usually a mismatch between the client's expectation and the server's security requirements.

This post will break down the common pitfalls in using Python’s smtplib for secure email transmission and provide a robust strategy for resolving these connection failures.

The Anatomy of an SMTP Connection Error

When sending mail, we rely on the Simple Mail Transfer Protocol (SMTP), which must be secured using Transport Layer Security (TLS/SSL). The confusion often arises from two main methods: implicit SSL (port 465) and explicit TLS (port 587).

The errors you encountered—such as [Errno 10060] A connection attempt failed or SSLError: unknown protocol—indicate that the initial handshake between your Python script and the SMTP server is failing before any actual email data can be sent. This usually points to one of three core problems:

  1. Protocol Mismatch: Trying to use an SSL method (like SMTP_SSL) on a port that expects a plain connection, or vice versa.
  2. Port Misconfiguration: Using the wrong port for the specific security level required by the mail server.
  3. Authentication Block: The most common modern blocker—the server rejects the login attempt because it doesn't recognize the credentials or the security context (e.g., if you are using an old password instead of an App Password).

Best Practices for Secure Python Email Sending

For reliable email delivery, we need to be explicit about the connection method. While SMTP_SSL attempts to establish SSL immediately upon connection, explicitly initiating the TLS negotiation via starttls() is often more robust when dealing with modern SMTP setups.

Here is a refined structure for connecting securely:

Explicit TLS Connection (Port 587)

The standard and most recommended approach for secure connections today is using port 587, which uses the STARTTLS command to upgrade an unencrypted connection into an encrypted one. This gives you more control over the negotiation process.

import smtplib

mailuser = 'MYEMAIL@gmail.com'
mailpasswd = 'YOUR_APP_PASSWORD' # Use App Passwords for security!
fromaddr = 'MYEMAIL@gmail.com'
toaddrs = 'MYEMAIL2@gmail.com'
msg = 'Hooooorah!'

try:
    # 1. Connect using standard SMTP (unencrypted)
    server = smtplib.SMTP("smtp.google.com", 587)
    
    # 2. Secure the connection using STARTTLS
    server.starttls() 
    
    # 3. Log in
    server.login(mailuser, mailpasswd)
    
    # 4. Send the email
    server.sendmail(fromaddr, toaddrs, msg)
    
    print("Email sent successfully!")

except smtplib.SMTPAuthenticationError:
    print("Authentication failed. Check your username and password/App Password.")
except smtplib.SMTPServerDisconnected:
    print("Server disconnected unexpectedly.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
finally:
    if 'server' in locals() and server:
        server.quit()

Why This Approach Works Better

By using smtplib.SMTP() first, we establish a basic TCP connection to port 587. Then, the crucial step is calling server.starttls(). This command tells the server, "I am ready to switch from plain text communication to an encrypted TLS session." This explicit negotiation often bypasses the obscure SSL initialization errors you encountered with SMTP_SSL in some environments, leading to a more stable connection, regardless of minor protocol variations on the server side.

Conclusion: Security Over Simplicity

Troubleshooting network and security protocols is a core skill for any developer. When dealing with external services like email providers, always default to best practices: use explicit TLS negotiation (starttls()) over relying solely on implicit SSL methods if you encounter handshake errors. Furthermore, remember that the biggest hurdle in modern email sending isn't the Python code itself, but rather adhering to the security policies of the mail provider—always prioritize using secure authentication methods like App Passwords instead of standard account passwords. Just as robust application design is essential when building complex systems on platforms like Laravel, reliable communication protocols are the bedrock of any successful software architecture.

Tags:

Enhance your marketing setup with your own email marketing platform.

Join the growing number of SaaS platforms using Laravel Mail to offer email marketing solutions to their customers.