mail_import.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import sys
  2. from config import DSN, MAILBOX
  3. from model import StatusMeldung
  4. from datetime import date, time, timedelta
  5. from email.message import EmailMessage
  6. from sqlalchemy import create_engine
  7. from sqlalchemy.orm import Session
  8. from sqlalchemy.exc import IntegrityError
  9. from imap_tools import MailBox, AND
  10. import json
  11. class MailImport:
  12. def open_mailbox(self) -> MailBox:
  13. return MailBox(MAILBOX["server"]).login(
  14. MAILBOX["user"], MAILBOX["password"], MAILBOX["folder"]
  15. )
  16. def mail_import(self) -> int:
  17. with (
  18. Session(create_engine(DSN)) as db_session,
  19. self.open_mailbox() as mb,
  20. ):
  21. messages = mb.fetch(mark_seen=True, limit=500)
  22. imported = []
  23. for msg in messages:
  24. status = self.get_status_message(msg)
  25. if status is None:
  26. continue
  27. db_session.add(status)
  28. try:
  29. db_session.commit()
  30. imported.append(msg.uid)
  31. except IntegrityError as e:
  32. db_session.rollback()
  33. print(e.args[0])
  34. mb.delete(imported)
  35. return len(imported)
  36. def get_status_message(self, msg: EmailMessage) -> StatusMeldung:
  37. subject = msg.subject.split(";")
  38. if len(subject) < 5:
  39. print(msg.subject)
  40. return None
  41. attachments = dict(
  42. [(att.filename, att.payload) for att in msg.attachments if att.size > 0]
  43. )
  44. fehlerbericht_json = json.loads(attachments.get("fehlerbericht.json", "[]"))
  45. fehlerbericht_import = json.dumps(fehlerbericht_json)
  46. aufgabe = ""
  47. if len(subject) > 5:
  48. if subject[5][-4:] == ".bat":
  49. aufgabe = subject[5]
  50. elif ":" in subject[5]:
  51. aufgabe = "manuell"
  52. if ":" not in subject[1]:
  53. aufgabe = subject[1]
  54. subject[1] = "00:00"
  55. if aufgabe == "":
  56. files = [f["Name"] for f in fehlerbericht_json if ".bat" in f["Name"]]
  57. if len(files) > 0:
  58. aufgabe = files[0]
  59. return StatusMeldung(
  60. datum=date.fromisoformat(subject[3]),
  61. kunde=subject[0],
  62. aufgabe=aufgabe,
  63. start=time.fromisoformat(subject[1]),
  64. ende=time.fromisoformat(subject[2]),
  65. fehlerbericht_import=fehlerbericht_import,
  66. anzahl=int(subject[4]),
  67. )
  68. def cleanup(self):
  69. date_criteria = date.today() - timedelta(days=7)
  70. with self.open_mailbox() as mb:
  71. messages = mb.fetch(
  72. criteria=AND(date_lt=date_criteria, seen=True),
  73. limit=500,
  74. )
  75. selected = [msg.uid for msg in messages]
  76. mb.delete(selected)
  77. if __name__ == "__main__":
  78. mi = MailImport()
  79. res = mi.mail_import()
  80. mi.cleanup()
  81. if res == 0:
  82. sys.exit(1)