mail_alert.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. '''Created Sep 28, 2021 Levi'''
  2. import configparser
  3. import sys
  4. import traceback
  5. import ssl
  6. import asyncio
  7. from time import sleep
  8. from collections import deque
  9. from threading import Event
  10. from imaplib import IMAP4
  11. import telegram
  12. import keyring
  13. from bs4 import BeautifulSoup
  14. from telegram.error import BadRequest
  15. from imap_tools import MailBox, AND
  16. # -> for python >=3.10, the dh key too small problem
  17. context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
  18. context.set_ciphers('DEFAULT@SECLEVEL=1')
  19. config = configparser.ConfigParser()
  20. config.read('bot')
  21. bot = telegram.Bot(token=config['AUTH']['token'])
  22. bot2 = telegram.Bot(token=config['AUTH']['bank'])
  23. def pretty_exc():
  24. exc_type, _exc_obj, exc_tb = sys.exc_info()
  25. # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
  26. for tb in list(traceback.format_exception(exc_type, _exc_obj, exc_tb)):
  27. print(tb)
  28. def mask(msg, to_):
  29. return any([to_ == msg.from_,
  30. to_ in msg.to,
  31. to_ in msg.cc,
  32. to_ in msg.bcc])
  33. def mask2(msg, to_):
  34. return any([to_ == msg.from_,
  35. to_ in msg.to,
  36. to_ in msg.cc,
  37. to_ in msg.bcc,
  38. to_ in msg.subject])
  39. def clean_html(text) -> str:
  40. soup = BeautifulSoup(text, 'html.parser')
  41. stripped_text = soup.get_text()
  42. lines = (line.strip() for line in stripped_text.splitlines())
  43. # break multi-headlines into a line each
  44. chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
  45. # drop blank lines
  46. text = '\n'.join(chunk for chunk in chunks if chunk)
  47. return text
  48. async def mail_alert(container) -> str | None:
  49. '''mail alert Inbox'''
  50. # container: deque = deque(maxlen=500)
  51. # while True:
  52. try:
  53. mailbox = MailBox(host=config['email']['host'], ssl_context=context)
  54. mailbox.login(config['email']['user'], keyring.get_password('yagmail', 'levente.marton@mzk.ro'), initial_folder='Inbox') # noqa E:mypy
  55. sleep(15)
  56. msgs = [msgs for msgs in mailbox.fetch(AND(seen=False), mark_seen=False)]
  57. for msg in msgs:
  58. chk = mask(msg, 'levente.marton@mzk.ro')
  59. if chk:
  60. msg_text = msg.text
  61. if 'end of day extras/intraday' in msg.subject:
  62. msg_text = msg.text.replace('<br>', '\n')
  63. if msg.uid not in container:
  64. try:
  65. if len(msg.text) != 0:
  66. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg_text}')
  67. else:
  68. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg.html}')
  69. container.appendleft(msg.uid)
  70. print('message appended', len(container))
  71. except BadRequest:
  72. try:
  73. if len(msg.text) != 0:
  74. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg_text[:len(msg_text) // 5]}')
  75. else:
  76. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg.html[:len(msg.html) // 5]}')
  77. container.appendleft(msg.uid)
  78. print('message appended', len(container))
  79. except BadRequest:
  80. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\nMessage is too long')
  81. container.appendleft(msg.uid)
  82. print('message appended', len(container), '!! last message was to long !!')
  83. except Exception:
  84. try:
  85. mailbox.logout()
  86. pretty_exc()
  87. except IMAP4.abort:
  88. pass
  89. # break
  90. mailbox.logout()
  91. return msg.uid
  92. except Exception:
  93. try:
  94. mailbox.logout()
  95. except IMAP4.abort:
  96. pass
  97. return 'empty box'
  98. async def mail_alert2(container) -> str | None:
  99. # container: deque = deque(maxlen=500)
  100. # while True:
  101. try:
  102. mailbox2 = MailBox(host=config['email']['host'], ssl_context=context)
  103. mailbox2.login(config['email']['user'], keyring.get_password('yagmail', 'levente.marton@mzk.ro'), initial_folder='bank_events') # noqa E:mypy
  104. sleep(15)
  105. msgs = [msgs for msgs in mailbox2.fetch(AND(seen=False), mark_seen=True)]
  106. for msg in msgs:
  107. chk = mask2(msg, 'account')
  108. if chk:
  109. if msg.uid not in container:
  110. soup = BeautifulSoup(msg.html, 'html.parser')
  111. msg_text = soup.prettify().replace('<br/>', '').replace('<html>', '').replace('<head>', '').replace('</head>', '').replace('<body>', '').replace('<div>', '').replace('</div>', '').replace('</body>', '').replace('</html>', '')
  112. msg_text = msg_text[:msg_text.find('Intraday transactions')]
  113. msg_text = clean_html(msg_text)
  114. try:
  115. if len(msg.text) or len(msg.html) != 0:
  116. await bot2.send_message(chat_id=config['AUTH']['chatid'], text=msg_text)
  117. else:
  118. await bot2.send_message(chat_id=config['AUTH']['chatid'], text=msg_text)
  119. container.appendleft(msg.uid)
  120. print('message appended', len(container))
  121. except BadRequest:
  122. try:
  123. if len(msg.text) or len(msg.html) != 0:
  124. await bot2.send_message(chat_id=config['AUTH']['chatid'], text=msg_text // 5) # noqa E:mypy
  125. else:
  126. await bot2.send_message(chat_id=config['AUTH']['chatid'], text=msg_text // 5) # noqa E:mypy
  127. container.appendleft(msg.uid)
  128. print('message appended', len(container))
  129. except BadRequest:
  130. await bot2.send_message(chat_id=config['AUTH']['chatid'], text=f'Message is too long')
  131. container.appendleft(msg.uid)
  132. print('message appended', len(container), '!! last message was to long !!')
  133. except Exception:
  134. try:
  135. mailbox2.logout()
  136. pretty_exc()
  137. except IMAP4.abort:
  138. pass
  139. # break
  140. mailbox2.logout()
  141. return msg.uid
  142. except Exception:
  143. # pretty_exc()
  144. try:
  145. mailbox2.logout()
  146. except IMAP4.abort:
  147. pass
  148. return 'empty box'
  149. async def mail_alert3(container) -> str | None:
  150. '''mail alert Inbox'''
  151. # container: deque = deque(maxlen=500)
  152. # while True:
  153. try:
  154. mailbox3 = MailBox(host=config['email']['host'], ssl_context=context)
  155. mailbox3.login(config['email']['user'], keyring.get_password('yagmail', 'levente.marton@mzk.ro'), initial_folder='API') # noqa E:mypy
  156. sleep(15)
  157. msgs = [msgs for msgs in mailbox3.fetch(AND(seen=False), mark_seen=True)]
  158. for msg in msgs:
  159. chk = mask(msg, 'Ciel_notifier@mzk.ro')
  160. if chk:
  161. msg_text = msg.text
  162. # if 'end of day extras/intraday' in msg.subject:
  163. # msg_text = msg.text.replace('<br>', '\n')
  164. if msg.uid not in container:
  165. try:
  166. if len(msg.text) != 0:
  167. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg_text}')
  168. else:
  169. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg.html}')
  170. container.appendleft(msg.uid)
  171. print('message appended', len(container))
  172. except BadRequest:
  173. try:
  174. if len(msg.text) != 0:
  175. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg_text[:len(msg_text) // 5]}')
  176. else:
  177. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\n{msg.html[:len(msg.html) // 5]}')
  178. container.appendleft(msg.uid)
  179. print('message appended', len(container))
  180. except BadRequest:
  181. await bot.send_message(chat_id=config['AUTH']['chatid'], text=f'{msg.from_}\nsubj: {msg.subject}\n\nMessage is too long')
  182. container.appendleft(msg.uid)
  183. print('message appended', len(container), '!! last message was to long !!')
  184. except Exception:
  185. try:
  186. mailbox3.logout()
  187. pretty_exc()
  188. except IMAP4.abort:
  189. pass
  190. # break
  191. mailbox3.logout()
  192. return msg.uid
  193. except Exception:
  194. try:
  195. mailbox3.logout()
  196. except IMAP4.abort:
  197. pass
  198. return 'empty box'
  199. # if __name__ == '__main__':
  200. # try:
  201. # # event = Event()
  202. # asyncio.run(mail_alert())
  203. # except KeyboardInterrupt:
  204. # loop = asyncio.get_event_loop()
  205. # loop.stop()