• email.py


    import os
    import argparse
    import yaml
    import smtplib
    import csv
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from urllib import unquote
    import logging
    import logging.handlers
    
    logger = logging.getLogger()
    error_list = []
    all_error_file_list=[]
    
    def extension(filename):
        """
        get file extension
        :param filename:
        :return:
        """
        ext = os.path.splitext(filename)[1]
        if ext.startswith('.'):
            # os.path.splitext retains . separator
            ext = ext[1:]
        return ext
    
    
    def list_file(file_name, list):
        """
        get all failed file list ,contains sub folder
        :param file_name: file name or folder name
        :param list:
        :return:
        """
        if os.path.isdir(file_name):
            for s in os.listdir(file_name):
                list_file(os.path.join(file_name, s), list)
        else:
            ext = extension(file_name)
            if ext == "failed":
                list.append(file_name)
    
    
    def read_email_record(faild_path):
        """
        read last failed file record
        :param faild_path:
        :return:
        """
        record = os.path.join(faild_path, "email_record.txt")
        if not os.path.isfile(record):
            return {}
        try:
            return yaml.load(open(record))
        except Exception as err:
            return {}
    
    
    def rewrite_record(args):
        """
        save record file
        :param args:
        :return:
        """
        if not error_list:
            return
        record = os.path.join(args.failed_path, "email_record.txt")
        map = {}
        for s in all_error_file_list:
            map[s] = "emailed"
        f = open(record, "w")
        yaml.dump(map, f, default_flow_style=False)
        f.close()
    
    
    def process(args):
        """
        process :
            * list all failed files
            * read record list
            * remove duplicate data
        :param args:
        :return:
        """
        faild_path = args.failed_path
        if not os.path.isdir(faild_path):
            logger.error("failed path:%s is not exist, exist", faild_path)
            return
        list_file(faild_path, all_error_file_list)
        record_map = read_email_record(faild_path)
        if not record_map:
            error_list.extend(all_error_file_list)
        else:
            for file in all_error_file_list:
                if not record_map.has_key(file):
                    error_list.append(file)
    
    
    def generate_body(s3path):
        """
        generate email body
        :return:
        """
        body = """<h4>The following billing csv files are format failed,please check</h4>
                """
        logger.info("failed file list as below:")
        # list all failed list which need send email
        for s in error_list:
            # define line number from 0
            line_num = 0
            # to get error file name and path , just support {orgid}/{failed_file} format
            ps = os.path.split(s)
            # to regenerate new web path, such as s3://{bucket}/xxx/{orgid}/{fail_file}
            s3 = os.path.join(s3path, os.path.split(ps[0])[1], ps[1])
            # generate html body
            body += "<hr>"
            # add file name with link
            body += """<div>File: <a href="%s">%s<a></div>""" % (s3, ps[1])
            # add URL which can copy
            body += "<div>URL: %s</div>" % (s3)
            # add logger info
            logger.info("-"*50)
            logger.info("file:[%s]",s)
            # lines which read each time
            total_rows_each_read=10000000
            # open failed file
            with open(s, 'r') as f:
                # read file in loop
                while 1:
                    # get lines array list
                    lines = f.readlines(total_rows_each_read)
                    if not lines:
                        break
                    # check each line with csv , when failed ,
                    # generate new array from failed index and re-check until finished
                    while len(lines)>0:
                        # check csv format with strict = True
                        reader=csv.reader(lines, strict=True)
                        # define array index
                        i = 0
                        try:
                            # get rows of each line
                            for row in reader:
                                # when row is csv format , array index will ++
                                i += 1
                                line_num += 1
                                for item in row:
                                    # check each column whether with 
     , if yes ,will add line number
                                    if str(item).find('
    ')>0:
                                        i += 1
                                        line_num += 1
                            # when all lines is correct , array will set to empty to break loop
                            lines=[]
                        # get Exceptions
                        except Exception as err:
                            # when error occur , line number will increase 1
                            line_num += 1
                            #line_num += reader.line_num
                            line = lines[i]
                            # generate each error line information
                            body += "<div></div><br><br>"
                            body += "<li><div>Error line number: [#%s] </div></li>" 
                                    "<div>#Exceptions: [%s]</div>" % (line_num, err)
                            body += """<div>#Error row data as below:</div>
                                       <div>%s</div>""" % line
                            if (i+1) == len(lines):
                                lines=[]
                            else:
                                tmp=lines[i+1:]
                                lines = tmp
        body += "<hr>"
        return body
    
    
    def email_sender(args):
        """
        send email ,iterator each receiver then send email
        :param args:
        :return:
        """
        subject = "Error Pipeline CSV File List"
        #if not error_list:
        #    return False
        #body = generate_body(args.s3url)
        body = "test"
        emails = args.email
        smtp_host = args.smtpHost
        smtp_port = args.smtpPort
        username = args.username
        password = args.password
        sent_from = args.sentFrom
    
        if emails:
            mail_server = smtplib.SMTP()
            try:
                msg = MIMEMultipart()
                msg['From'] = sent_from
                msg['Subject'] = subject
                msg.attach(MIMEText(body, 'html'))
                mail_server.connect(smtp_host, smtp_port)
                mail_server.ehlo()
                mail_server.starttls()
                mail_server.ehlo()
                if password and smtp_host != 'eng-smtp.calix.local':
                    mail_server.login(username, unquote(password))
                for recipient in emails:
                    logger.info("send email to %s", recipient)
                    msg['To'] = recipient
                    mail_server.sendmail(sent_from, recipient, msg.as_string())
            except Exception as err:
                logger.error("send email failed:%s", err)
                return False
            finally:
                if mail_server:
                    mail_server.close()
            return True
        return False
    
    
    def init_log(log_file):
        """
        init logger
        :param log_file:
        :return:
        """
        log_path = os.path.split(log_file)[0]
        if not os.path.isdir(log_path):
            os.makedirs(log_path)
        logger.setLevel(logging.DEBUG)
        handler = logging.handlers.RotatingFileHandler(log_file,
                                                       maxBytes=20 * 1024 * 1024,
                                                       backupCount=5,
                                                       )
        fmt = '%(asctime)s-[%(filename)s:%(lineno)s]-[%(levelname)s]- %(message)s'
        formatter = logging.Formatter(fmt)
        handler.setFormatter(formatter)
        logger.addHandler(handler)
    
    
    def main():
        parser = argparse.ArgumentParser(description=__doc__,
                                         formatter_class=argparse.RawDescriptionHelpFormatter)
        parser.add_argument('--failed_path', default='/var/tmp/billing/', help='store failed files')
        parser.add_argument('-e', '--email', action='append',
                            help="To send multiple emails --email <email-address-1> --email <email-address-2> ...")
        parser.add_argument('--smtpHost', type=str, help="Host of SMTP server", required=False,
                            default="outlook.office365.com")
        parser.add_argument('--smtpPort', type=int, help="Port of SMTP server", required=False, default=587)
        parser.add_argument('--username', type=str, help="outlook username", required=False)
        parser.add_argument('--password', type=str, help="outlook password", required=False)
        parser.add_argument('--sentFrom', type=str, help="outlook email", required=False,
                            default="noreply-compass-fa@calix.com")
        parser.add_argument('--logfile', help='logger file name', required=False,
                            default='/var/log/sxadp-api-server/scan_failed_email.log')
        parser.add_argument('--s3url',type=str,help="billing s3 URL ",required=False)
        args = parser.parse_args()
        init_log(args.logfile)
        #process(args)
        if email_sender(args):
            print "done"
            #rewrite_record(args)
    
    
    if __name__ == '__main__':
        main()
  • 相关阅读:
    执行上下文和作用域,作用域链
    学习笔记一:定位
    exports和module.exports的区别——学习笔记
    伪类和伪元素
    visibility和display
    CSS选择器,层叠
    Servlet乱码处理-------续集
    Servlet的乱码处理手记
    前端框架之Semantic UI
    最完整的Oracle11g 概述
  • 原文地址:https://www.cnblogs.com/tben/p/8961184.html
Copyright © 2020-2023  润新知