email.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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)
  56. def __get_body(self, msg):
  57. if msg.is_multipart():
  58. res = ""
  59. for i in msg.get_payload():
  60. res += self.__get_body(i)
  61. return res
  62. else:
  63. msg_type = msg.get_content_type()
  64. if msg_type == "text/plain":
  65. return "text/plain:\n" + msg.get_payload(decode=True).decode('utf-8') + "\n"
  66. elif msg_type == "text/html":
  67. return "text/html:\n" + msg.get_payload(decode=True).decode('utf-8') + "\n"
  68. else:
  69. return ""
  70. def save_file(self, file_dir: str):
  71. return self.__get_files(self.__data, file_dir)
  72. @staticmethod
  73. def __get_files(msg, file_dir: str):
  74. create = False
  75. for part in msg.walk():
  76. if not create:
  77. os.makedirs(file_dir, exist_ok=True)
  78. create = True
  79. if part.get_content_maintype() == 'multipart':
  80. continue
  81. if part.get('Content-Disposition') is None:
  82. continue
  83. filename = part.get_filename()
  84. if filename:
  85. filepath = os.path.join(file_dir, filename)
  86. with open(filepath, 'wb') as f:
  87. f.write(part.get_payload(decode=True))
  88. def __lt__(self, other: "Mail"):
  89. return self.date < other.date
  90. def __eq__(self, other: "Mail"):
  91. return self.date == other.date
  92. def __le__(self, other: "Mail"):
  93. return self.date <= other.date
  94. def __str__(self):
  95. return f"{self.num} {self.title} {self.from_addr} {self.date}"