mailFunctions.py 6.9 KB

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