Simple Mail Transfer Protocol (SMTP) is a standard internet protocol that is used to transfer emails.
SMTP was originally standardized in 1982 under RFC 821. It was later updated to Extended SMTP through RFC 5321 which is currently in use by the majority of mail service providers.
The SMTP protocol is used only for the transfer of emails.
If you want to read emails from the server or modify the mailbox then there is a different protocol named Internet Message Access Protocol (IMAP - see below imaplib library link).
Python provides a library named smtplib which can be used to connect to the mail server to send mail. It provides a bunch of methods that can let us send SMTP commands to the mail server and send emails.
As a part of this tutorial, we have explained how to use Python module "smtplib" to communicate with the mail server and send / transfer emails using simple and easy-to-understand examples. We'll be connecting to Gmail and yahoo mail servers to transfer / send emails during our examples. We have explained various things like how to connect to server, authenticate email, login / logout, send mail, add attachments to emails, etc.
If you are looking for guidance on how to perform operations with mailboxes like read emails, delete emails, star / flag emails, list directories, create directories, delete directories, search emails (w / wo pattern), etc then please check below link. As we mentioned earlier, we need to use IMAP protocol for interacting with mailboxes.
Below, we have listed important sections of tutorial to give an overview of the material covered.
This is the first step we need to do in order to interact with email servers. It authenticate us using secret generated by following these steps.
Please make a NOTE that Gmail and yahoo mail nowadays does not let us login to the server using a password if we are trying to access their account through some other applications/scripts. It requires us to create an app password that will be used to authenticate that application/script.
Please DELETE the app if you are no longer using that app for your own safety.
As a part of our first example, we are demonstrating how we can connect to the mail server using SMTP_SSL.
Gmail and yahoo mail provides access to SMTP over SSL through port number 465 or 587. We'll be using SMTP over SSL for the majority of our examples because Gmail and yahoo mail does not let us connect to SMTP without SSL. Please find below details about Gmail and yahoo mail server and port details for communicating over SMTP.
Our code for this example has 3 parts.
The first two parts try to connect with the SMTP server of Gmail using SMTP class and the third party tries to connect using SMTP_SSL.
The first two fails because Gmail does not allow connection over normal SMTP. It only accepts the connection over SSL.
The second part has included a timeout of 3 seconds hence it times out and prints an error. We have also printed the time taken by each part.
We have used Python module time for measuring time taken by various steps throughout our tutorial. Please feel free to check below link if you want to learn about module.
import smtplib
import time
################### SMTP ########################
start = time.time()
try:
smtp = smtplib.SMTP(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp = None
print("Connection Object : {}".format(smtp))
print("Total Time Taken : {:,.2f} Seconds\n".format(time.time() - start))
############### SMTP with Timeout ######################
start = time.time()
try:
smtp = smtplib.SMTP(host="smtp.gmail.com", port=465, timeout=3)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp = None
print("Connection Object : {}".format(smtp))
print("Total Time Taken : {:,.2f} Seconds\n".format(time.time() - start))
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
As a part of our second example, we are explaining how we can log in and logout of the server using user name and password once the connection is established.
Our code for this example connects to the Gmail server by creating an instance of SMTP_SSL. It then tries to log in to the server using the user name and app password. After successful login, it logs out of the session. We are printing response code and response messages for each call of the methods.
import smtplib
import time
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
Our code for this example is exactly the same as our code for the previous part with the only difference that we are connecting to the Yahoo mail server in this part.
import smtplib
import time
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.mail.yahoo.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="sunny.2309@yahoo.in", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
As a part of our third example, we are explaining how we can verify user name by connecting to the SMTP server using verify() method.
Our code for this example first connects to the Gmail mail server by creating an instance of SMTP_SSL providing its hostname and port number. It then sets the debug level to 1 to prints all communication messages. We then login to the mail server by providing user credentials. We are then verifying an email address using verify() method. At last, We are logging out of the server and terminating the connection with the server.
import smtplib
import time
################# IMAP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
smtp_ssl.set_debuglevel(1)
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In........")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
######### Verify mail adress ############################
print("\nVerifying Email Address.......")
resp_code, response = smtp_ssl.verify("coderzcolumn07@gmail.com")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
######### Log out to mail account ############################
print("\nLogging Out.......")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
Our code for this example is almost the same as our code for the previous example with minor changes.
The first change is that we have set debug level to 2 in this example.
The second change is that before logging in, we have called ehlo_or_helo_if_needed() method. This method will make sure that login() method does not need to send HELO / EHLO message to the server which it does if the user had not identified itself with the server.
import smtplib
import time
################# IMAP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
smtp_ssl.set_debuglevel(2)
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
################# Saying Hello ################################
print("\nSaying Hello to server........")
smtp_ssl.ehlo_or_helo_if_needed()
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
######### Verify mail adress ############################
print("\nVerifying Email Address.......")
resp_code, response = smtp_ssl.verify("coderzcolumn07@gmail.com")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
######### Log out to mail account ############################
print("\nLogging Out........")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
As a part of our fourth example, we'll demonstrate how we can send mail using sendmail() method once the connection has been established with the mail server and the user has logged in.
Our code for this example builds on the code from our previous examples. It creates a connection with the Gmail server and then logs in. It then sends simple mail using sendmail() method.
import smtplib
import time
import imaplib
import email
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
frm = "mail2sunny.2309@gmail.com"
to_list = ["mail2sunny.2309@gmail.com", "sunny.2309@yahoo.in", "coderzcolumn07@gmail.com"]
message = 'Subject: {}\n\n{}'.format("Test Email", "Hello All,\n\nHow are you doing?\n\nRegards,\nCoderzColumn")
response = smtp_ssl.sendmail(from_addr=frm,
to_addrs=to_list,
msg=message
)
print("List of Failed Recipients : {}".format(response))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
Our code for this example is almost the same as our previous example with the only minor change that we have created an instance of EmailMessage available from email module which can be used to represent email messages. We can treat an instance of EmailMessage as a dictionary and set fields of mail like from, to, subject, etc. We have set the body of the email using set_content() method of the EmailMessage. When calling sendmail() method we have passed string by calling as_string() method on EmailMessage instance. The as_string() method returns string representation of email.
If you are interested in learning about how emails are represented in Python then please feel free to check our tutorial on module email which is used for it.
import smtplib
import time
import email
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
message = email.message.EmailMessage()
message.set_default_type("text/plain")
frm = "mail2sunny.2309@gmail.com"
to_list = ["mail2sunny.2309@gmail.com", "sunny.2309@yahoo.in", "coderzcolumn07@gmail.com"]
message["From"] = frm
message["To"] = to_list
message["Subject"] = "Test Email"
body = '''
Hello All,
How are you doing?
Regards,
CoderzColumn
'''
message.set_content(body)
response = smtp_ssl.sendmail(from_addr=frm,
to_addrs=to_list,
msg=message.as_string())
print("List of Failed Recipients : {}".format(response))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
As a part of our fifth example, we are demonstrating how we can send mail using send_message() method.
Our code for this example is almost the same as our previous example with the only major change that we are using send_message() method to send mail.
import smtplib
import time
import email
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
message = email.message.EmailMessage()
message.set_default_type("text/plain")
message["From"] = "mail2sunny.2309@gmail.com"
message["To"] = ["mail2sunny.2309@gmail.com", "sunny.2309@yahoo.in", "coderzcolumn07@gmail.com"]
message["Subject"] = "Test Email"
body = '''
Hello All,
How are you doing?
Regards,
CoderzColumn
'''
message.set_content(body)
response = smtp_ssl.send_message(msg=message)
print("List of Failed Recipients : {}".format(response))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
As a part of our sixth example, we are demonstrating how we can set CC and BCC fields of the mail.
Our code for this example is exactly the same as our previous example with minor changes. We have moved one of our addresses to Cc field and one address to Bcc field of the EmailMessage instance representing mail.
import smtplib
import time
import email
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
message = email.message.EmailMessage()
message.set_default_type("text/plain")
message["From"] = "mail2sunny.2309@gmail.com"
message["To"] = ["coderzcolumn07@gmail.com", ]
message["cc"] = ["mail2sunny.2309@gmail.com",]
message["Bcc"] = ["sunny.2309@yahoo.in", ]
message["Subject"] = "Test Email"
body = '''
Hello All,
How are you doing?
Regards,
CoderzColumn
'''
message.set_content(body)
response = smtp_ssl.send_message(msg=message)
print("List of Failed Recipients : {}".format(response))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
As a part of our seventh example, we'll explain how we can attach files to our mail using add_attachment() method of EmailMessage instance.
Our code for this example is almost the same as our previous example with the minor addition of code for attaching a jpeg image file. We have kept a JPEG image file in the same directory. We are first reading the file's content as bytes. Then we are calling add_attachment() method on an instance of EmailMessage giving it bytes of data as input. We are also setting other parameters of add_attachment() as mentioned below.
If you are interested in learning which main and subtype to use for different file types then please check the below link.
Python provides a module named mimetypes that let us retrieve MIME type of a file. We can use it as well for our purposes. Please feel free to check below link to learn about it.
import smtplib
import time
import email
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
message = email.message.EmailMessage()
message["From"] = "mail2sunny.2309@gmail.com"
message["To"] = ["coderzcolumn07@gmail.com", ]
message["cc"] = ["mail2sunny.2309@gmail.com",]
message["Bcc"] = ["sunny.2309@yahoo.in", ]
message["Subject"] = "Mail with attachments"
body = '''
Hello All,
Please find attached file.
Regards,
CoderzColumn
'''
message.set_content(body)
### Attach JPEG Image.
with open("dr_apj_kalam.jpeg", mode="rb") as fp:
img_content = fp.read()
message.add_attachment(img_content, maintype="image", subtype="jpeg", filename="kalam.jpeg")
### Send Message
response = smtp_ssl.send_message(msg=message)
print("List of Failed Recipients : {}".format(response))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
Our code for this example is almost the same as our previous example with the only change that we are using a PDF file in this example instead of a JPEG file.
import smtplib
import time
import email
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
message = email.message.EmailMessage()
message["From"] = "mail2sunny.2309@gmail.com"
message["To"] = ["coderzcolumn07@gmail.com", ]
message["cc"] = ["mail2sunny.2309@gmail.com",]
message["Bcc"] = ["sunny.2309@yahoo.in", ]
message["Subject"] = "Mail with attachments"
body = '''
Hello All,
Please find attached file.
Regards,
CoderzColumn
'''
message.set_content(body)
### Attach PDF Image.
with open("Deploying a Django Application to Google App Engine.pdf", mode="rb") as fp:
pdf_content = fp.read()
message.add_attachment(pdf_content, maintype="application", subtype="pdf", filename="doc.pdf")
### Send Message
response = smtp_ssl.send_message(msg=message)
print("List of Failed Recipients : {}".format(response))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
Our code for this example is almost the same as our previous example with the only change that we are attaching a zip file in this example instead. The zip file has PDF and a JPEG image from previous examples in it.
import smtplib
import time
import email
################# SMTP SSL ################################
start = time.time()
try:
smtp_ssl = smtplib.SMTP_SSL(host="smtp.gmail.com", port=465)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
smtp_ssl = None
print("Connection Object : {}".format(smtp_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
message = email.message.EmailMessage()
message["From"] = "mail2sunny.2309@gmail.com"
message["To"] = ["coderzcolumn07@gmail.com", ]
message["cc"] = ["mail2sunny.2309@gmail.com",]
message["Bcc"] = ["sunny.2309@yahoo.in", ]
message["Subject"] = "Mail with attachments"
body = '''
Hello All,
Please find attached file.
Regards,
CoderzColumn
'''
message.set_content(body)
### Attach Zip Image.
with open("docs.zip", mode="rb") as fp:
zip_content = fp.read()
message.add_attachment(zip_content, maintype="application", subtype="zip", filename="docs.zip")
### Send Message
response = smtp_ssl.send_message(msg=message)
print("List of Failed Recipients : {}".format(response))
######### Log out to mail account ############################
print("\nLogging Out....")
resp_code, response = smtp_ssl.quit()
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
As a part of our eighth example, we are demonstrating that we can use SMTP_SSL instance as context manager as well. If we use SMTP_SSL as context manager then we don't need to call quit() method to close the connection. It'll be called automatically once the context manager ends.
Our code for this example is almost the same as our 4th example with the only change that we are using SMTP_SSL as a context manager and not calling quit() method to end connection.
Python provides a library named contextlib to easily create context managers. Please feel free to check our article on it if you are interested in it.
import smtplib
import time
import imaplib
import email
################# SMTP SSL ################################
with smtplib.SMTP_SSL(host="smtp.gmail.com", port=465) as smtp_ssl:
print("Connection Object : {}".format(smtp_ssl))
######### Log In to mail account ############################
print("\nLogging In.....")
resp_code, response = smtp_ssl.login(user="mail2sunny.2309@gmail.com", password="app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response.decode()))
################ Send Mail ########################
print("\nSending Mail..........")
frm = "mail2sunny.2309@gmail.com"
to_list = ["mail2sunny.2309@gmail.com", "sunny.2309@yahoo.in", "coderzcolumn07@gmail.com"]
message = 'Subject: {}\n\n{}'.format("Test Email", "Hello All,\n\nHow are you doing?\n\nRegards,\nCoderzColumn")
response = smtp_ssl.sendmail(from_addr=frm,
to_addrs=to_list,
msg=message
)
print("List of Failed Recipients : {}".format(response))demonstrating
This ends our small tutorial explaining how we can use smtplib to send mails using Python.
If you are more comfortable learning through video tutorials then we would recommend that you subscribe to our YouTube channel.
When going through coding examples, it's quite common to have doubts and errors.
If you have doubts about some code examples or are stuck somewhere when trying our code, send us an email at coderzcolumn07@gmail.com. We'll help you or point you in the direction where you can find a solution to your problem.
You can even send us a mail if you are trying something new and need guidance regarding coding. We'll try to respond as soon as possible.
If you want to