Internet Message Access Protocol (IMAPv4) is an Internet protocol that lets us access email messages from mailboxes. It even let us move mails between mailboxes, create directories within mailboxes, mark emails as read/unread, mark emails as important, search emails, etc.
It's the protocol used by all the email clients to access the mailbox of the user.
The current version of IMAP is IMAP4rev1 generally referred to as IMAP4.
Python provides us with the library named 'imaplib' which lets us access our mailbox and read emails over IMAP Protocol.
As a part of this tutorial, we have explained how to use Python library imaplib to access mailboxes, read emails, copy emails between directories, create directories, search emails, delete emails, star emails, etc with simple examples. We have connected to Gmail server to explain various operations with mailboxes for a majority of our examples. Though same code can be used with Yahoo or any other mailboxes as well. We have connected to Yahoo server as well for one or two of our examples.
Below, we have listed important sections of Tutorial to give an overview of the material covered.
This is the first step that we need to perform in order to access our mailbox.
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 that returns a token that will be used to authenticate that application/script. This is good for security of your account. We can anytime delete this app and application/script will not be able to access mailboxes. This can be useful if a hacker somehow gets access to your token/password.
Below we have given steps to create an app whose password we'll use to access Gmail and Yahoo mail mailboxes.
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 explaining how we can make connections to the mail server over IMAP4. The imaplib provides us with a class named IMPA4 and IMAP4_SSL which can be used to make a connection to the server.
Our code for this example has three-part.
The first part tries connection with the Gmail mail server over port 993 using IMAP4 class.
The second part tries the same but with the timeout set to 3 seconds using IMAP4 class.
The third part tries to connect with the Gmail server using IMAP4_SSL class.
The first two parts of the code fail to connect to the server because Gmail and Yahoo mail allows connection over SSL only. The third part of our code is successfully able to connect to the mail server.
Gmail and Yahoo mail provides access to IMAP4 over port number 993. Gmail and Yahoo mail let us access the mailbox over SSL only.
The below links have information about hostname and port details about Gmail and Yahoo mail that we'll be using for our examples.
import imaplib
import time
################### IMAP ########################
start = time.time()
try:
imap = imaplib.IMAP4(host="imap.gmail.com", port=993)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
imap = None
print("Connection Object : {}".format(imap))
print("Total Time Taken : {:,.2f} Seconds\n".format(time.time() - start))
############### IMAP with Timeout ######################
start = time.time()
try:
imap = imaplib.IMAP4(host="imap.gmail.com", port=993, timeout=3)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
imap = None
print("Connection Object : {}".format(imap))
print("Total Time Taken : {:,.2f} Seconds\n".format(time.time() - start))
################# IMAP SSL ################################
start = time.time()
try:
imap_ssl = imaplib.IMAP4_SSL(host="imap.gmail.com", port=993)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
imap_ssl = None
print("Connection Object : {}".format(imap_ssl))
print("Total Time Taken : {:,.2f} Seconds".format(time.time() - start))
As a part of our second example, we are demonstrating how we can log in to the server using user credentials and log out once the connection is established using IMAP4 instance.
Please make a NOTE that majority of methods of IMAP4/IMAP4_SSL returns a tuple of two values of the form (reponse_code, [reponse_message,...]).
The response code is either OK, BYE or NONE.
The response message is a list with a single bytes string or a list of bytes strings based on the method call.
If the method is a simple command like login/logout then the second value of the tuple is a list with one value (bytes message) specifying the response of the server after the execution of that method.
Our code for this example first creates an instance of IMAP4_SSL and establishes a connection with the server.
It then calls the login() method with user name and password to log in a user to the server.
At last, it calls logout() to log the user out.
All our method calls are wrapped inside of the try-except block to catch any errors that can happen. We are also printing response codes and messages.
Please make a NOTE that we are calling decode() methods on response messages to convert them from bytes to string format.
import imaplib
import time
################ IMAP SSL Establish Connection #################
start = time.time()
try:
imap_ssl = imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
imap_ssl = None
print("Connection Object : {}".format(imap_ssl))
print("Total Time Taken : {:,.2f} Seconds\n".format(time.time() - start))
############### Login to Mailbox ######################
print("Logging into mailbox...")
try:
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, response = None, None
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
############### Logout of Mailbox ######################
print("\nLogging Out....")
try:
resp_code, response = imap_ssl.logout()
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, response = None, None
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
As a part of our third example, we'll explain how we can list down directories present within the mailbox using list() method of IMAP4/IMAP4_SSL instance.
Our code for this example tarts like our previous examples by establishing a connection with the server and logging in to it.
Then, we called list() method without any parameters to list down all mailboxes present. We are then looping through all directories and printing them.
After that, we called list() method again but this time with parameter directory set to [Gmail] so that it returns directory which are subdirectories of it.
At last, Our code logs out of the server.
Please make a NOTE that yahoo mailbox has Spam directory available with name "Bulk". If you are not able to find Spam folder in mail list then you can look for "\Junk" flag. The directory with this flag is generally Spam directory.
import imaplib
import time
################ IMAP SSL Connection ##############################
start = time.time()
try:
imap_ssl = imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
imap_ssl = None
print("Connection Object : {}".format(imap_ssl))
print("Total Time Taken : {:,.2f} Seconds\n".format(time.time() - start))
############### Login to Mailbox ######################
print("Logging into mailbox...")
try:
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, response = None, None
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
#################### List Directores #####################
try:
resp_code, directories = imap_ssl.list()
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, directories = None, None
print("Response Code : {}".format(resp_code))
print("========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
#################### List Directores #####################
try:
resp_code, directories = imap_ssl.list(directory="[Gmail]")
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, directories = None, None
print("Response Code : {}".format(resp_code))
print("\n========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
############### Logout of Mailbox ######################
print("\nLogging Out....")
try:
resp_code, response = imap_ssl.logout()
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, response = None, None
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
As a part of our fourth example, we are again explaining the usage of list() method to list down mailboxes present in the directory but this time we are explaining 'pattern' parameter.
The 'pattern' parameter accepts a pattern to match the list of directories that matches that pattern. The pattern format is same as the Unix directory matching patterns.
Our code for this example starts by establishing a connection with the server and logs in to it like our previous examples.
Then, it calls list() method with a pattern that will match all directories which has 'Coursera' word in them. We print all subdirectories which match this pattern.
Then, we called list() method again with a pattern that matches for word 'Coursera/Algo' at the beginning of the directory name. We again print a list of directories that matches this pattern.
At last, we log out of the server.
import imaplib
import time
################ IMAP SSL Connection ##############################
start = time.time()
try:
imap_ssl = imaplib.IMAP4_SSL(host="imap.mail.yahoo.com", port=imaplib.IMAP4_SSL_PORT)
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
imap_ssl = None
print("Connection Object : {}".format(imap_ssl))
print("Total Time Taken : {:,.2f} Seconds\n".format(time.time() - start))
############### Login to Mailbox ######################
print("Logging into mailbox...")
try:
resp_code, response = imap_ssl.login("sunny.2309@yahoo.in", "app_password")
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, response = None, None
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
#################### List Directores #####################
try:
resp_code, directories = imap_ssl.list(pattern="*Coursera*")
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, directories = None, None
print("Response Code : {}".format(resp_code))
print("========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
#################### List Directores #####################
try:
resp_code, directories = imap_ssl.list(pattern="Coursera/Algo*")
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, directories = None, None
print("Response Code : {}".format(resp_code))
print("\n========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
############### Logout of Mailbox ######################
print("\nLogging Out....")
try:
resp_code, response = imap_ssl.logout()
except Exception as e:
print("ErrorType : {}, Error : {}".format(type(e).__name__, e))
resp_code, response = None, None
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
Our code for this example is almost the same as our code for the third example with the only change that we are using IMAP4_SSL instance as a context manager (Python "with" statement).
As we are using IMAP4_SSL instance as a context manager, we don't need to call logout() method to log out of the server.
When we are exiting of context, the logout() method will be called by the context manager.
Context managers are a very important concept of Python. It let us execute particular code within a context. It handles enter and exit tasks which are common for some code like DB connection, etc so. It helps us prevent errors like forgetting to close DB connection, etc.
Python provides a library named 'contextlib' that let us easily create context managers. We recommend that you check it out in your free time by clicking a link.
import imaplib
import time
################ IMAP SSL Connection ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
#################### List Directores #####################
resp_code, directories = imap_ssl.list()
print("Response Code : {}".format(resp_code))
print("========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
#################### List Directores #####################
resp_code, directories = imap_ssl.list(directory="[Gmail]")
print("Response Code : {}".format(resp_code))
print("\n========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
As a part of our sixth example, we are demonstrating how we can display the count of mail messages present per directory using select() method of IMAP4_SSL instance.
select(mailbox='INBOX',readonly=False) - This method sets mailbox given by parameter mailbox so that all the operations that we'll perform after this method will be performed on this selected mailbox. It's set to INBOX by default. It returns the tuple of two values where the second value has a count of the mails for a given mailbox.
close() - It closes currently selected mailbox. The deleted messages are permanently removed from the mailbox. We should call this command before logging out of the mailbox.
Our code for this example starts by creating an instance of IMAP4_SSL and logging in to the mail server.
Then, it lists down a list of directories present in the mailbox using list() method.
We are then looping through the list of directories and retrieving mail count per directory using select() method.
We are accessing the mailbox in read-only mode.
import imaplib
import time
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
#################### List Directores #####################
resp_code, directories = imap_ssl.list()
print("Response Code : {}".format(resp_code))
print("========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
############### Number of Messages per Directory ############
print("\n=========== Mail Count Per Directory ===============\n")
for directory in directories:
directory_name = directory.decode().split('"')[-2]
directory_name = '"' + directory_name + '"'
if directory_name == '"[Gmail]"':
continue
try:
resp_code, mail_count = imap_ssl.select(mailbox=directory_name, readonly=True)
print("{} - {}".format(directory_name, mail_count[0].decode()))
except Exception as e:
print("{} - ErrorType : {}, Error : {}".format(directory_name, type(e).__name__, e))
resp_code, mail_count = None, None
############# Close Selected Mailbox #######################
imap_ssl.close()
As a part of our seventh example, we are demonstrating how we can retrieve mails from mailboxes using search() method.
search(charset, criterion) - This method searches mailbox based on criteria provided using criterion parameter. The criterion parameter accepts strings specifying which mails to retrieve. This method will return a tuple of two values where the second value will have a byte string having a list of mail ids separated by space.
fetch(message_set,message_parts) - This method accepts a string specifying a list of message ids and a string specifying message parts to retrieve for all messages.
Below link has detailed information about strings which can be used as criterion parameter of search() method and message_parts parameter of fetch() method.
Our code for this example starts by "connecting to the server" by creating an instance of IMAP4_SSL.
After establishing a connection, it "logs in" to the server and then selects ELITMUS as a mailbox.
Then, it "retrieves mail ids" for all mails inside of ELITMUS mailbox using 'select()' method. The mail ids are an integer from 1 to a number of emails in the box. The number 1 represents the oldest mail and the maximum number represents the latest mail id.
From a list of mail ids, we take the last two mail ids and "retrieve mail contents" using 'fetch()' method. The mail contents are returned as bytes string and we need to convert them to human-readable format for looking at contents.
To "construct email message", we are creating an instance of 'EmailMessage' which is a wrapper class provided by 'email' module which is used to represent mails in Python. We can generate an instance of EmailMessage by calling message_from_bytes() method of email module. The method accepts a message represented as a bytes string as input and returns EmailMessage instance.
Once an email message is created, we are "printing various parts of the mail" like from, to, bcc, date, subject, and body. We are calling walk() method instance of EmailMessage to retrieve all parts of the message and print only part which is text.
The message can have multiple parts like audio, video, image, and attachments that we have ignored here, and printing only body text content.
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. It'll help you with handling various parts of mail other than body text.
import imaplib
import email
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
############### Set Mailbox #############
resp_code, mail_count = imap_ssl.select(mailbox="ELITMUS", readonly=True)
############### Retrieve Mail IDs for given Directory #############
resp_code, mail_ids = imap_ssl.search(None, "ALL")
print("Mail IDs : {}\n".format(mail_ids[0].decode().split()))
############### Display Few Messages for given Directory #############
for mail_id in mail_ids[0].decode().split()[-2:]:
print("================== Start of Mail [{}] ====================".format(mail_id))
resp_code, mail_data = imap_ssl.fetch(mail_id, '(RFC822)') ## Fetch mail data.
message = email.message_from_bytes(mail_data[0][1]) ## Construct Message from mail data
print("From : {}".format(message.get("From")))
print("To : {}".format(message.get("To")))
print("Bcc : {}".format(message.get("Bcc")))
print("Date : {}".format(message.get("Date")))
print("Subject : {}".format(message.get("Subject")))
print("Body : ")
for part in message.walk():
if part.get_content_type() == "text/plain":
body_lines = part.as_string().split("\n")
print("\n".join(body_lines[:12])) ### Print first 12 lines of message
print("================== End of Mail [{}] ====================\n".format(mail_id))
############# Close Selected Mailbox #######################
imap_ssl.close()
As a part of our eighth example, we are demonstrating how we can create, delete and rename mailboxes using create(), delete() and rename() methods of IMAP4_SSL instance.
Our code for this example starts by establishing a connection to the server by creating an instance of IAP4_SSL.
We are then logged in to the mail server.
We are then selecting mailbox as INBOX using 'select()' method.
We are then creating a mailbox named ELITMUS_2 using 'create()' method. Once the mailbox is created, we are listing down directories using list() method to check whether the mailbox was created or not.
We are then deleting mailbox using 'delete()' method. Once the mailbox is deleted, we are again listing down mailboxes to check whether the mailbox was deleted or not.
The last part of our code rename mailbox ELITMUS_2 to ELITMUS_4 using 'rename()' method. We are then again listing down directories to check whether the mailbox was renamed or not.
Once all operations are performed, we are calling 'expunge()' method to make the change permanent and close the mailbox using 'close()' method.
import imaplib
import email
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
############### Set Mailbox #############
resp_code, mail_count = imap_ssl.select(mailbox="INBOX", readonly=False)
############### Create Mailbox #############
print("Creating Mailbox : ELITMUS_2")
resp_code, response = imap_ssl.create(mailbox="ELITMUS_2")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
#################### List Directores #####################
resp_code, directories = imap_ssl.list()
print("\nResponse Code : {}".format(resp_code))
print("========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
############### Delete Mailbox #############
print("\nDeleting Mailbox : Myntra")
resp_code, response = imap_ssl.delete(mailbox="Myntra")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
#################### List Directores #####################
resp_code, directories = imap_ssl.list()
print("\nResponse Code : {}".format(resp_code))
print("========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
############### Rename Mailbox #############
print("\nRenaming Mailbox : ELITMUS_2")
resp_code, response = imap_ssl.rename(oldmailbox="ELITMUS_2", newmailbox="ELITMUS_4")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
#################### List Directores #####################
resp_code, directories = imap_ssl.list()
print("\nResponse Code : {}".format(resp_code))
print("========= List of Directories =================\n")
for directory in directories:
print(directory.decode())
################### Expunge ########################
print("\nFinalizing changes...")
resp_code, response = imap_ssl.expunge()
print("\nResponse Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode() if response[0] else None))
############# Close Selected Mailbox #######################
imap_ssl.close()
As a part of the ninth example, we'll explain how we can copy emails from one directory to another using copy() method of IMAP4_SSL instance.
Our code for this example starts by creating an instance of IMPA4_SSL to establish a connection to the server.
It then logs in to the server and selects the mailbox as ELITMUS.
It then searches the mailbox using 'search()' method to retrieve all mail ids.
It then takes the last two mail ids and copies them using 'copy()' method to Personal mailbox. It passes both mail ids together to be copied.
It then again copies the first two emails from the ELITMUS mailbox to Personal mailbox. This time it loops through ids and copies individual mail by calling 'copy()' method more than once.
Once all operations are done, it closes mailbox using 'close()' method.
import imaplib
import email
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
############### Set Mailbox #############
resp_code, mail_count = imap_ssl.select(mailbox="ELITMUS", readonly=False)
############### Retrieve Mail IDs for given Directory #############
resp_code, mails = imap_ssl.search(None, "ALL")
print("Mail IDs : {}\n".format(mails[0].decode().split()))
################## Copy Messages to new mailbox ###################
print("\nCopying few mails of ELITMUS to different directory....")
mail_ids = mails[0].decode().split()[-2:]
mail_ids = ":".join(mail_ids)
print(mail_ids)
resp_code, response = imap_ssl.copy(mail_ids, "Personal")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
################## Copy Messages to new mailbox ###################
print("\nCopying few mails of ELITMUS to different directory....")
mail_ids = mails[0].decode().split()[:2] ## Copying first two mails
for mail_id in mail_ids:
resp_code, response = imap_ssl.copy(mail_id, "Personal")
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
############# Close Selected Mailbox #######################
print("\nClosing selected mailbox....")
imap_ssl.close()
As a part of our tenth example, we are demonstrating how we can search mailbox using different patterns passed to 'criterion' parameter of the 'search()' method.
Our code for this example like our previous example starts by establishing a connection with the server and logging in to the server.
It then selects a mailbox named INBOX.
It then gives a pattern that searches for emails from a particular sender. It retrieves all mail ids matching that pattern using 'search()' method. It then prints the contents of the last two emails from that sender.
The second search call searches for a mail from a particular sender and subject line containing a particular string. It retrieves all mail ids matching that pattern and then uses that mail ids to print contents of the latest two emails matching that pattern.
import imaplib
import email
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
############### Set Mailbox #############
resp_code, mail_count = imap_ssl.select(mailbox="INBOX", readonly=True)
############### Search mails in a given Directory #############
resp_code, mails = imap_ssl.search(None, '(FROM "Neil Patel")')
mail_ids = mails[0].decode().split()
print("Total Mail IDs : {}\n".format(len(mail_ids)))
for mail_id in mail_ids[-2:]:
print("================== Start of Mail [{}] ====================".format(mail_id))
resp_code, mail_data = imap_ssl.fetch(mail_id, '(RFC822)') ## Fetch mail data.
message = email.message_from_bytes(mail_data[0][1]) ## Construct Message from mail data
print("From : {}".format(message.get("From")))
print("To : {}".format(message.get("To")))
print("Bcc : {}".format(message.get("Bcc")))
print("Date : {}".format(message.get("Date")))
print("Subject : {}".format(message.get("Subject")))
print("Body : ")
for part in message.walk():
if part.get_content_type() == "text/plain": ## Only Printing Text of mail. It can have attachements
body_lines = part.as_string().split("\n")
print("\n".join(body_lines[:6])) ### Print first few lines of message
print("================== End of Mail [{}] ====================\n".format(mail_id))
############### Search mails in a given Directory #############
resp_code, mails = imap_ssl.search(None, 'FROM "Medium Daily Digest" Subject "Jupyter"')
mail_ids = mails[0].decode().split()
print("Total Mail IDs : {}\n".format(len(mail_ids)))
for mail_id in mail_ids[-2:]:
print("================== Start of Mail [{}] ====================".format(mail_id))
resp_code, mail_data = imap_ssl.fetch(mail_id, '(RFC822)') ## Fetch mail data.
message = email.message_from_bytes(mail_data[0][1]) ## Construct Message from mail data
print("From : {}".format(message.get("From")))
print("To : {}".format(message.get("To")))
print("Bcc : {}".format(message.get("Bcc")))
print("Date : {}".format(message.get("Date")))
print("Subject : {}".format(message.get("Subject")))
print("Body : ")
for part in message.walk():
if part.get_content_type() == "text/plain": ## Only Printing Text of mail.
body_lines = part.as_string().split("\n")
print("\n".join(body_lines[:6])) ### Print first few lines of message
print("================== End of Mail [{}] ====================\n".format(mail_id))
############# Close Selected Mailbox #######################
print("\nClosing selected mailbox....")
imap_ssl.close()
As a part of our eleventh example, we'll demonstrate how we can delete mails from the mailbox using store() method by changing flags.
Below mentioned RFC has very detailed explanations of flags.
Our code for this example starts as usual by establishing a connection and logging into the server.
It then select mailbox INBOX using select() method and retrieves emails ids from particular sender using search() method. We have set readonly parameter of select() method to False so that we can modify the mailbox otherwise we'll get an error when performing operations that try to modify the mailbox.
It then loops through mail ids and sets the flag as \Deleted for the first two mail ids using 'store()' method. It prints details with mail id, data, and subject informing which emails will be deleted. The 'store()' method will set a flag indicating that these emails need to be deleted.
Once flags are modified for two mail ids, we are calling expunge() method which will permanently delete both mails.
Please make a NOTE that we have used two backslashes inside the string of \\Deleted flag because a single backslash is used as an escape character and we need to escape it.
import imaplib
import email
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
############### Set Mailbox #############
resp_code, mail_count = imap_ssl.select(mailbox="INBOX", readonly=False)
############### Search and delete mails in a given Directory #############
resp_code, mails = imap_ssl.search(None, '(FROM "Neil Patel")')
mail_ids = mails[0].decode().split()
print("Total Mail IDs : {}\n".format(len(mail_ids)))
print("Deleting Mails...")
for mail_id in mail_ids[:2]:
resp_code, mail_data = imap_ssl.fetch(mail_id, '(RFC822)') ## Fetch mail data.
message = email.message_from_bytes(mail_data[0][1]) ## Construct Message from mail data
print("Mail ID : {}, Date : {}, Subject : {}".format(mail_id, message.get("Date"), message.get("Subject")))
resp_code, response = imap_ssl.store(mail_id, '+FLAGS', '\\Deleted') ## Setting Deleted Flag
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
resp_code, response = imap_ssl.expunge()
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode() if response[0] else None))
############# Close Selected Mailbox #######################
print("\nClosing selected mailbox....")
imap_ssl.close()
As a part of our twelfth example, we are demonstrating how we can mark the mail as important (starred) using store() method.
Our code for this example starts by establishing a connection with the server and then logs in to the server.
It then selects INBOX as a mailbox to work with.
It then retrieves mail ids of all emails in the mailbox.
It then loops through the 5 latest mail ids and sets their flag ('+FLAGS') as '\Flagged' using store() method. This will make mails as important mails.
In our Gmail and Yahoo mail mailboxes, these emails will be starred.
We are then again looping through mail ids and removing '\Flagged' emails from the latest two mails to mark them as unimportant again ('-FLAGS').
We are also printing details of emails (mail id, date, and subject) which are getting marked as important and unimportant.
import imaplib
import email
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
############### Set Mailbox #############
resp_code, mail_count = imap_ssl.select(mailbox="INBOX", readonly=False)
############### Mark few latest mails as important in a given Directory #############
resp_code, mails = imap_ssl.search(None, 'ALL')
mail_ids = mails[0].decode().split()
print("Total Mail IDs : {}\n".format(len(mail_ids)))
print("Flagging Important Mails...")
for mail_id in mail_ids[-5:]:
resp_code, mail_data = imap_ssl.fetch(mail_id, '(RFC822)') ## Fetch mail data.
message = email.message_from_bytes(mail_data[0][1]) ## Construct Message from mail data
print("Mail ID : {}, Date : {}, Subject : {}".format(mail_id, message.get("Date"), message.get("Subject")))
resp_code, response = imap_ssl.store(mail_id, '+FLAGS', '\\Flagged')
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode() if response[0] else response[0]))
############### Mark few latest mails as unimportant in a given Directory #############
print("Unflagging few Mails...")
for mail_id in mail_ids[-2:]:
resp_code, mail_data = imap_ssl.fetch(mail_id, '(RFC822)') ## Fetch mail data.
message = email.message_from_bytes(mail_data[0][1]) ## Construct Message from mail data
print("Mail ID : {}, Date : {}, Subject : {}".format(mail_id, message.get("Date"), message.get("Subject")))
resp_code, response = imap_ssl.store(mail_id, '-FLAGS', '\\Flagged')
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode() if response[0] else response[0]))
############# Close Selected Mailbox #######################
print("\nClosing selected mailbox....")
imap_ssl.close()
As a part of our thirteenth example, we'll explain how we can send NOOP command to the server to indicate no command at all. It can be used to keep the connection alive.
import imaplib
import email
################ IMAP SSL ##############################
with imaplib.IMAP4_SSL(host="imap.gmail.com", port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
print("Connection Object : {}".format(imap_ssl))
############### Login to Mailbox ######################
print("Logging into mailbox...")
resp_code, response = imap_ssl.login("mail2sunny.2309@gmail.com", "app_password")
print("Response Code : {}".format(resp_code))
print("Response : {}\n".format(response[0].decode()))
################## Keeping Connection Alive ###############
resp_code, response = imap_ssl.noop() ## Keep connection Alive
print("Response Code : {}".format(resp_code))
print("Response : {}".format(response[0].decode()))
This ends our small tutorial explaining how we can use IMAP4 protocol through 'imaplib' Python library to perform various operations with a mailbox.
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