Monitoring d’une boite IMAP en python
// juillet 29th, 2009 // Python
Voici un script en python qui permet de monitorer une boite mail via IMAP. Pour chaque nouveau mail contenant une pièce jointe, la pièce jointe est sauvegardée dans un sous-dossier ayant pour nom l’adresse mail de l’expéditeur. Le mail traité est sauvegardé dans un dossier IMAP nommé Backup. Ce script a été écrit en majorité par Suresh Kumar qu’on remercie au passage, j’ai ajouté un système de log avec rotation automatique ainsi quelques autres petites modifs.
import getopt, getpass, os, sys, time import imaplib import email, email.Errors, email.Header, email.Message, email.Utils from time import strftime from time import sleep import random import string import glob import logging import logging.handlers AttachDir = 'Attachments' # Directory where Attachments will be stored SaveAttachments = 1 # Shall Attachements be saved ? imap_server = "xxx.xxx.xxx.xxx" # IP adress of IMAP Server User = "user" # Username of the IMAP mailbox receiveing KDMs Password = "passwd" # Password for the above mailbox Do_sub=1 # Shall the script create subdirectories entry for each sender e-mail Do_backup = 1 # Shall a backup directory be created in mailbox IMAP_backup_Dir= "Backup" # Name of the IMAP backup Directory Frequency = 300 # Time in seconds between two checks exists = 0 name = 0 Do_random = 1 LOG_FILENAME = 'fichier_log.log' my_logger = logging.getLogger('MyLogger') my_logger.setLevel(logging.DEBUG) handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=5242880, backupCount=4) my_logger.addHandler(handler) def dir_check_and_create(directory_name): try: exists = "0" curdir= os.getcwd() list = os.listdir(curdir) for name in list: if name == directory_name: exists = "1" break if exists != "1": os.mkdir(directory_name) exists == "0" except IOError, val: my_logger.debug('Unable to create "%s": %s' % (filename, str(val))) #error('Unable to create "%s": %s' % (filename, str(val))) def write_file(filename, addr, data): if Do_random ==1: tmp_str = "".join(random.sample(string.letters+string.digits, 8)) ext = os.path.splitext(filename)[1] file_name = tmp_str+ext else: file_name=filename if Do_sub ==1: os.chdir(addr) my_logger.debug('Writing '+filename+' as '+file_name+' in folder '+addr) else: my_logger.debug('Writing '+filename+' as '+file_name) fd = open(file_name, "wb") fd.write(data) fd.close() def gen_filename(name, mtyp, addr, date, n): timepart = strftime("%d %b %y %H_%M_%S") file = email.Header.decode_header(name)[0][0] file = os.path.basename(file) my_logger.debug("Downloading file " + file + " sent by " + addr) #print "Downloading file " + file + " sent by " + addr #print "\n" path = os.path.join(AttachDir, file) path =file return path def error(reason): sys.stderr.write('%s\n' % reason) sys.exit(1) def walk_parts(msg, addr, date, count, msgnum): for part in msg.walk(): if part.is_multipart(): continue dtypes = part.get_params(None, 'Content-Disposition') if not dtypes: if part.get_content_type() == 'text/plain': continue ctypes = part.get_params() if not ctypes: continue for key,val in ctypes: if key.lower() == 'name': filename = gen_filename(val, part.get_content_type(), addr, date, count) break else: continue else: attachment,filename = None,None for key,val in dtypes: key = key.lower() if key == 'filename': filename = val if key == 'attachment': attachment = 1 if not attachment: continue filename = gen_filename(filename, part.get_content_type(), addr, date, count) try: data = part.get_payload(decode=1) except: typ, val = sys.exc_info()[:2] my_logger.debug("Error while decoding the attachmentfor message %s error: %s for %s ``%s''" % (msgnum, str(val), part.get_content_type(), filename)) #warn("Error while decoding the attachmentfor message %s error: %s for %s ``%s''" # % (msgnum, str(val), part.get_content_type(), filename)) continue if not data: my_logger.debug("Unable to decode the attachment %s for %s" % (part.get_content_type(), filename)) continue if type(data) is type(msg): count = walk_parts(data, addr, date, count, msgnum) continue if SaveAttachments: exists = "0" try: curdir= os.getcwd() os.chdir(AttachDir) list = os.listdir('.\\') if Do_sub ==1 : for name in list: if name == addr: exists = "1" break if exists == "1": write_file(filename, addr, data) os.chdir(curdir) else: os.mkdir(addr) write_file(filename, addr, data) os.chdir(curdir) exists == "0" os.chdir(curdir) else: write_file(filename, addr, data) os.chdir(curdir) except IOError, val: my_logger.debug('Unable to cereate "%s": %s' % (filename, str(val))) count += 1 return count def process_message(text, msgnum): # Begin message processing try: msg = email.message_from_string(text) except email.Errors.MessageError, val: my_logger.debug("Error while processing message %s : %s" % (msgnum, str(val))) #warn("Error while processing message %s : %s" % (msgnum, str(val))) return text date = msg['Date'] or 'Tue, 09 Apr 1978 00:03:27 +1000' date = time.strftime('%Y_%m_%d.%T', email.Utils.parsedate(date)) addr = email.Utils.parseaddr(msg['From'])[1] attachments_found = walk_parts(msg, addr, date, 0, msgnum) if attachments_found: return '' else: return None def read_messages(fd): data = []; app = data.append for line in fd: if line[:5] == 'From ' and data: yield ''.join(data) data[:] = [] app(line) if data: yield ''.join(data) def process_server(host): global DeleteAttachments try: mbox = imaplib.IMAP4(host) except: typ,val = sys.exc_info()[:2] my_logger.debug('Unable to connect to IMAP server "%s": %s' % (host, str(val))) if User or mbox.state != 'AUTH': user = User or getpass.getuser() if Password == "": pasw = getpass.getpass("Password not provided, please input one now for %s on %s: " % (user, host)) else: pasw = Password try: typ,dat = mbox.login(user, pasw) except: typ,dat = sys.exc_info()[:2] if typ != 'OK': my_logger.debug('unable to open the INBOX folder for "%s" on "%s": %s' % (user, host, str(dat))) mbox.select('Inbox') typ, dat = mbox.search(None, 'ALL') if Do_backup == 1: mbox.create(IMAP_backup_Dir) deleteme = [] for num in dat[0].split(): typ, dat = mbox.fetch(num, '(RFC822)') if typ != 'OK': error(dat[-1]) message = dat[0][1] if process_message(message, num) == '': deleteme.append(num) #if deleteme == []: #print "\n" #print "No mail with attachment found in INBOX" deleteme.sort() for number in deleteme: if Do_backup == 1: mbox.copy(number, 'Backup') mbox.store(number, "+FLAGS.SILENT", '(\\Deleted)') mbox.expunge() mbox.close() mbox.logout() def main(): dir_check_and_create(AttachDir) my_logger.debug("Monitoring IMAP server at " + imap_server + " for mailbox " + User) while 1: process_server(imap_server) printfre = str(Frequency) #my_logger.debug("Sleeping " + printfre + " seconds...") sleep(Frequency) if __name__ == '__main__': try: main() except KeyboardInterrupt: pass
Leave a Reply
You must be logged in to post a comment.