diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/mail.py | 128 |
1 files changed, 116 insertions, 12 deletions
diff --git a/utils/mail.py b/utils/mail.py index 3dc346f..f26e7b8 100644 --- a/utils/mail.py +++ b/utils/mail.py @@ -1,20 +1,97 @@ +import base64 +from datetime import datetime +from email.parser import Parser +import logging import poplib +import pytz +import re -class MailInfo(object): - """ - Class for storing mail's metadata - """ +logger = logging.getLogger(__name__) + +class MailDetails(object): def __init__(self): - self.index = 0 - self.size = 0 - self.status = "" - self.data = "" + self.from_nickname = "" + self.from_account = "" + self.to_nickname = "" + self.to_account = "" + self.subject = "" + self.receivedtime = "" + self.text_content = "" + self.html_content = "" + + +def decode_byte(bstr, charset='utf8'): + return bstr.decode(charset) + +def get_rawcontent_charset(rawcontent): + for item in rawcontent: + if decode_byte(item).find('charset='): + charset = re.findall(re.compile('charset="(.*)"'), decode_byte(item)) + for member in charset: + if member is not None: + return member + + +def parse_raw_mail_data(raw_lines, charset='utf8'): + msg_content = b'\r\n'.join(raw_lines).decode(encoding=charset) + return Parser().parsestr(text=msg_content) + +def decode_base64(s, charset='utf8'): + return str(base64.decodebytes(s.encode(encoding=charset)), encoding=charset) + + +def get_mail_info(s): + try: + nickname, account = s.split(" ") + except ValueError: + nickname = '' + account = s + + account = account.lstrip('<') + account = account.rstrip('>') + return nickname, account + +def get_mail_details(msg): + maildetails = MailDetails() + + fromstr = msg.get('From') + from_nickname, from_account = get_mail_info(fromstr) + maildetails.from_nickname = from_nickname + maildetails.from_account = from_account + tostr = msg.get('To') + to_nickname, to_account = get_mail_info(tostr) + maildetails.to_nickname = to_nickname + maildetails.to_account = to_account + + subject = msg.get('Subject') + try: + maildetails.subject = decode_base64(subject.split("?")[3], charset=subject.split("?")[1]) + except IndexError: + maildetails.subject = subject + received_time = msg.get("Date") + time_str_fmt = "%a, %d %b %Y %H:%M:%S %z" + time_obj = datetime.strptime(received_time, time_str_fmt) + time_obj = time_obj.astimezone(pytz.timezone('Asia/Hong_Kong')) + maildetails.receivedtime = time_obj.strftime(time_str_fmt) + + parts = msg.get_payload() + content_charset = parts[0].get_content_charset() + content = parts[0].as_string().split('base64')[-1] + try: + maildetails.text_content = decode_base64(content, content_charset) + except Exception as e: + logger.error('Exception caught: "%s"', e) + maildetails.text_content = content + content = parts[1].as_string().split('base64')[-1] + maildetails.html_content = content + + return maildetails class EmailClient(object): - def __init__(self, email_account, password): + def __init__(self, email_account, passwd): self.email_account = email_account - self.password = password + self.password = passwd self.server = self.connect(self) @staticmethod @@ -34,15 +111,42 @@ class EmailClient(object): return server - def get_mail_count(self): + def get_mails_list(self): _, mails, _ = self.server.list() + return mails + + def get_mails_count(self): + mails = self.get_mails_list() return len(mails) + def get_mail_by_index(self, index): + resp_status, mail_lines, mail_octets = self.server.retr(index) + content_charset = get_rawcontent_charset(mail_lines) + data = parse_raw_mail_data(mail_lines, charset=content_charset or 'utf-8') + maildetails = get_mail_details(data) + return maildetails + + + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type is None: + print('exited normally\n') + self.server.quit() + else: + print('raise an exception! ' + str(exc_type)) + self.server.close() + return False # Propagate + + + if __name__ == '__main__': useraccount = "XXXXX" password = "XXXXXX" client = EmailClient(useraccount, password) - client.get_mail_count()
\ No newline at end of file + client.get_mails_count()
\ No newline at end of file |