Пример #1
0
 def close(self):
     try:
         self.connection.close()
         return True
     except:
         Logger.error(traceback.format_exc())
         return False
Пример #2
0
    def get_new_mail_ids(self):
        try:
            # 连接到POP3服务器:
            self.pop3_session = poplib.POP3(self.pop3_server)

            # 身份认证:
            self.pop3_session.user(self.r_account)
            self.pop3_session.pass_(self.r_password)

            # 获取邮件唯一编号
            resp, mails, octets = self.pop3_session.uidl()

            # 获取邮件唯一编号和在服务器中的索引
            mail_dict = dict()
            for mail_idx_id in mails:
                twice = mail_idx_id.split()
                mail_idx = int(twice[0])
                mail_id = twice[1]
                mail_dict[mail_idx] = mail_id

            # 过虑已读邮件
            for mail_idx, mail_id in mail_dict.items():
                if self.recorder.exist(mail_id):
                    del mail_dict[mail_idx]

            # 返回结果
            return mail_dict
        except:
            Logger.error(traceback.format_exc())
            return None
Пример #3
0
 def __init__(self, file_name, stay_seconds):
     try:
         self.file_name = file_name
         self.stay_seconds = stay_seconds
         self.dict = dict()
         self.load_from_disk()
         self.update = False
     except:
         Logger.error(traceback.format_exc())
Пример #4
0
 def put(self, a_key):
     try:
         if isinstance(a_key, str):
             a_key = a_key.decode('utf-8')
         self.dict[a_key] = time.time()
         self.update = True
         return True
     except:
         Logger.error(traceback.format_exc())
         return False
Пример #5
0
 def filter(self, mail_info):
     try:
         if not self.__is_leave(mail_info):
             return False
         if self.__is_discard(mail_info):
             return False
         return True
     except:
         Logger.error(traceback.format_exc())
         return True
Пример #6
0
 def load_from_disk(self):
     try:
         with open(self.file_name, 'ab+') as content_file:
             content_file.seek(0, 0)
             content = content_file.read()
             if content:
                 self.dict = json.loads(content)
         return True
     except:
         Logger.error(traceback.format_exc())
         return False
