Get Only NEW Emails Imaplib and Python

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

Get only NEW Emails imaplib and python


Asked 10 years, 3 months ago Modified 4 months ago Viewed 79k times

This is a smaller portion of a bigger project. I need to only get unread emails and a parse
their headers. How can I modify the following script to only get unread emails?
31
conn = imaplib.IMAP4_SSL(imap_server)
conn.login(imap_user, imap_password)

status, messages = conn.select('INBOX')

if status != "OK":
print "Incorrect mail box"
exit()

print messages

python imaplib

Share Follow asked Nov 3, 2012 at 15:46


David Vasandani
1,722 8 28 52

I forgot to also ask for the body of the email. –  David Vasandani Nov 3, 2012 at 16:08

6 Answers Sorted by: Highest score (default)

Your privacy
By clicking “Accept all cookies”, you agree Stack
Exchange can store cookies on your device and disclose
information in accordance with our Cookie Policy.

Accept all cookies

Customize settings

1 of 8 12/02/23, 7:44 am
Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

Something like this will do the trick.

46 conn = imaplib.IMAP4_SSL(imap_server)

try:
(retcode, capabilities) = conn.login(imap_user, imap_password)
except:
print sys.exc_info()[1]
sys.exit(1)

conn.select(readonly=1) # Select inbox or default namespace


(retcode, messages) = conn.search(None, '(UNSEEN)')
if retcode == 'OK':
for num in messages[0].split(' '):
print 'Processing :', message
typ, data = conn.fetch(num,'(RFC822)')
msg = email.message_from_string(data[0][1])
typ, data = conn.store(num,'-FLAGS','\\Seen')
if ret == 'OK':
print data,'\n',30*'-'
print msg

conn.close()

There's also a duplicate question here - Find new messages added to an imap mailbox
since I last checked with python imaplib2?

Two useful functions for you to retrieve the body and attachments of the new message you
detected (reference: How to fetch an email body using imaplib in python?) -

