Skip to main content
1 of 5
Graipher
  • 41.1k
  • 7
  • 69
  • 133

My main comment is that you should separate the different concerns of you code into descriptive functions. This will make it a lot more readable (and re-usable).

One comment before I get started: Your login function, which looks like it would log you in with the reddit API seems to be unused atm. I guess this is a copy&paste error from censoring?


Your first concern is to log-in with gmail to get the mail object. This can be pasted directly into a separate function:

def mail_login():
    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")
    return mail

The second task, which is repeated quite often, is to print a message with the current timestamp preceeding it:

def log(text):
    print('\t{:%Y-%m-%d %H:%M:%S} - {}'.format(datetime.now(), text))

Note that I used the custom format options of str.format here.


Final code:

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'


class LongTimeOut(Exception):
    pass


class ShortTimeOut(Exception):
    pass


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


def log(text):
    print('\t{:%Y-%m-%d %H:%M:%S} - {}'.format(datetime.now(), text))


def mail_login():
    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")
    return mail


def post_alert(alert, r):
    alert_text = """
    {}

     ********

     *^^I ^^am ^^a ^^bot. ^^For ^^any ^^questions, ^^comments, ^^or ^^concerns, ^^please ^^email [^^xxxxxxx@xxxxx](mailto://xxxxxxx@xxxxx)*
     """
    while True:
        try:
            r.submit(subreddit='xxxxxxxxxxxx', title=alert,
                     text=alert_text.format(alert))
            print('\t{}'.format(alert), end=' ')
            break
        except praw.errors.ExceptionList as e:
            raise LongTimeOut(
                'Reddit error! {}'.format(e))


def search_for_alerts(mail):
    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 unread_msg_nums:
        log('Something\'s wrong!')
        for part in email_message.walk():
            if part.get_content_type() == 'text/plain':
                yield part.get_payload()
    else:
        raise ShortTimeOut


while True:
    try:
        r = RUAlerts.login()
        mail = mail_login()
        try:
            for alert in search_for_alerts(mail):
                post_alert(alert, r)
        except ShortTimeOut:
            log('All clear on the RU front')
            time.sleep(30)

    except LongTimeOut as e:
        log('{} Retrying in 5 minutes'.format(e))
        time.sleep(300)
Graipher
  • 41.1k
  • 7
  • 69
  • 133