Skip to content

Instantly share code, notes, and snippets.

@julianandrews
Last active March 5, 2016 22:53
Show Gist options
  • Save julianandrews/e7f7d4024b1589ba4fed to your computer and use it in GitHub Desktop.
Save julianandrews/e7f7d4024b1589ba4fed to your computer and use it in GitHub Desktop.
Simple script to check your gmail inbox, suitable for use with i3status, xmobar or anything that can run scripts and use the output.
#!/usr/bin/python3
import argparse
import getpass
import keyring
import requests
import sys
import xml.etree.ElementTree
SERVICE_NAME = 'gmail-count'
def get_url(email_address):
localpart, _, domain = email_address.rpartition('@')
if domain == 'gmail.com':
return 'https://mail.google.com/mail/feed/atom/'
else:
return 'https://mail.google.com/a/%s/feed/atom/' % domain
def get_count_from_xml(xml_string):
tree = xml.etree.ElementTree.fromstring(xml_string)
node = tree.find('{http://purl.org/atom/ns#}fullcount')
return node.text
def get_mail_count(email_address):
url = get_url(email_address)
password = keyring.get_password(SERVICE_NAME, email_address)
if password is None:
print("No password found for '%s'." % email_address, file=sys.stderr)
return
auth = requests.auth.HTTPBasicAuth(email_address, password)
response = requests.get(url, auth=auth)
if response.status_code == 200:
try:
return get_count_from_xml(response.content)
except xml.etree.ElementTree.ParseError:
print("Failed to parse XML:\n%s" % xml_string, file=sys.stderr)
else:
print("Request failed:\n%s" % response.content, file=sys.stderr)
def parse_args():
parser = argparse.ArgumentParser(description='Check gmail message count.')
parser.add_argument(
'-s',
'--set-pass',
dest='set_pass',
action='store_true',
default=False,
help='set the password for email_address',
)
parser.add_argument(
'-d',
'--delete-pass',
dest='delete_pass',
action='store_true',
default=False,
help='delete the password for email_address'
)
parser.add_argument('email_address', help='Email Address')
return parser.parse_args()
if __name__ == '__main__':
args = parse_args()
if args.set_pass and args.delete_pass:
raise parser.error('-s and -d are mutually exclusive')
elif args.set_pass:
password = getpass.getpass()
keyring.set_password(SERVICE_NAME, args.email_address, password)
elif args.delete_pass:
keyring.delete_password(SERVICE_NAME, args.email_address)
else:
print(get_mail_count(args.email_address) or '?')
@julianandrews
Copy link
Author

Use verbose mode if you want more than minimal output; this script is designed by default to suppress all excess output for convenient use with i3status.

The script, requires the python keyring module and a compatible system keyring. It would be pretty easy to modify it to accept a password via the command-line, but I'll leave that particular sin for someone else to commit.

@julianandrews
Copy link
Author

Here's a shell script suitable for use with i3blocks:

#!/bin/sh

[ "$BLOCK_BUTTON" = 1 ] && xdg-open https://inbox.google.com

$email='my_email@gmail.com'
full_text=$(~/bin/gmail-count "$email")

case $full_text in
  ''|*[!0-9]*) color=\#FF0000 ;;
  0)           color=\#888888 ;;
  *)           color=\#00FF00 ;; 
esac

echo "$full_text"
echo "$short_text"
echo "$color"

Configure with something like:

[mail]
label=✉
command=~/.config/i3/gmail-status.sh
interval=60

@Anachron
Copy link

Man that's wayyyy too complicated and only works with gmail.
I've written a very small and useable script in bash:
https://github.com/Anachron/i3blocks/blob/master/blocks/mail

@julianandrews
Copy link
Author

I've switched to xmonad. Here's a script that works for xmobar:

#!/bin/sh

email='my_email@gmail.com'
full_text=$(~/bin/gmail-count "$email")

case $full_text in
  ''|*[!0-9]*) color=\#FF0000 ;;
  0)           color=\#888888 ;;
  *)           color=\#00FF00 ;;
esac

echo "<action=\`xdg-open https://inbox.google.com\`><fc=$color>✉ $full_text</fc></action>"

@julianandrews
Copy link
Author

@Anachron: Your script really doesn't do what I need from a security point of view. It stores the password in plaintext and requires using lower security methods for access (I'm using 2-factor authentication and an app specific password).

Take out my code for using the system keyring and my argument parsing to make a nice clean interface and you'll find that my script is pretty short.

@julianandrews
Copy link
Author

Updated to work with python 3. I also switched from urllib2 to requests, which is cleaner, and removed the verbose flag in favor of just printing to stderr. This way I can still output ? for failed attempts so that the output for xmobar etc. is reasonable, but the script reliably provides helpful error messages when used from the command line.

@julianandrews
Copy link
Author

I've gone ahead and made a proper repo for this script:

I was fiddling with it compulsively, and it seemed worth the trouble:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment