Source code for AutomateTheBoringStuff.Ch16.Projects.P3_autoUnsubscribe

"""Auto unsubscribe

Write a program that scans through your email account, finds all the unsubscribe
links in all your emails, and automatically opens them in a browser. This program
will have to log in to your email provider’s IMAP server and download all of your
emails. You can use BeautifulSoup to check for any instance where the word
unsubscribe occurs within an HTML link tag.

Once you have a list of these URLs, you can use :func:`webbrowser.open` to automatically
open all of these links in a browser.

Notes:
    * ``imap_info`` file has each item on a separate line.
    * Email address used is specially created for this chapter.
    * Use :func:`input` for password to prevent storing in unencrypted file.

"""


[docs]def main(): import imapclient, pyzmail, bs4, webbrowser, imaplib # Increase size limit from 10,000 bytes to 10,000,000 bytes imaplib._MAXLINE = 10000000 # Login to IMAP server with open('../imap_info') as config: email, password, server, port = config.read().splitlines() imap_obj = imapclient.IMAPClient(server, ssl=True) imap_obj.login(email, password) # Get message and soupify imap_obj.select_folder('INBOX', readonly=True) # Don't mark as read or delete uids = imap_obj.search(['SINCE', '21-Sep-2018']) raw_messages = imap_obj.fetch(uids, ['BODY[]']) for uid in uids: message = pyzmail.PyzMessage.factory(raw_messages[uid][b'BODY[]']) if message.html_part is not None: print(f'Accessing "{message.get_subject()}" from: {message.get_address("from")}...') html = message.html_part.get_payload().decode(message.html_part.charset) soup = bs4.BeautifulSoup(html, 'lxml') else: print('RuntimeError: Email is not HTML.') print(f'Skipping "{message.get_subject()}" from: {message.get_address("from")}') break # Check soup for unsubscribe links anchors = soup.select('a') for anchor in anchors: if anchor.getText().lower() == 'unsubscribe': # Open link in browser url = anchor.get('href') print(f'Opening: {url}') webbrowser.open(url) # Disconnect from IMAP server imap_obj.logout()
if __name__ == '__main__': main()