This is the first program I've ever made in Python, and I never really studied the language (just looked at bits of code online) so I'm sure the performance is less than optimal.
The Objective: At my college, security alerts are occasionally sent to our phones, and sometimes posted to our subreddit for discussion. To automate this, I set up my phone to forward relevant texts to an email address, then take the message from the email address and post to Reddit. The script scans my inbox every 30 seconds for unread emails and posts the newest one if it finds anything.
Issues
- I wanted to use something like twilio to avoid the email address part, but I can only sign up for Alerts with one phone number, and I still want to receive alerts on my phone
- Too many points of failure. My phone could be off, my computer (script host) could be off/asleep, text forwarding could fail, gmail could be down, etc.
- Scanning the inbox every 30 seconds seems needlessly excessive and I wish there was a better way to do it.
- There are a lot of while loops, but I don't know any other way to catch exceptions.
I'm planning on putting the script onto a Raspberry Pi 3 later on so there's something dedicated running it, but I'd like to optimize the code as much as possible before I do that. I also had to remove the OAuth codes for security reasons.
import praw
import imaplib
import email
import time
import getpass
import RUAlerts
from datetime import datetime
app_id = 'xxxxxxxxxxxx'
app_secret = 'xxxxxxxxxxxx'
app_uri = 'xxxxxxxxxxxx'
app_scopes = 'account creddits edit flair history identity mysubreddits privatemessages read report save submit subscribe vote'
app_ua='xxxxxxxxxxxx'
app_account_code = 'xxxxxxxxxxxx'
app_refresh = 'xxxxxxxxxxxx'
def login():
r = praw.Reddit(app_ua)
r.set_oauth_app_info(app_id, app_secret, app_uri)
r.refresh_access_information(app_refresh)
return r
mail = imaplib.IMAP4_SSL('imap.gmail.com')
while True:
try:
emailpass = getpass.getpass('Please enter the password for xxxxxxx@xxxxx: ')
mail.login('[email protected]', emailpass)
break
except imaplib.IMAP4.error:
print('Incorrect password')
mail.select("inbox")
while True:
try:
r = RUAlerts.login()
while 1:
result, response = mail.uid('search', None, "(UNSEEN)")
unread_msg_nums = response[0].split()
result, data = mail.uid('search', None, "ALL")
latest_email_uid = data[0].split()[-1]
result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
raw_email = data[0][1]
email_message = email.message_from_bytes(raw_email)
if len(unread_msg_nums)>0:
print('\t' + str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + ' - Something\'s wrong!')
for part in email_message.walk():
if part.get_content_type()=='text/plain':
Alert=part.get_payload()
while True:
try:
r.submit(subreddit='xxxxxxxxxxxx',title=Alert,text=str(Alert)+"\n \n ******** \n \n*^^I ^^am ^^a ^^bot. ^^For ^^any ^^questions, ^^comments, ^^or ^^concerns, ^^please ^^email [^^xxxxxxx@xxxxx](mailto://xxxxxxx@xxxxx)*")
print('\t' + str(Alert),end=' ')
break
except praw.errors.ExceptionList as e:
print('\tReddit error!' + str(e) + '\tRetrying in 5 minutes - ' + str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
##mail.uid('STORE', latest_email_uid, '-FLAGS', '\SEEN')
time.sleep(300)
else:
print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + ' - All clear on the RU front')
time.sleep(30)
break
except:
print('\t' + str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + ' - No connection! Retrying in 5 minutes')
time.sleep(300)