#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
# Se è andato tutto bene:
# sys.exit(0)
# Se non ho rilevato la mail richiesta
# sys.exit(1)
# Se ho avuto un errore sulla scrittura del body della mail cercata su file
# sys.exit(2)
# Errore in lettura del uid del messaggio id_value: id_value
# sys.exit(3)
# Errore nella copia del messaggio msg_uid_found: msg_uid_found
# sys.exit(4)
# Erroe nella copia della mail sul server imap
# sys.exit(5)
# Errore nella rimozzione del messaggio msg_uid: msg_uid_found
# sys.exit(6)
# Erroe nella delete della mail msg_uid_found sul server imap
# sys.exit(7)
'''

import imaplib
import re
import email
import sys
import codecs
import datetime
from pprint import pprint

from imaplib_connect import open_connection
from imaplib_list_parse import parse_list_response, parse_uid

CONTENT = 'Ricevuta di avvenuta consegna'
recipient = ""
writemode = 'wb'
destination_folder = '<ARCHIVIO>'
message_found = 0
recipient_found = 0
email_found = 0

if __name__ == "__main__":
    from optparse import OptionParser
    usage = "usage: %prog [options] argument"
    parser = OptionParser(usage=usage)
    parser.set_defaults(mode="query")
    parser.add_option("--server_mail", dest="server_mail", action="store", type="string",
                      help="set server_mail [REQUIRED]")
    parser.add_option("--user_mail", dest="user_mail", action="store", type="string",
                      help="set user_mail [REQUIRED]")
    parser.add_option("--pass_mail", dest="pass_mail", action="store", type="string",
                      help="set pass_mail [REQUIRED]")
    parser.add_option("-s", "--subject_mail", dest="subject_mail", action="store", type="string",
                      help="set subject_mail [REQUIRED]")
    parser.add_option("-d", "--recipient_mail", dest="recipient_mail", action="store", type="string",
                      help="set recipient_mail")
    parser.add_option("-b", "--data_mail_invio", dest="data_mail_invio", action="store", type="string",
                      help="set data_mail_invio")
    parser.add_option("-f", "--file_name_output", dest="file_name_output", action="store", type="string",
                      help="set file name to process [REQUIRED if interrogate mode]")
    parser.add_option("-m", "--mode", dest="mode", action="store", type="string",
                      help="set mode interrogate/archieve. 'i' for interrogate and 'a' for archieve. if not provided mode=interrogate [REQUIRED]")
    parser.add_option("-a", "--mail_destination_folder", dest="mail_destination_folder", action="store", type="string",
                      help="set mail folder name to process [REQUIRED if archieve mode]")
    parser.add_option("-t", "--test_mode", dest="test_mode", action="store", type="string",
                      help="set test_mode true to test folder structure")
    (options, args) = parser.parse_args()
    
    if not options.server_mail or not options.user_mail or not options.pass_mail:
        parser.error("server param required; try -h")
    if not options.test_mode:
        if not options.mode:
            options.mode = "i"
        if options.mode != 'i' and options.mode != 'a':
            parser.error("-m mode wrong. mode allowed are: i for interrogate mode or a for archieve mode")
        if not options.subject_mail:
            parser.error("-s subject_mail  is required; try -h")
        if not options.data_mail_invio:
            parser.error("-b data_mail_invio  is required; try -h")
        if options.mode == 'a' and not options.file_name_output:
            parser.error("with mode a -f param is required; try -h")
        if options.mode == 'a' and not options.mail_destination_folder:
            parser.error("with mode a -a param is required; try -h")
        if options.mail_destination_folder:
            destination_folder = options.mail_destination_folder
    def errlog(msg):
        print >>sys.stderr,"%s - %s" % (datetime.datetime.now().ctime(), msg)
    
    CONTENT = options.subject_mail
    CONTENT_list = []
    if CONTENT:
    	CONTENT_list = CONTENT.split("|")
    if options.recipient_mail and options.recipient_mail != "":
    	recipient = options.recipient_mail
    connect_verbose = False
    mail = open_connection(options.server_mail,options.user_mail,options.pass_mail,connect_verbose)
    msg_uid_list = []

    if options.test_mode:
		try:
		    typ, data = mail.list()
		except Exception as e:
		    print e
		    sys.exit(8)
		finally:
		    mail.logout()
		print 'Response code:', typ
		print 'data: ',data
		for line in data:
		    print 'Server response:', line
		    flags, delimiter, mailbox_name = parse_list_response(line)
		    print 'Parsed response:', (flags, delimiter, mailbox_name)
		sys.exit(0)
    
    try:
        mail.select('INBOX', readonly=False)
        #typ, msg_data = mail.search(None, "ALL")
        #print options.data_mail_invio
        date = datetime.datetime.strptime(options.data_mail_invio, "%Y%m%d").date().strftime("%d-%b-%Y")
        typ, msg_data = mail.search(None, '(SENTSINCE {date})'.format(date=date))
        ids = msg_data[0] # data is a list.
        id_list = ids.split() # ids is a space separated string
        uid_list = []
        
        for id_value in id_list:
            esp, data_mail = mail.fetch(id_value, "(UID)")
            msg_uid = parse_uid(data_mail[0])
            uid_list.append(msg_uid)
        for id_value in id_list:
			elem_to_found_for_list = len(CONTENT_list)
			#print "mail: ",id_value," elem_to_found_for_list: ",elem_to_found_for_list
			result, data = mail.fetch(id_value, "(RFC822)")
			raw_email = data[0][1] # here's the body, which is raw text of the whole message
			email_message = email.message_from_string(raw_email)
			message_found = 0
			recipient_found = 0
			for part in email_message.walk():
				#print "mail: ",id_value," parte controllata: ",part
				type_ext = part.get_content_type()
				if type_ext == 'text/plain':
					body = part.get_payload(decode=True)
					#print "Body: ",body
					#print "CONTENT: ",CONTENT
					#print "Find: ",body.find(CONTENT)
					#if body.find(CONTENT) != -1:
					#    message_found = 1
					#    #print "testo rilevato"
					if CONTENT:
						for search_string in CONTENT_list:
							if search_string == "" or body.find(search_string) != -1:
								elem_to_found_for_list = elem_to_found_for_list - 1
					#print "Dopo verifica numero parti restatnti da ricercare: ",elem_to_found_for_list
					#print "Destinatario: ",recipient
					if recipient and recipient in body:
						recipient_found = 1
						#print "destinatario rilevato"
					#if ((( elem_to_found_for_list == 0 or message_found == 1 ) and recipient_found == 1 ) or (( elem_to_found_for_list == 0 or message_found == 1 ) and not recipient )):
					if ((( elem_to_found_for_list == 0 ) and recipient_found == 1 ) or (( elem_to_found_for_list == 0 ) and not recipient )):
						email_found = 1
						#print "testo rilevato e se specificato rilevato anche destinatario"
						#print ( body )
						#print 'mode: ', options.mode == 'a'
						if options.mode == 'i':
						    #Scrittura su file dei dati del body
						    try:
						        with open(options.file_name_output, writemode) as f:
						            f.write(body)
						    except Exception as e:
						        # Se ho avuto un errore sulla scrittura del body della mail cercata su file
						        print 'Errore in scrittura file: ', options.file_name_output
						        print e
						        sys.exit(2)
						if options.mode == 'a':
						    #Archivio mail nella cartella richiesta
						    try:
						        esp, data_mail = mail.fetch(id_value, "(UID)")
						        print esp, data_mail, data_mail[0]
						        msg_uid = parse_uid(data_mail[0])
						        #print msg_uid
						        msg_uid_list.append(msg_uid)
						    except Exception as e:
						        # Se ho avuto un errore sulla lettura del uid del messaggio
						        print 'Errore in lettura del uid del messaggio id_value: ', id_value
						        print e
						        sys.exit(3)
						elem_to_found_for_list = None
						#Una volta rilevata la mail ricercata ed eseguita l'operazione richiesta non esco dal ciclo di analisi del messaggio
						break
        # Se non ho rilevato la mail richiesta
        if email_found == 0:
            print 'mail non rilevata'
            sys.exit(1)
        else:
        	print 'mail rilevata'
        if options.mode == 'a' and len(msg_uid_list) > 0:
            for msg_uid_found in msg_uid_list:
                #Archivio mail nella cartella richiesta
                try:
                    
                    result = mail.uid('COPY', msg_uid_found, destination_folder)
                    
                    if result[0] == 'OK':
                        try:
                            mov, data_mail_delete = mail.uid('STORE', msg_uid_found , '+FLAGS', '(\Deleted)')
                            print mov, data_mail_delete, data_mail_delete[0]
                            mail.expunge()
                            if mov != 'OK':
                                print 'Erroe nella delete della mail ',msg_uid_found,' sul server imap'
                                print data_mail_delete, data_mail_delete[0]
                                sys.exit(7)
                        except Exception as e:
                            # Se ho avuto un errore nella rimozzione del messaggio
                            print 'Errore nella rimozzione del messaggio msg_uid: ', msg_uid_found
                            print e
                            sys.exit(6)
                    else:
                        print 'Erroe nella copia della mail sul server imap'
                        print result, result[1]
                        sys.exit(5)
                except Exception as e:
                    # Se ho avuto un errore nella copia del messaggio
                    print 'Errore nella copia del messaggio msg_uid_found: ', msg_uid_found
                    print e
                    sys.exit(4)
    finally:
        try:
            mail.close()
        except:
            pass
        mail.logout()
    sys.exit(0)
