Python: Keep checking new email and alert of further new emails

11,356

Try to use this approach:

Logic is the same as from @tripleee comment.

import time
word = ["href=", "href", "<a href="] #list of strings to search for in email body

#connection to the email server
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('xxxx', 'xxxx')
mail.list()
# Out: list of "folders" aka labels in gmail.
latest_email_uid = ''

while True:
    mail.select("Inbox", readonly=True)
    result, data = mail.uid('search', None, "ALL") # search and return uids instead
    ids = data[0] # data is a list.
    id_list = ids.split() # ids is a space separated string

    if data[0].split()[-1] == latest_email_uid:
         time.sleep(120) # put your value here, be sure that this value is sufficient ( see @tripleee comment below)
    else:
         result, data = mail.uid('fetch', latest_email_uid, '(RFC822)') # fetch the email headers and body (RFC822) for the given ID
         raw_email = data[0][1]
         latest_email_uid == data[0].split()[-1]
         time.sleep(120) # put your value here, be sure that this value is sufficient ( see @tripleee comment below)
Share:
11,356

Related videos on Youtube

idwithin
Author by

idwithin

Updated on June 04, 2022

Comments

  • idwithin
    idwithin almost 2 years

    I have this code that checks the latest email and then goes and does something. Is it possible to write something that keeps checking the inbox folder for new mail? Although I want it to keep checking for the latest new email. Is it getting too complicated if I try and store that it has made one pass? So it doesn't alert about the same email twice about the same email.

    Code:

    import imaplib
    import email
    import Tkinter as tk
    
    word = ["href=", "href", "<a href="] #list of strings to search for in email body
    
    #connection to the email server
    mail = imaplib.IMAP4_SSL('imap.gmail.com')
    mail.login('xxxx', 'xxxx')
    mail.list()
    # Out: list of "folders" aka labels in gmail.
    mail.select("Inbox", readonly=True) # connect to inbox.
    
    result, data = mail.uid('search', None, "ALL") # search and return uids instead
    
    ids = data[0] # data is a list.
    id_list = ids.split() # ids is a space separated string
    latest_email_uid = data[0].split()[-1]
    
    result, data = mail.uid('fetch', latest_email_uid, '(RFC822)') # fetch the email headers and body (RFC822) for the given ID
    
    
    raw_email = data[0][1] # here's the body, which is raw headers and html and body of the whole email
    # including headers and alternate payloads
    
    .....goes and does other code regarding to email html....
    
    • tripleee
      tripleee about 6 years
      In pseudocode, while true: fetch newest message; if it's newer than the previous, display an alert; previous := newest; sleep;
    • tripleee
      tripleee about 6 years
      Python's imaplib doesn't support the IMAP IDLE command but ideally, use that.
    • tripleee
      tripleee about 6 years
      IIRC you shoud be able to get away with something much less brutal than always doing "search all" but not in a /ood place to check right now.
  • tripleee
    tripleee about 6 years
    You want to sleep significantly longer than five seconds; once per minute is already considered fairly aggressive by many IMAP server admins. Depending on your application and expected traffic, checking every five or ten minutes may well be quite sufficient.
  • Kyrylo
    Kyrylo about 6 years
    @tripleee Okay, I will change it :) I do not familiar with IMAP imaplib, so this code is just my thought that I had when finished reading the question.
  • idwithin
    idwithin about 6 years
    I needed to restructure the else statement to get everything to work and then run my command. In this order - latest_email_uid == data[0].split()[-1] > result, data = mail.uid('fetch', latest_email_uid, '(RFC822)') > raw_email = data[0][1] It runs and waits yet when it seems to run again I get this error..... in next comment.....
  • idwithin
    idwithin about 6 years
    Traceback (most recent call last): File "beta_1.4.py", line 36, in <module> result, data = mail.uid('search', None, "ALL") # search and return uids instead File "C:\Python27\lib\imaplib.py", line 773, in uid ', '.join(Commands[command]))) imaplib.error: command SEARCH illegal in state LOGOUT, only allowed in states SELECTED
  • Kyrylo
    Kyrylo about 6 years
    @idwithin Can you move mail.select("Inbox", readonly) inside while True? Put it on the first line after while True statement.
  • idwithin
    idwithin about 6 years
    That fixed it and worked with testing new emails sent. Thanks so much :)
  • Admin
    Admin over 5 years
    @Kyrylo : Getting the error Traceback (most recent call last): File "C:/Users/sh/PycharmProjects/DemoReadmail/demo.py", line 23, in <module> mail.select("INBOX") AttributeError: 'Message' object has no attribute 'select' after using while loop, the file is downloaded once and when it goes to check for new mails (while loop) then i got this error.