What is SMTP
SMTP stands for Simple Mail Transfer Protocol. It's a protocol used for sending and forwarding email messages over the Internet. SMTP is the standard protocol that email clients (like Outlook, Gmail, Thunderbird) and email servers (like Exchange, Postfix, and Sendmail) use to send outgoing emails from a sender's email client to the recipient's email server.
Overview of how SMTP works:
Client Initiation: An email client (sender) initiates an SMTP connection to an SMTP server (outgoing mail server) on a designated port (usually port 25 or 587).
Handshake: The client and server perform a handshake to establish a connection. The client identifies itself using the EHLO (Extended Hello) command.
Sender and Recipient Information: The client specifies the sender's email address and the recipient's email address.
Message Transfer: The client sends the email message to the server. The message includes headers, subject, sender, recipient, and the body of the email.
Data Transfer: The client sends the email content, including any attachments, using the DATA command.
Closing Connection: After the message is sent, the client and server may close the connection using the QUIT command.
SMTP is a crucial component of the email infrastructure, enabling the exchange of emails across different domains and email service providers. It works alongside other protocols like POP3 (Post Office Protocol) and IMAP (Internet Message Access Protocol) that are used for receiving emails on the recipient's end.
Sending an email
MIME types
Before sending we have to know some extra stuff. Here are some examples of emails where the MIME will be different for each type. For example, If we want to send plain text, the format will be different If we want to send an image with plain text. It may seem a bit confusing but hopefully, we will understand how It helps us for sending an email.
Compose the email (Sending HTML text)
# Email content
subject = "Email subject"
body = "This is the body of the email."
# Compose the email
msg = MIMEMultipart("alternative")
msg['From'] = "your_email@example.com"
msg['To'] = "recipient@example.com"
msg['Subject'] = Header(subject, 'utf-8')
# Include the identifier of the email you wish to respond to within the email header
# i.e: CAPduzUmsOd*****************@mail.gmail.com
msg["Message-ID"] = email.utils.make_msgid()
msg["In-Reply-To"] = '<message_id_of_the_email_i_want_to_reply_against>'
msg["References"] = '<message_id_of_the_email_i_want_to_reply_against>'
Attach the body (Sending HTML text)
# Email content
subject = "Email subject"
reply_body = """\\
Hi,
This email contains the reply message.
Regards,
Sayad ahmed Chowdhury
"""
parent_copy = """\\
Hi,
This email contains the parent message.
Regards,
Sayad ahmed Chowdhury
"""
reply_plain_body = """
{}
On Aug 10, 2023, at 10:30 AM, {} wrote:
> {}
> {}
""".format(reply_body, original_sender, original_subject, original_body)
reply_html_body = """\\
<div>
<div>
{}
</div>
<div>
<p>On Aug 10, 2023, at 10:30 AM, you wrote:</p>
<blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
{}
</blockquote>
</div>
</div>
""".format("<br>".join(reply_body.split("\\n")), "<br>".join(parent_copy.split("\\n")))
# Add both plain text and HTML versions of the email
html_part = MIMEText(reply_html_body, 'html')
msg.attach(html_part)
# plain part is not necessary If we are sending the HTML part.
plain_part = MIMEText(reply_plain_body, 'plain')
msg.attach(plain_part)
email_body = msg.as_string()
Here, one thing might seem confusing. We have to send the body of the email in a defined way where the reply and the parent email will be wrapped inside different <div>, while both of them will be enclosed by another <div>. By sending this way, we will see the reply email on top, and the parent email will be under the 3 dots (in Gmail).
Connect to the SMTP server and send the email
# Connect to the SMTP server and send the email
smtp_server = "smtp.example.com" # Replace with your SMTP server
smtp_port = 587 # Replace with the appropriate port
smtp_username = "your_email@example.com"
smtp_password = "your_password"
with smtplib.SMTP(smtp_server, smtp_port) as server:
"""
sender_email - the email of the sender
receiver_email - the email where the message will be sent
email_body - the body of the email
"""
server.starttls()
server.login(smtp_username, smtp_password)
server.sendmail(sender_email, receiver_email, email_body)
We can use different security methods (SSL, TLS, and STARTTLS) to connect and authenticate with an SMTP server using the smtplib
library in Python:
- Using SSL:
import smtplib
import ssl
SMTP_SERVER = "smtp.example.com"
SMTP_PORT_SSL = 465
USERNAME = "your_email@example.com"
PASSWORD = "your_password"
context = ssl.create_default_context()
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT_SSL, context=context) as smtp:
smtp.login(USERNAME, PASSWORD)
print("Logged in using SSL.")
- Using TLS (Explicit TLS):
import smtplib
import ssl
SMTP_SERVER = "smtp.example.com"
SMTP_PORT_TLS = 587
USERNAME = "your_email@example.com"
PASSWORD = "your_password"
context = ssl.create_default_context()
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT_TLS) as smtp:
smtp.starttls(context=context)
smtp.login(USERNAME, PASSWORD)
print("Logged in using TLS.")
- Using STARTTLS:
import smtplib
SMTP_SERVER = "smtp.example.com"
SMTP_PORT = 587
USERNAME = "your_email@example.com"
PASSWORD = "your_password"
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as smtp:
smtp.starttls()
smtp.login(USERNAME, PASSWORD)
print("Logged in using STARTTLS.")
Replace "
smtp.example.com
"
, 465
(for SSL), 587
(for TLS and STARTTLS), "
your_email@example.com
"
, and "your_password"
with your actual SMTP server details, credentials, and desired ports.
Each method uses a different approach to establishing a secure connection, but the login process remains the same. Remember to handle your credentials securely, as hardcoding them directly in your code is not recommended. We can use .env file store passwords and email here.
Keep in mind that not all SMTP servers support all these methods, so you should choose the appropriate method based on the configuration of the SMTP server you are using.
Final code to send an email (plain text)
With this piece of code, we can send an email to a user.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
# Email content
subject = "Email subject"
body = "This is the body of the email."
# Compose the email
msg = MIMEMultipart()
msg['From'] = "your_email@example.com"
msg['To'] = "recipient@example.com"
msg['Subject'] = Header(subject, 'utf-8')
# Include the identifier of the email you wish to respond to within the email header
# i.e: CAPduzUmsOd*****************@mail.gmail.com
msg["Message-ID"] = email.utils.make_msgid()
msg["In-Reply-To"] = '<message_id_of_the_email_i_want_to_reply_against>'
msg["References"] = '<message_id_of_the_email_i_want_to_reply_against>'
# Attach the body text to the email
msg.attach(MIMEText(body, 'plain'))
email_body = msg.as_string()
# Connect to the SMTP server and send the email
smtp_server = "smtp.example.com" # Replace with your SMTP server
smtp_port = 587 # Replace with the appropriate port
smtp_username = "your_email@example.com"
smtp_password = "your_password"
with smtplib.SMTP(smtp_server, smtp_port) as server:
"""
sender_email - the email of the sender
receiver_email - the email where the message will be sent
email_body - the body of the email
"""
server.starttls()
server.login(smtp_username, smtp_password)
server.sendmail(sender_email, receiver_email, email_body)