def getMsgs(servername="myimapserverfqdn"):
usernm = getpass.getuser()
passwd = getpass.getpass()
subject = 'Your SSL Certificate'
conn = imaplib.IMAP4_SSL(servername)
conn.login(usernm,passwd)
conn.select('Inbox')
typ, data = conn.search(None,'(UNSEEN SUBJECT "%s")' % subject)
for num in data[0].split():
typ, data = conn.fetch(num,'(RFC822)')
msg = email.message_from_string(data[0][1])
typ, data = conn.store(num,'-FLAGS','\\Seen')
Your privacy
yield msg
By clicking “Accept all cookies”, you agree Stack
Exchange can store cookies
def getAttachment on your):
(msg,check device and disclose
information in accordance
for part with our Cookie Policy.
in msg.walk():
if part.get_content_type() == 'application/octet-stream':
if check(part.get_filename()):
returnAccept all cookies
part.get_payload(decode=1)

Customize settings
PS: If you pass by in 2020 after python 2.7 death: replace
email.message_from_string(data[0][1]) with email.message_from_bytes(data[0][1])

2 of 8 12/02/23, 7:44 am
Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

Share Follow edited Feb 12, 2020 at 13:56 answered Nov 3, 2012 at 15:53
Espoir Murhabazi Calvin Cheng
5,597 4 43 69 35.1k 36 115 166

1 Updated my answer with two new functions getMsgs and getAttachment which you can then
use in the for message in messages[0].split(' '): for-loop. – Calvin Cheng Nov 3, 2012 at
16:27

2 A note on marking messages as seen. Changing the line typ, data = conn.store(num,'-
FLAGS','\\Seen') to typ, data = conn.store(num,'+FLAGS','\\Seen') fixed it for me.
– concentricpuddle Jun 10, 2014 at 8:32

9 where is ret defined? – user1767754 Sep 29, 2014 at 9:47

1 your answer does not work in every case. i try to check for unseen messages and the first
message in the list of unseen messages has ['flags', ('RFC822', 'message') while the
others have [('RFC822', 'message')] . Either this is some IMAP strangeness, or imaplib2 has a
weird output format. – allo Mar 8, 2015 at 14:22

1 What is check() ? Python does not find it – user6165050 Apr 26, 2016 at 8:01

Your privacy
By clicking “Accept all cookies”, you agree Stack
Exchange can store cookies on your device and disclose
information in accordance with our Cookie Policy.

Accept all cookies

Customize settings

3 of 8 12/02/23, 7:44 am
Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

The above answer does not actually work anymore or maybe never did but i modified it so
it returns only unseen messages, it used to give : error cannot parse fetch command or
31 something like that here is a working code :

mail = imaplib.IMAP4_SSL('imap.gmail.com')
(retcode, capabilities) = mail.login('email','pass')
mail.list()
mail.select('inbox')

n=0
(retcode, messages) = mail.search(None, '(UNSEEN)')
if retcode == 'OK':

for num in messages[0].split() :


print 'Processing '
n=n+1
typ, data = mail.fetch(num,'(RFC822)')
for response_part in data:
if isinstance(response_part, tuple):
original = email.message_from_string(response_part[1])

print original['From']
print original['Subject']
typ, data = mail.store(num,'+FLAGS','\\Seen')

print n

I think the error was coming from the messages[0].split(' ') but the above code should
work fine.

Also, note the +FLAGS instead of -FLAGS which flags the message as read.

EDIT 2020: If you pass by in 2020 after python 2.7 death: replace
email.message_from_string(data[0][1]) with email.message_from_bytes(data[0][1])

Share Follow edited Feb 12, 2020 at 13:57 answered Apr 14, 2015 at 14:15
Espoir Murhabazi Amr El Aswar
5,597 4 43 69 3,365 2 22 36

Your
7 privacy
And of course, do not forget to import imaplib and email – Abdul Rauf Apr 20, 2018 at 15:03
By clicking “Accept all cookies”, you agree Stack
1 Howcan
Exchange do Istore
get the mail body
cookies from
on your original
device and? disclose
– Shahriar Rahman Zahin Sep 15, 2020 at 10:10
information in accordance with our Cookie Policy.

Accept all cookies

Customize settings

4 of 8 12/02/23, 7:44 am
Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

You may use imap_tools package: https://pypi.org/project/imap-tools/

10 from imap_tools import MailBox, AND


with MailBox('imap.mail.com').login('test@mail.com', 'password', 'INBOX') as
mailbox:
# get unseen emails from INBOX folder
for msg in mailbox.fetch(AND(seen=False)):
print(msg.date, len(msg.html or msg.text))

Share Follow edited Feb 10, 2021 at 10:50 answered Oct 9, 2019 at 17:57
Vladimir
5,801 2 29 35

original = email.message_from_string(response_part[1])

7
Needs to be changes to:

original = email.message_from_bytes(response_part[1])

Share Follow edited Feb 12, 2016 at 17:28 answered Aug 28, 2015 at 17:09
Kara Daniel Karpienia
6,065 16 51 57 71 1 1

1 This is probably a necessary fix for Python 3, but does not attempt to answer the question of the
OP, and should be a comment instead, apparently in reference to Amro's answer. – tripleee Feb 12,
2016 at 11:39

Your privacy
By clicking “Accept all cookies”, you agree Stack
Exchange can store cookies on your device and disclose
information in accordance with our Cookie Policy.

Accept all cookies

Customize settings

5 of 8 12/02/23, 7:44 am
Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

I've managed to get this to work using Gmail:

3 import datetime
import email
import imaplib
import mailbox

EMAIL_ACCOUNT = "your@gmail.com"
PASSWORD = "your password"

mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(EMAIL_ACCOUNT, PASSWORD)
mail.list()
mail.select('inbox')
result, data = mail.uid('search', None, "UNSEEN") # (ALL/UNSEEN)
i = len(data[0].split())

for x in range(i):
latest_email_uid = data[0].split()[x]
result, email_data = mail.uid('fetch', latest_email_uid, '(RFC822)')
# result, email_data = conn.store(num,'-FLAGS','\\Seen')
# this might work to set flag to seen, if it doesn't already
raw_email = email_data[0][1]
raw_email_string = raw_email.decode('utf-8')
email_message = email.message_from_string(raw_email_string)

# Header Details
date_tuple = email.utils.parsedate_tz(email_message['Date'])
if date_tuple:
local_date =
datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple))
local_message_date = "%s" %(str(local_date.strftime("%a, %d %b %Y
%H:%M:%S")))
email_from =
str(email.header.make_header(email.header.decode_header(email_message['From'])))
email_to =
str(email.header.make_header(email.header.decode_header(email_message['To'])))
subject =
str(email.header.make_header(email.header.decode_header(email_message['Subject'])))

# Body details
for part in email_message.walk():
if part.get_content_type() == "text/plain":
body = part.get_payload(decode=True)
Your privacy file_name = "email_" + str(x) + ".txt"
By clicking “Acceptoutput_file = open
all cookies”, you (file_name,
agree Stack 'w')
output_file.write("From: %s\nTo: %s\nDate: %s\nSubject: %s\n\nBody:
Exchange can store cookies on your device and disclose
\n\n%s" %(email_from, email_to,local_message_date, subject, body.decode('utf-
information in accordance with our Cookie Policy.
8')))
output_file.close()
else: Accept all cookies
continue

Customize settings
Share Follow answered Aug 3, 2016 at 12:48
Edward Chapman
509 6 8

6 of 8 12/02/23, 7:44 am
Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

509 6 8

I didn't like the existing solutions so I decided to make a sister library for my email sender
called Red Box.
0
Here is an example of how to fetch new messages and process them:

from redbox import EmailBox

# Create email box instance


box = EmailBox(
host="imap.example.com",
port=993,
username="me@example.com",
password="<PASSWORD>"
)

# Select an email folder


inbox = box["INBOX"]

# Search and process messages


for msg in inbox.search(unseen=True):

# Process the message


print(msg.headers)
print(msg.from_)
print(msg.to)
print(msg.subject)
print(msg.text_body)
print(msg.html_body)

# Set the message as read/seen


msg.read()

There is also a query language if you need complex logical operations. You can also easily
access various parts of the messages if needed.

To install:

pip install redbox

Your privacy
ByLinks:
clicking “Accept all cookies”, you agree Stack
Exchange can store cookies on your device and disclose
• Source
information code
in accordance with our Cookie Policy.

• Documentation
Accept all cookies

Share Follow answered Oct 1, 2022 at 17:24


Customize settings
miksus
1,666 1 13 30

7 of 8 12/02/23, 7:44 am
Get only NEW Emails imaplib and python - Stack Overflow https://stackoverflow.com/questions/13210737/get-only-new-emails-ima...

Your privacy
By clicking “Accept all cookies”, you agree Stack
Exchange can store cookies on your device and disclose
information in accordance with our Cookie Policy.

Accept all cookies

Customize settings

8 of 8 12/02/23, 7:44 am

You might also like