Receive your emails via SMS with the Free Mobile API.

emails_sms_free.py 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8-*-
  3. from __future__ import print_function
  4. import email
  5. import hashlib
  6. import imaplib
  7. import os.path
  8. import requests
  9. import sys
  10. import time
  11. try:
  12. # For python 3
  13. import json
  14. except ImportError:
  15. # For python 2
  16. import simplejson as json
  17. print('Error importing lib as python3, switching to python 2 libraries')
  18. msg_ids = {}
  19. def get_subject(subject_header):
  20. tmp = email.header.decode_header(subject_header)[0]
  21. if tmp[1] is None:
  22. return str(tmp[0])
  23. else:
  24. try:
  25. return tmp[0].decode(tmp[1])
  26. except LookupError:
  27. return "--Unable to fetch subject--"
  28. def send(url, user, password, msg, i=0):
  29. try:
  30. r = requests.get(url, params={'user': user, 'pass': password, 'msg': msg}, verify=False)
  31. if r.status_code == 200:
  32. return True
  33. elif r.status_code == 400:
  34. print('Un paramètre obligatoire est manquant.')
  35. return False
  36. elif r.status_code == 402:
  37. if i < 3:
  38. print('Trop de SMS ont été envoyés en trop peu de temps, ' +
  39. 'le script réessayera dans 30 secondes.')
  40. time.sleep(30)
  41. send(url, user, password, msg, i+1)
  42. else:
  43. print('Impossible d\'envoyer le message dans la dernière minute ' +
  44. 'et demie.')
  45. return False
  46. elif r.status_code == 403:
  47. print('Identifiants incorrects ou service non activé.')
  48. return False
  49. elif r.status_code == 500:
  50. print('Erreur côté serveur.')
  51. return False
  52. except requests.exceptions.RequestException:
  53. return False
  54. def get_emails(imap_server, imap_user, imap_password, inbox, uid):
  55. global msg_ids
  56. print('Connecting to '+imap_server+'… ', end='')
  57. conn = imaplib.IMAP4_SSL(imap_server)
  58. print('Connected')
  59. to_send = []
  60. try:
  61. print('Logging as '+imap_user+'… ', end='')
  62. retcode, capabilities = conn.login(imap_user, imap_password)
  63. except:
  64. print('Failed')
  65. print(sys.exc_info()[1])
  66. sys.exit(1)
  67. print('Logged in')
  68. try:
  69. conn.select(inbox, readonly=True)
  70. typ, tmp_msg_ids = conn.uid('search', None, 'ALL')
  71. tmp_msg_ids = [i.decode('utf-8')
  72. for i in tmp_msg_ids[0].split()]
  73. if uid in msg_ids:
  74. diff_msg_ids = [i
  75. for i in tmp_msg_ids
  76. if i not in msg_ids[uid]]
  77. else:
  78. diff_msg_ids = tmp_msg_ids
  79. msg_ids[uid] = tmp_msg_ids
  80. if len(diff_msg_ids) == 0:
  81. print("\tNo new emails")
  82. else:
  83. for i in diff_msg_ids:
  84. typ, msg_data = conn.uid('fetch', i, '(RFC822)')
  85. msg_parsed = email.message_from_bytes(msg_data[0][1])
  86. text = ""
  87. for part in msg_parsed.walk():
  88. if part.get_content_charset() is None:
  89. # We cannot know the character set, so return decoded "something"
  90. text = part.get_payload(decode=True)
  91. continue
  92. charset = part.get_content_charset()
  93. if part.get_content_type() == 'text/plain':
  94. text = part.get_payload(decode=True).decode(str(charset))
  95. break
  96. subject = get_subject(msg_parsed['Subject'])
  97. print("\tNew email from "+msg_parsed['From'] +
  98. " : "+subject)
  99. to_send.append({'server_uid': uid,
  100. 'id': i,
  101. 'from': msg_parsed['From'],
  102. 'subject': subject,
  103. 'content': text})
  104. return to_send
  105. finally:
  106. try:
  107. conn.close()
  108. except:
  109. pass
  110. conn.logout()
  111. if __name__ == '__main__':
  112. # EDIT BELOW ACCORDING TO YOUR NEEDS
  113. imap_servers = [{'server': 'SERVER',
  114. 'login': 'LOGIN',
  115. 'password': 'PASS',
  116. 'inbox': 'INBOX'}]
  117. save_path = os.path.expanduser('~/.emails_sms_free.json')
  118. debug = False
  119. url = "https://smsapi.free-mobile.fr/sendmsg"
  120. user = 'IDENT'
  121. password = 'PASS'
  122. # YOU SHOULD NOT HAVE TO EDIT BELOW
  123. url = url.replace('{$user}', user)
  124. url = url.replace('{$pass}', password)
  125. if os.path.isfile(save_path):
  126. with open(save_path, 'r') as fh:
  127. msg_ids = json.load(fh)
  128. to_send = []
  129. for imap_server in imap_servers:
  130. to_send.extend(get_emails(imap_server['server'],
  131. imap_server['login'],
  132. imap_server['password'],
  133. imap_server['inbox'],
  134. hashlib.md5((imap_server['server']+imap_server['login']).encode('utf-8')).hexdigest()))
  135. if debug:
  136. print("\nNew emails to send via SMS:")
  137. print("\t", to_send)
  138. i = 1
  139. for data in to_send:
  140. msg = ('New email from '+data['from']+'\n' +
  141. data['subject']+'\n' +
  142. str(data['content'][:700])+'...')
  143. if send(url, user, password, msg):
  144. print('Sent '+str(i)+'/'+str(len(to_send)))
  145. else:
  146. msg_ids[data['server_uid']].remove(data['id'])
  147. print('Email '+str(i)+'/'+str(len(to_send))+' : Unable to send the text ' +
  148. 'message, remove this email from parsed list.')
  149. i += 1
  150. with open(save_path, 'w') as fh:
  151. json.dump(msg_ids, fh)