Email encryption and authentication are modern security techniques that you can use to protect your emails and their content from unauthorized access.
Everyone, from individuals to business owners, uses emails for official communication, which may contain sensitive information. Therefore, securing emails is important, especially when cyberattacks like phishing, smishing, etc. are soaring high.
In this article, I'll discuss how to send emails in Python securely using email encryption and authentication.
Setting Up Your Python Environment
Before you start creating the code for sending emails, set up your Python environment first with the configurations and libraries you'll need.
You can send emails in Python using:
Simple Mail Transfer Protocol (SMTP): This application-level protocol simplifies the process since Python offers an in-built library or module (smtplib) for sending emails. It's suitable for businesses of all sizes as well as individuals to automate secure email sending in Python. We're using the Gmail SMTP service in this article.
An email API: You can leverage a third-party API like Mailtrap Python SDK, SendGrid, Gmail API, etc., to dispatch emails in Python. This method offers more features and high email delivery speeds, although it requires some investment.
In this tutorial, we're opting for the first choice - sending emails in Python using SMTP, facilitated by the smtplib library. This library uses the RFC 821 protocol and interacts with SMTP and mail servers to streamline email dispatch from your applications. Additionally, you should install packages to enable Python email encryption, authentication, and formatting.
Step 1: Install Python
Install the Python programming language on your computer (Windows, macOS, Linux, etc.). You can visit the official Python website and download and install it from there.
If you've already installed it, run this code to verify it:
python --version
Step 2: Install Necessary Modules and Libraries
smtplib: This handles SMTP communications. Use the code below to import 'smtplib' and connect with your email server:
import smtplib
email module: This provides classes (Subject, To, From, etc.) to construct and parse emails. It also facilitates email encoding and decoding with Multipurpose Internet Mail Extensions (MIME).
MIMEText: It's used for formatting your emails and supports sending emails with text and attachments like images, videos, etc. Import this using the code below:
import MIMEText
MIMEMultipart: Use this library to add attachments and text sections separately in your email.
import MIMEMultipart
ssl: It provides Secure Sockets Layer (SSL) encryption.
Step 3: Create a Gmail Account
To send emails using the Gmail SMTP email service, I recommend creating a test account to develop the code. Delete the account once you've tested the code.
The reason is, you'll need to modify the security settings of your Gmail account to enable access from the Python code for sending emails. This might expose the login details, compromising security. In addition, it will flood your account with too many test emails.
So, instead of using your own Gmail account, create a new one for creating and testing the code. Here's how to do this:
Create a fresh Gmail account
Set up your app password:
Google Account > Security > Turn on 2-Step Verification > Security > Set up an App Password
Next, define a name for the app password and click on "Generate". You'll get a 16-digit password after following some instructions on the screen. Store the password safely.
Use this password while sending emails in Python. Here, we're using Gmail SMTP, but if you want to use another mail service provider, follow the same process. Alternatively, contact your company's IT team to seek support in accessing your SMTP server.
Email Authentication With Python
Email authentication is a security mechanism that verifies the sender's identity, ensuring the emails from a domain are legitimate. If you have no email authentication mechanism in place, your emails might land in spam folders, or malicious actors can spoof or intercept them. This could affect your email delivery rates and the sender's reputation.
This is the reason you must enable Python email authentication mechanisms and protocols, such as:
SMTP authentication: If you're sending emails using an SMTP server like Gmail SMTP, you can use this method of authentication. It verifies the sender's authenticity when sending emails via a specific mail server.
SPF: Stands for Sender Policy Framework and checks whether the IP address of the sending server is among
DKIM: Stands for DomainKeys Identified Mail and is used to add a digital signature to emails to ensure no one can alter the email's content while it's in transmission. The receiver's server will then verify the digital signature. Thus, all your emails and their content stay secure and unaltered.
DMARC: Stands for Domain-based Message Authentication, Reporting, and Conformance. DMARC instructs mail servers what to do if an email fails authentication. In addition, it provides reports upon detecting any suspicious activities on your domain.
How to Implement Email Authentication in Python
To authenticate your email in Python using SMTP, the smtplib library is useful. Here's how Python SMTP security works:
import smtplib
server = smtplib.SMTP('smtp.domain1.com', 587)
server.starttls() # Start TLS for secure connection
server.login('
[email protected]', 'my_password')
message = "Subject: Test Email."
server.sendmail('
[email protected]', '
[email protected]', message)
server.quit()
Implementing email authentication will add an additional layer of security to your emails and protect them from attackers or from being marked as spam.
Encrypting Emails With Python
Encrypting emails enables you to protect your email's content so that only authorized senders and receivers can access or view the content. Encrypting emails with Python is done using encryption techniques to encode the email message and transform it into a secure and unreadable format (also known as ciphertext).
This way, email encryption secures the message from unauthorized access or attackers even if they intercept the email.
Here are different types of email encryption:
SSL: This stands for Secure Sockets Layer, one of the most popular and widely used encryption protocols. SSL ensures email confidentiality by encrypting data transmitted between the mail server and the client.
TLS: This stands for Transport Layer Security and is a common email encryption protocol today. Many consider it a great alternative to SSL. It encrypts the connection between an email client and the mail server to prevent anyone from intercepting the email during its transmission.
E2EE: This stands for end-to-end encryption, ensuring only the intended recipient with valid credentials can decrypt the email content and read it. It aims to prevent email interception and secure the message.
How to Implement Email Encryption in Python
If your mail server requires SSL encryption, here's how to send an email in Python:
import smtplib
import ssl
context = ssl.create_default_context()
server = smtplib.SMTP_SSL('smtp.domain1.com', 465, context=context) # This is for SSL connections, requiring port number 465
server.login('
[email protected]', 'my_password')
message = "Subject: SSL Encrypted Email."
server.sendmail('
[email protected]', '
[email protected]', message)
server.quit()
For TLS connections, you'll need the smtplib library:
import smtplib
server = smtplib.SMTP('smtp.domain1.com', 587) # TLS requires 587 port number
server.starttls() # Start TLS encryption
server.login('
[email protected]', 'my_password')
message = "Subject: TLS Encrypted Email."
server.sendmail('
[email protected]', '
[email protected]', message)
server.quit()
For end-to-end encryption, you'll need more advanced libraries or tools such as GnuPG, OpenSSL, Signal Protocol, and more.
Combining Authentication and Encryption
Email Security with Python requires both encryption and authentication. This ensures that mail servers find the email legitimate and it stays safe from cyber attackers and unauthorized access during transmission. For email encryption, you can use either SSL or TLS and combine it with SMTP authentication to establish a robust email connection.
Now that you know how to enable email encryption and authentication in your emails, let's examine some complete code examples to understand how you can send secure emails in Python using Gmail SMTP and email encryption (SSL).
Code Examples
1. Sending a Plain Text Email
import smtplib
from email.mime.text import MIMEText
subject = "Plain Text Email"
body = "This is a plain text email using Gmail SMTP and SSL."
sender = "
[email protected]"
receivers = ["
[email protected]", "
[email protected]"]
password = "my_password"
def send_email(subject, body, sender, receivers, password):
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = ', '.join(receivers)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp_server:
smtp_server.login(sender, password)
smtp_server.sendmail(sender, receivers, msg.as_string())
print("The plain text email is sent successfully!")
send_email(subject, body, sender, receivers, password)
Explanation:
sender: This contains the sender's address.
receivers: This contains email addresses of receiver 1 and receiver 2.
msg: This is the content of the email.
sendmail(): This is the SMTP object's instance method. It takes three parameters - sender, receiver, and msg and sends the message.
with: This is a context manager that is used to properly close an SMTP connection once an email is sent.
MIMEText: This holds only plain text.
2. Sending an Email with Attachments
To send an email in Python with attachments securely, you will need some additional libraries like MIMEBase and encoders. Here's the code for this case:
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
sender = "
[email protected]"
password = "my_password"
receiver = "
[email protected]"
subject = "Email with Attachments"
body = "This is an email with attachments created in Python using Gmail SMTP and SSL."
with open("attachment.txt", "rb") as attachment:
part = MIMEBase("application", "octet-stream") # Adding the attachment to the email
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition", # The header indicates that the file name is an attachment.
f"attachment; filename='attachment.txt'",
)
message = MIMEMultipart()
message['Subject'] = subject
message['From'] = sender
message['To'] = receiver
html_part = MIMEText(body)
message.attach(html_part) # To attach the file
message.attach(part)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login(sender, password)
server.sendmail(sender, receiver, message.as_string())
Explanation:
MIMEMultipart: This library allows you to add text and attachments both to an email separately.
'rb': It represents binary mode for the attachment to be opened and the content to be read.
MIMEBase: This object is applicable to any file type.
Encode and Base64: The file will be encoded in Base64 for safe email sending.
Sending an HTML Email in Python
To send an HTML email in Python using Gmail SMTP, you need a class - MIMEText.
Here's the full code for Python send HTML email:
import smtplib
from email.mime.text import MIMEText
sender = "
[email protected]"
password = "my_password"
receiver = "
[email protected]"
subject = "HTML Email in Python"
body = """
HTML email created in Python with SSL and Gmail SMTP.
"""
message = MIMEText(body, 'html') # To attach the HTML content to the email
message['Subject'] = subject
message['From'] = sender
message['To'] = receiver
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login(sender, password)
server.sendmail(sender, receiver, message.as_string())
Testing Your Email With Authentication and Encryption
Testing your emails before sending them to the recipients is important. It enables you to discover any issues or bugs in sending emails or with the formatting, content, etc.
Thus, always test your emails on a staging server before delivering them to your target recipients, especially when sending emails in bulk. Testing emails provide the following advantages:
Ensures the email sending functionality is working fine
Emails have proper formatting and no broken links or attachments
Prevents flooding the recipient's inbox with a large number of test emails
Enhances email deliverability and reduces spam rates
Ensures the email and its contents stay protected from attacks and unauthorized access
To test this combined setup of sending emails in Python with authentication and encryption enabled, use an email testing server like Mailtrap Email Testing. This will capture all the SMTP traffic from the staging environment, and detect and debug your emails before sending them. It will also analyze the email content, validate CSS/HTML, and provide a spam score so you can improve your email sending.
To get started:
Open Mailtrap Email Testing
Go to 'My Inbox'
Click on 'Show Credentials' to get your test credentials - login and password details
Here's the Full Code Example for Testing Your Emails:
import smtplib
from socket import gaierror
port = 2525 # Define the SMTP server separately
smtp_server = "sandbox.smtp.mailtrap.io"
login = "xyz123" # Paste your Mailtrap login details
password = "abc$$" # Paste your Mailtrap password
sender = "
[email protected]"
receiver = "
[email protected]"
message = f"""\
Subject: Hello There!
To: {receiver}
From: {sender}
This is a test email."""
try:
with smtplib.SMTP(smtp_server, port) as server: # Use Mailtrap-generated credentials for port, server name, login, and password
server.login(login, password)
server.sendmail(sender, receiver, message)
print('Sent')
except (gaierror, ConnectionRefusedError): # In case of errors
print('Unable to connect to the server.')
except smtplib.SMTPServerDisconnected:
print('Server connection failed!')
except smtplib.SMTPException as e:
print('SMTP error: ' + str(e))
If there's no error, you should see this message in the receiver's inbox:
This is a test email.
Best Practices for Secure Email Sending
Consider the below Python email best practices for secure email sending:
Protect data: Take appropriate security measures to protect your sensitive data such as SMTP credentials, API keys, etc. Store them in a secure, private place like config files or environment variables, ensuring no one can access them publicly.
Encryption and authentication: Always use email encryption and authentication so that only authorized individuals can access your emails and their content.
For authentication, you can use advanced methods like API keys, two-factor authentication, single sign-on (SSO), etc. Similarly, use advanced encryption techniques like SSL, TLS, E2EE, etc.
Error handling: Manage network issues, authentication errors, and other issues by handling errors effectively using except/try blocks in your code.
Rate-Limiting: Maintain high email deliverability by rate-limiting the email sending functionality to prevent exceeding your service limits.
Validate Emails: Validate email addresses from your list and remove invalid ones to enhance email deliverability and prevent your domain from getting marked as spam. You can use an email validation tool to do this.
Educate: Keep your team updated with secure email practices and cybersecurity risks. Monitor your spam score and email deliverability rates, and work to improve them.
Wrapping Up
Secure email sending with Python using advanced email encryption methods like SSL, TLS, and end-to-end encryption, as well as authentication protocols and techniques such as SPF, DMARC, 2FA, and API keys.
By combining these security measures, you can protect your confidential email information, improve email deliverability, and maintain trust with your target recipients. In this way, only individuals with appropriate credentials can access it. This will help prevent unauthorized access, data breaches, and other cybersecurity attacks.