Checking your snail mail with Python/Docker and Slack. (Part 1)

Background

Recently I became aware of a service for USPS called “Informed Delivery”. This service will allow you to view mail items coming to your physical mailbox before they arrive, as well as a get an email with the same information.

This is a very cool service but unfortunately there is no way to get push notifications about this information, or have any kind of notification at all besides a email that doesn’t allow for any customization, or even show all of your mail items. There are apps for various platforms, but they are simple webkit wrappers around the USPS website and have fairly terrible reviews.

Obviously we are going to need to automate this. I decided to use python to automate grabbing this information and making it more useful.

Checking your  mail with Python

If you just want to get the finished Docker image please jump straight to my Github Project Page

I decided to make a script that will leverage the information from this service to grab the data, and push it to me in useful ways on various platforms, beginning with Slack and Pushbullet. I wanted to have the following features to start-

  • Login to the MyUSPS Website
  • Generate Session Cookie
  • Scrape package and mail data
  • For each piece of package data or mail data, generate CLI output
  • Download mail piece images locally and upload to another hosting site
  • Post a custom formatted notification to Slack and Pushbullet

While looking for any type of API or help scraping data from the Informed Delivery website I came across a Github Library that already did most of this work for me. “python-myusps” uses Beautifulsoup, Selenium and the trusty Requests library to do the scraping for me. Using this was fairly difficult at the beginning as the library had some issues that needed be resolved to get it working. On the plus side, this is a huge time saver overall. Once it’s up and running, we can use simple functions to return a list of dicts that contain all the information we need. For example – Checking your mail for today returns each item, as well as a link to a scanned image.

import myusps

username = "xxx"
password = "xxx"

# Use the login credentials you use to login to My USPS via the web.
# A login failure raises a `USPSError`.
# Using the Firefox driver here for selenium as it appears to be the most stable one at the moment. 
session = myusps.get_session(username, password, driver='firefox')

In [6]: mail = myusps.get_mail(session, datetime.datetime.now().date())

In [7]: print(mail)
[{'id': '232180517528', 'image': 'https://informeddelivery.usps.com/box/pages/secure/getMailpieceImageFile.action?id=232180517528', 'date': datetime.date(2018, 4, 25)}, {'id': '232180517529', 'image': 'https://informeddelivery.usps.com/box/pages/secure/getMailpieceImageFile.action?id=232180517529', 'date': datetime.date(2018, 4, 25)}]

So this is cool, but now we need to do something useful with that information. I decided to implement a simple slack notification system that also uploads each picture to imgur as a temporary storage location. There is an official slack library you can use, but I decided to just use the requests/JSON library instead to make our API requests.

It’s pretty straight forward. I just created a function to call when we want to post to slack.

webhook_url = 'https://hooks.slack.com/services/XXXX'

def slack_post(webhook_url, slack_data):
    response = requests.post(
        webhook_url, data=json.dumps(slack_data),
        headers={'Content-Type': 'application/json'}
    )
    return response

Then we can use it inside a  loop to write text and links to Slack

    mail_num = (f"Number of USPS Mail Items Today: {len(mail)}")
    #Post to pushbullet if enabled
    if pushbullet_enabled == 1:
        print("Sending note to pushbullet")
        push = pb.push_note("MyUSPS", mail_num)
    slack_data = {"text": mail_num}
    slack_post(webhook_url, slack_data)

I also needed to store my images with Imgur to embed them into Slack and Pushbullet notifications. With the requests library and our image url that’s already been scraped – that’s easy to do:

            image = session.get(item['image'], allow_redirects=False)
            if image.status_code == 200:
                with open("mailpieceImg.jpg", 'wb') as f:
                    f.write(image.content)
        
            #upload to imgur
            imgurlink = client.upload_from_path("mailpieceImg.jpg", config=None, anon=True)

The end result of this script is a CLI output after each run –

You have no packages right now
Number of Mail Items: 1
Sending note to pushbullet
ID: 231206225030
Image: https://informeddelivery.usps.com/box/pages/secure/getMailpieceImageFile.action?id=231206225030
Date: 2018-04-24
https://i.imgur.com/v5hgWXi.jpg

As well as a slack and pushbullet notification (if enabled)

Check out part 2 of this post for information on packaging this with docker, and future work.

Share this content:

Leave a Comment

Your email address will not be published. Required fields are marked *