mailFunctions.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import imaplib, smtplib, ssl, email, os, json
  2. from itertools import chain
  3. # format raw string you get from fetching mails
  4. def stringCompiling(inputIterable):
  5. # remove first nested iterables
  6. try:
  7. unitered = list(chain.from_iterable(inputIterable))
  8. except TypeError:
  9. unitered = inputIterable
  10. # remove None Type entries
  11. nonNoneList = []
  12. try:
  13. for item in unitered:
  14. if item is not None:
  15. if type(item) is not str:
  16. try:
  17. nonNoneList.append(str(item.decode("utf-8")))
  18. except UnicodeDecodeError:
  19. nonNoneList.append(str(item.decode("iso-8859-1")))
  20. except AttributeError:
  21. print(item)
  22. print(type(item))
  23. print(inputIterable)
  24. print(nonNoneList)
  25. exit()
  26. else:
  27. nonNoneList.append(item)
  28. except TypeError:
  29. return ""
  30. # return non empty values
  31. if len(nonNoneList) >= 1:
  32. return nonNoneList[0]
  33. else:
  34. return ""
  35. def errorMsgExit(error_msg):
  36. print("Error: " + error_msg)
  37. def checkConnection(host, username, password, port):
  38. try:
  39. connection = imaplib.IMAP4_SSL(host, port)
  40. connection.login(username, password)
  41. connection.logout()
  42. return True
  43. except Exception as e:
  44. print(str(e))
  45. return False
  46. def connect(host, username, password, port):
  47. connect = imaplib.IMAP4_SSL(host, port)
  48. connect.login(username, password)
  49. try:
  50. connect.enable("UTF8=ACCEPT")
  51. except:
  52. pass
  53. return connect
  54. def listMailboxes(connection):
  55. mailboxes = connection.list()
  56. formatted_mailbox_list = []
  57. for items in mailboxes:
  58. if type(items) == list:
  59. for raw_box_string in items:
  60. box_string = str(raw_box_string)
  61. # TODO: handle cases when folder contains subfolders
  62. modified_box_string = (box_string[box_string.find('"/" ')+4:-1])
  63. # strip unneeded "'s surrounding the folder name
  64. if modified_box_string.startswith('"') and modified_box_string.endswith('"'):
  65. modified_box_string = modified_box_string[1:-1]
  66. formatted_mailbox_list.append(modified_box_string)
  67. connection.logout()
  68. return formatted_mailbox_list
  69. # check that there are no bytes anymore that cannot be dumped into a json
  70. def verifyNoBytes(messages, output_list):
  71. for messages in output_list:
  72. for item in messages:
  73. print(type(item))
  74. print(item)
  75. print(messages["{}".format(item)])
  76. if type(messages["{}".format(item)]) is not str:
  77. print("ERROREXIT: .format failed")
  78. print(messages["{}".format(item)])
  79. print(type(messages["{}".format(item)]))
  80. exit()
  81. if type(item) is not str:
  82. print("ERROREXIT")
  83. exit()
  84. def fetchMails(connection, inbox):
  85. print("###" + inbox + "###")
  86. print(type(inbox))
  87. try:
  88. status, messages = connection.select(inbox)
  89. except:
  90. return []
  91. print("status-------\n" + status)
  92. print("messages-------\n" + str(messages))
  93. # number of top emails to fetch
  94. #N = 3
  95. # total number of emails
  96. messages_int = int(messages[0])
  97. #print("message_int------\n" + str(messages_int))
  98. output_list = []
  99. for seentype in ['(UNSEEN)', '(SEEN)']:
  100. typ, data = connection.search(None, 'ALL', seentype)
  101. for num in data[0].split():
  102. output_dict = {}
  103. typ, data = connection.fetch(num, '(RFC822)')
  104. msg = email.message_from_bytes(data[0][1])
  105. print(num)
  106. raw_string = email.header.decode_header(msg['Subject'])[0]
  107. print("raw_string: " + str(raw_string))
  108. raw_from = email.header.decode_header(msg['From'])
  109. print("raw_from" + str(raw_from))
  110. try:
  111. raw_to = email.header.decode_header(msg['To'])
  112. except TypeError:
  113. raw_to = [""]
  114. try:
  115. raw_cc = email.header.decode_header(msg['CC'])
  116. except TypeError:
  117. raw_cc = [""]
  118. try:
  119. raw_bcc = email.header.decode_header(msg['BCC'])
  120. except TypeError:
  121. raw_bcc = [""]
  122. print("raw_to" + str(raw_to))
  123. raw_date = email.header.decode_header(msg['Date'])[0]
  124. print("raw_to" + str(raw_date))
  125. raw_msg = str(msg)
  126. primitive_body = raw_msg[raw_msg.find('\n\n'):].strip()
  127. #raw_body = email.header.decode_header(msg['Body'])[0][0]
  128. # set subject to an empty string when not found
  129. try:
  130. if raw_string[1] == 'utf-8':
  131. subject = raw_string[0].raw_string('utf-8')
  132. else:
  133. subject = raw_string[0].decode("iso-8859-1")
  134. #nonNoneList.append(str(item.decode("iso-8859-1")))
  135. except AttributeError:
  136. subject=""
  137. output_dict['subject'] = subject
  138. output_dict['from'] = stringCompiling(raw_from)
  139. output_dict['cc'] = stringCompiling(raw_cc)
  140. output_dict['bcc'] = stringCompiling(raw_bcc)
  141. output_dict['to'] = stringCompiling(raw_to)
  142. output_dict['date'] = stringCompiling(raw_date)
  143. output_dict['content'] = primitive_body
  144. if seentype == '(SEEN)':
  145. output_dict['seen'] = "True"
  146. else:
  147. output_dict['seen'] = "False"
  148. # make sure the fetch command doesn't add a SEEN flag
  149. connection.store(num, '-FLAGS', '(\Seen)')
  150. output_dict['subject'] = subject
  151. output_dict['from'] = stringCompiling(raw_from)
  152. output_dict['cc'] = stringCompiling(raw_cc)
  153. output_dict['bcc'] = stringCompiling(raw_bcc)
  154. output_dict['to'] = stringCompiling(raw_to)
  155. output_dict['date'] = stringCompiling(raw_date)
  156. output_dict['content'] = primitive_body
  157. if seentype == '(SEEN)':
  158. output_dict['seen'] = "True"
  159. else:
  160. output_dict['seen'] = "False"
  161. # make sure the fetch command doesn't add a SEEN flag
  162. connection.store(num, '-FLAGS', '(\Seen)')
  163. output_list.append(output_dict)
  164. connection.close()
  165. connection.logout()
  166. verifyNoBytes(messages, output_list)
  167. print("Finstep")
  168. return json.dumps(output_list)
  169. def sendStarttls(host, sendingMail, receivingMail, password, message="", subject="", port=587, cc=[], bcc=[]):
  170. context = ssl.create_default_context()
  171. if type(cc) is not str:
  172. cc = ",".join(cc)
  173. if type(bcc) is not str:
  174. bcc = ",".join(bcc)
  175. utf8Message = "Subject: " + subject + "\nCC: " + cc + "\nBCC: " + bcc + "\n\n" + message
  176. decoded=utf8Message.encode('cp1252').decode('utf-8')
  177. with smtplib.SMTP(host, port) as serverConnection:
  178. serverConnection.starttls(context=context)
  179. serverConnection.login(sendingMail, password)
  180. serverConnection.sendmail(sendingMail, receivingMail, decoded)
  181. def afetchMails(con):
  182. con.select("Sent")
  183. status, email_ids = con.search(None, "ALL")
  184. if status != 'OK':
  185. raise Exception("Error running imap search for spinvox messages: "
  186. "%s" % status)
  187. print(email_ids[0])
  188. fetch_ids = ','.join(str(email_ids[0]).split())
  189. status, data = con.fetch(3, '(RFC822)')
  190. if status != 'OK':
  191. raise Exception("Error running imap fetch for spinvox message: "
  192. "%s" % status)
  193. for i in range(3,4):
  194. header_msg = email.message_from_string(data[i * 3 + 0][1])
  195. subject = header_msg['Subject'],
  196. print(subject)
  197. date = header_msg['Date'],
  198. print(date)
  199. body = data[i * 3 + 1][1]
  200. print(body)
  201. connection.close()
  202. connection.logout()