email.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from email import message_from_bytes
  2. import email.header
  3. import os
  4. import re
  5. import datetime
  6. import calendar
  7. class Mail:
  8. date_pattern = re.compile(
  9. r"[A-Za-z]+, "
  10. r"([0-9]{1,2}) "
  11. r"([A-Za-z]+) "
  12. r"([0-9]{4}) "
  13. r"([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}) "
  14. r"([\s\S]*)"
  15. )
  16. time_zone_pattern = re.compile(r"([+-])([0-9]{2})00")
  17. def __init__(self, num: str, data: bytes):
  18. self.__data = message_from_bytes(data)
  19. self.byte = data
  20. self.num = num
  21. @property
  22. def from_addr(self):
  23. if not self.__data['From']:
  24. return ""
  25. return str(email.header.make_header(email.header.decode_header(self.__data['From'])))
  26. @property
  27. def date(self):
  28. if not self.__data['Date']:
  29. return datetime.datetime(2022, 1, 1)
  30. date = str(email.header.make_header(email.header.decode_header(self.__data['Date'])))
  31. res = self.date_pattern.match(str(date)).groups()
  32. time = datetime.datetime(int(res[2]),
  33. list(calendar.month_abbr).index(res[1]),
  34. int(res[0]),
  35. int(res[3]),
  36. int(res[4]),
  37. int(res[5]))
  38. timezone = self.time_zone_pattern.match(res[6])
  39. if timezone:
  40. if timezone.groups()[0] == '-':
  41. time += datetime.timedelta(hours=int(timezone.groups()[1]))
  42. else:
  43. time -= datetime.timedelta(hours=int(timezone.groups()[1]))
  44. time += datetime.timedelta(hours=8) # 转换为北京时间
  45. return time
  46. @property
  47. def title(self):
  48. if not self.__data['Subject']:
  49. return ""
  50. return (str(email.header.make_header(email.header.decode_header(self.__data['Subject'])))
  51. .replace('\n', '')
  52. .replace('\r', ''))
  53. @property
  54. def body(self):
  55. return self.__get_body(self.__data).decode("utf-8")
  56. def __get_body(self, msg):
  57. if msg.is_multipart():
  58. return self.__get_body(msg.get_payload(0))
  59. else:
  60. return msg.get_payload(None, decode=True)
  61. def save_file(self, file_dir: str):
  62. return self.__get_files(self.__data, file_dir)
  63. @staticmethod
  64. def __get_files(msg, file_dir: str):
  65. create = False
  66. for part in msg.walk():
  67. if not create:
  68. os.makedirs(file_dir, exist_ok=True)
  69. create = True
  70. if part.get_content_maintype() == 'multipart':
  71. continue
  72. if part.get('Content-Disposition') is None:
  73. continue
  74. filename = part.get_filename()
  75. if filename:
  76. filepath = os.path.join(file_dir, filename)
  77. with open(filepath, 'wb') as f:
  78. f.write(part.get_payload(decode=True))
  79. def __lt__(self, other: "Mail"):
  80. return self.date < other.date
  81. def __eq__(self, other: "Mail"):
  82. return self.date == other.date
  83. def __le__(self, other: "Mail"):
  84. return self.date <= other.date
  85. def __str__(self):
  86. return f"{self.num} {self.title} {self.from_addr} {self.date}"