#! python3 # Checks for instructions via email and runs them. # So far, this program checks for BitTorrent "magnet" links and launches the torrent program for them. import smtplib, imapclient, pyzmail, logging, traceback, time, subprocess logging.basicConfig(filename='torrentStarterLog.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') # Configure the program by setting some variables. MY_EMAIL = 'asweigart@gmail.com' # bot should only respond to me BOT_EMAIL = 'imaptest@coffeeghost.net' BOT_EMAIL_PASSWORD = '7|)6S1JS6>euu8p/nTlf' IMAP_SERVER = 'mail.coffeeghost.net' SMTP_SERVER = 'mail.coffeeghost.net' SMTP_PORT = 465 TORRENT_PROGRAM = 'C:\\Program Files (x86)\\qBittorrent\\qbittorrent.exe' assert BOT_EMAIL != MY_EMAIL, "Give the bot it's own email address." def getInstructionEmails(): # Log in to the email imapCli. logging.debug('Connecting to IMAP server at %s...' % (IMAP_SERVER)) imapCli = imapclient.IMAPClient(IMAP_SERVER, ssl=True) imapCli.login(BOT_EMAIL, BOT_EMAIL_PASSWORD) imapCli.select_folder('INBOX') logging.debug('Connected.') # Fetch all instruction emails. instructions = [] UIDs = imapCli.search(['FROM ' + MY_EMAIL]) rawMessages = imapCli.fetch(UIDs, ['BODY[]']) for UID in rawMessages.keys(): # Parse the raw email message. message = pyzmail.PyzMessage.factory(rawMessages[UID]['BODY[]']) if message.html_part != None: body = message.html_part.get_payload().decode(message.html_part.charset) if message.text_part != None: # If there's both an html and text part, use the text part. body = message.text_part.get_payload().decode(message.text_part.charset) # Extract instruction from email body. instructions.append(body) # Delete the instruction emails, if there are any. if len(UIDs) > 0: imapCli.delete_messages(UIDs) imapCli.expunge() imapCli.logout() return instructions def parseInstructionEmail(instruction): # Send an email response about the task. responseBody = 'Subject: Instruction completed.\nInstruction received and completed.\nResponse:\n' # Parse the email body to figure out the instruction. lines = instruction.split('\n') for line in lines: if line.startswith('magnet:?'): subprocess.Popen(TORRENT_PROGRAM + ' ' + line) # launch the bittorrent program responseBody += 'Downloading magnet link.\n' # Email the response body to confirm the bot carried out this instruction. logging.debug('Connecting to SMTP server at %s to send confirmation email...' % (SMTP_SERVER)) #smtpCli = smtplib.SMTP(SMTP_SERVER, SMTP_PORT) # uncomment one or the other as needed. smtpCli = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) # uncomment one or the other as needed. smtpCli.ehlo() #smtpCli.starttls() # comment this out if using SMTP_SSL smtpCli.login(BOT_EMAIL, BOT_EMAIL_PASSWORD) logging.debug('Connected.') smtpCli.sendmail(BOT_EMAIL, MY_EMAIL, responseBody) logging.debug('Confirmation email sent.') smtpCli.quit() # Start an infinite loop that checks email and carries out instructions. print('Email bot started. Press Ctrl-C to quit.') logging.debug('Email bot started.') while True: try: logging.debug('Getting instructions from email...') instructions = getInstructionEmails() for instruction in instructions: logging.debug('Doing instruction: ' + instruction) parseInstructionEmail(instruction) except Exception as err: logging.error(traceback.format_exc()) # Wait 15 minutes before checking again logging.debug('Done processing instructions. Pausing for 15 minutes.') time.sleep(60 * 15)