Пример #7
0
 def put(self, a_key):
     try:
         language = 'INSERT OR REPLACE INTO mails(key, time) VALUES("%s", "%s")' % (
             a_key, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
         cursor = self.connection.execute(language)
         cursor.execute(language)
         self.connection.commit()
         return True
     except:
         Logger.error(traceback.format_exc())
         return False
Пример #8
0
 def flush_to_disk(self):
     try:
         if not self.update:
             return True
         self.update = False
         content = json.dumps(self.dict, ensure_ascii=False)
         with open(self.file_name, 'w') as content_file:
             content_file.write(content)
         return True
     except:
         Logger.error(traceback.format_exc())
         return False
Пример #9
0
    def load(self, xml_file):
        try:
            root = xml.etree.ElementTree.parse(xml_file).getroot()
            for child in root:
                if child.tag == 'leave':
                    self.__parse(child, leave=True)

                if child.tag == 'discard':
                    self.__parse(child, leave=False)
            return True
        except:
            Logger.error(traceback.format_exc())
            return False
Пример #10
0
 def clear_dead(self):
     try:
         now = time.time()
         for key, value in self.dict.items():
             stay = now - value
             if stay > self.stay_seconds:
                 del self.dict[key]
                 self.update = True
                 Logger.info('del self.dict[%s]' % key)
         return True
     except:
         Logger.error(traceback.format_exc())
         return False
Пример #11
0
 def guess_charset(cls, root):
     try:
         # 先从root对象获取编码:
         charset = root.get_charset()
         if charset is None:
             # 如果获取不到,再从Content-Type字段获取:
             content_type = root.get('Content-Type', '').lower()
             pos = content_type.find('charset=')
             if pos >= 0:
                 charset = content_type[pos + 8:].strip()
         return charset
     except:
         Logger.error(traceback.format_exc())
         return None
Пример #12
0
    def handle(self):
        try:
            # 获取邮件唯一编号
            mail_dict = self.get_new_mail_ids()

            # 依次处理所有邮件
            for mail_idx, mail_id in mail_dict.items():
                self.handle_one(mail_idx, mail_id)

            # recorder内存刷到磁盘
            Logger.info("close sqlite")
            self.recorder.close()
        except:
            Logger.error(traceback.format_exc())
Пример #13
0
 def __parse(self, e, leave):
     for item in e:
         rule = Rule(leave)
         for child in item:
             if child.tag == 'from':
                 rule.from_address = child.text
             if child.tag == 'to':
                 rule.to_address = child.text
             if child.tag == 'cc':
                 rule.cc_address = child.text
             if child.tag == 'subject':
                 rule.subject = child.text
             if child.tag == 'content':
                 rule.content = child.text
         if leave:
             self.__leave.append(rule)
         else:
             self.__discard.append(rule)
         Logger.info(str(rule))
Пример #14
0
    def handle_one(self, mail_idx, mail_id):
        try:
            Logger.info("get mail[%s]" % mail_idx)
            resp, lines, octets = self.pop3_session.retr(mail_idx)
            msg_content = '\r\n'.join(lines)
            root = Parser().parsestr(msg_content)

            # 记录邮件
            self.recorder.put(mail_id)

            # 解析邮件
            mail_info = self.parse_mail(root)
            if not mail_info:
                return

            # 过滤邮件
            msg = "idx[{}], id[{}], from[{}], to[{}], cc[{}], subject[{}]". \
                format(mail_idx,
                       mail_id,
                       mail_info.from_address,
                       mail_info.to_address,
                       mail_info.cc_address,
                       mail_info.subject)

            if not self.filters.filter(mail_info):
                Logger.report("filter: " + msg)
                return

            # 发送邮件
            Logger.report("send: " + msg)
            if self.send_flag:
                self.send_mime(root)
            else:
                Logger.report(mail_info.content)
        except:
            Logger.error(traceback.format_exc())
Пример #15
0
def loop_once(r_account, r_password, pop3_server,
              s_account, s_password, smpt_server,
              recorder_file, filter_file,
              send_flag, target_account,
              idx):
    """
    :type r_account: str
    :type r_password: str
    :type pop3_server: str
    :type s_account: str
    :type s_password: str
    :type recorder_file: str
    :type filter_file: str
    :type smpt_server: str
    :type send_flag: bool
    :type target_account: str
    :type idx: int
    :return:
    """
    try:
        # 打印标志
        Logger.info("-----------------------%s--------------------------" % idx)
        # 初始化已读邮件记录
        recorder = DBDict(recorder_file)

        # 初始化过滤策略
        filters = Filter()
        if not filters.load(filter_file):
            Logger.error("init mail filter error")
            return False

        # 初始化邮件 proxy
        proxy = MailFilterProxy(r_account, r_password, pop3_server,
                                s_account, s_password, smpt_server,
                                recorder, filters,
                                send_flag, target_account)
        proxy.handle()
    except:
        Logger.error(traceback.format_exc())
Пример #16
0
    def send_mime(self, root):
        """
        :type root: MIMEBase
        """
        try:
            # 显示原始信息
            for key in root.keys():
                raw_header = 'old_key[%s] ====> [%s]' % (key, root.get(key))
                Logger.info(raw_header)

            # 仅保留以下 Header
            left_header = ('from',
                           'boundary',
                           'content-type',
                           'mime-version',
                           'subject',
                           'date',
                           'message-id',
                           'content-transfer-encoding')
            for key in root.keys():
                little = key.lower()
                if little not in left_header:
                    del root[key]
                    Logger.info("delete key[%s]" % key)
            root['to'] = self.target_account

            # 打印新key
            # for key in root.keys():
            #     raw_header = 'new_key[%s] ====> [%s]' % (key, root.get(key))
            #     Logger.info(raw_header)

            # 发送邮件
            server = smtplib.SMTP(self.smpt_server, 25)
            server.login(self.s_account, self.s_password)
            server.sendmail(self.s_account, [self.target_account], root.as_string())
            server.quit()
        except:
            Logger.error(traceback.format_exc())
Пример #17
0
 def __init__(self, file_name):
     try:
         self.file_name = file_name
         self.connection = sqlite3.connect(file_name)
     except:
         Logger.error(traceback.format_exc())
Пример #18
0
    def parse_mail(self, root):
        try:
            mail_info = MailInfo()

            # from
            value = root.get('From', '')
            values = self.parse_address(value)
            if values:
                for (header, address) in values:
                    name = self.decode_str(header)
                    mail_info.from_name.add(name)
                    mail_info.from_address.add(address)

            # to
            value = root.get('To', '')
            values = self.parse_address(value)
            if values:
                for (header, address) in values:
                    name = self.decode_str(header)
                    mail_info.to_name.add(name)
                    mail_info.to_address.add(address)

            # cc
            value = root.get('Cc', '')
            values = self.parse_address(value)
            if values:
                for (header, address) in values:
                    name = self.decode_str(header)
                    mail_info.cc_name.add(name)
                    mail_info.cc_address.add(address)

            # subject
            value = root.get('Subject', '')
            if value:
                mail_info.subject = self.decode_str(value)

            # child MIMEMultipart
            if root.is_multipart():
                parts = root.get_payload()
                for n, part in enumerate(parts):
                    sub_mail_info = self.parse_mail(part)
                    mail_info.child_mail.append(sub_mail_info)
            else:
                content_type = root.get_content_type()
                if content_type == 'text/plain' or content_type == 'text/html':
                    # 纯文本或HTML内容:
                    content = root.get_payload(decode=True)
                    # 要检测文本编码:
                    charset = self.guess_charset(root)
                    if charset:
                        content = content.decode(charset)
                    mail_info.content = content
                    # 调试用
                    # Logger.report(mail_info.content)
                else:
                    # 不是文本,作为附件处理
                    pass
            return mail_info
        except:
            Logger.error(traceback.format_exc())
            return None
Пример #19
0
def __main__():
    # utf-8
    reload(sys)
    sys.setdefaultencoding('utf-8')

    # 日志目录
    log_target = "logs"
    # 邮件过滤策
    filter_file = "config/filter.xml"
    # 收件账号
    r_account = raw_input("receive mail account: ")
    # 收件密码
    r_password = getpass.getpass('receive mail password: '******'send mail password: '******'receive mail password: '******'send mail password: '******'Y' and input_flag != 'N':
        print >> sys.stderr, "Invalid send_flag values, it must be Y or N"
        return False
    send_flag = True if input_flag == 'Y' else False

    print >> sys.stdout, "program is running in background, please check the running log!"

    # 初始化日志
    Logger.init(LogEnv.develop, log_target, "result", max_file_count=10)
    Logger.info("program is starting......")

    # 非调试状态时在后台启动
    try:
        pid = os.fork()
        if pid > 0:
            Logger.info("#1 parent exit")
            os._exit(0)
    except:
        Logger.error(traceback.format_exc())

    try:
        pid = os.fork()
        if pid > 0:
            Logger.info("#2 parent exit")
            Logger.info("pid[%s] is running..." % pid)
            os._exit(0)
    except:
        Logger.error(traceback.format_exc())

    # 邮件记录文件
    self_dir = os.path.dirname(os.path.abspath(__file__))
    recorder_dir = os.path.join(self_dir, 'data')
    if not os.path.exists(recorder_dir):
        os.mkdir(recorder_dir)
    recorder_file = os.path.join(self_dir, 'data', 'transfer.db')

    # 循环接收邮件
    idx = 0
    while True:
        try:
            loop_once(r_account, r_password, pop3_server,
                      s_account, s_password, smpt_server,
                      recorder_file, filter_file,
                      send_flag, target_account,
                      idx)
            idx += 1
            # 非调试状态时循环转发邮件
            time.sleep(60)
            # 调试用
            # break
        except:
            Logger.error(traceback.format_exc())
Пример #20
0
 def __del__(self):
     try:
         self.clear_dead()
         self.flush_to_disk()
     except:
         Logger.error(traceback.format_exc())