Skip to content

Instantly share code, notes, and snippets.

@silvercircle
Created November 6, 2022 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save silvercircle/e4d6a2a0dc21afb972a9787614fcff49 to your computer and use it in GitHub Desktop.
Save silvercircle/e4d6a2a0dc21afb972a9787614fcff49 to your computer and use it in GitHub Desktop.
Python script to create desktop notifications for new mail that can be used by procmail
#!/usr/bin/python
# simple procmail filter to display a desktop notification
# usage: mailnotify username. Excepts the mail on stdin
# this is meant to live in a procmail recipe, for example:
# pipe the msg to this script to send a notification and deliver via
# dovecot-lda
#:0
#{
# :0c
# |/home/foobar/.local/bin/mailnotify.py foobar
# :0:
# |/usr/libexec/dovecot/dovecot-lda
#}
import sys
import os
import email
from email.parser import HeaderParser
from email.header import decode_header
import dbus
from pwd import getpwnam
nargs = len(sys.argv)
# you can customize this to set a different icon
desktop_entry = "thunderbird"
# missing user name argument -> exit
if nargs < 2:
sys.exit(0)
euid = getpwnam(sys.argv[1]).pw_uid
# no stdin input -> exit
if os.isatty(sys.stdin.fileno()):
sys.exit(0)
the_mail = sys.stdin
# performance: only parse headers, we do not need the body
parser = HeaderParser()
msg = parser.parse(the_mail)
# msg = email.parser.Parser().parse(the_mail)
# we need sender and the subject, not more
if "from" in msg and "subject" in msg:
decoded_subject, charset = decode_header(msg["subject"])[0]
decoded_from, charset = decode_header(msg["from"])[0]
os.seteuid(euid) # because procmail invoked by sendmail may run
# as root
item = "org.freedesktop.Notifications"
# notfy_intf = dbus.Interface(dbus.SessionBus().get_object(item, "/"+item.replace(".", "/")), item)
# since procmail may run as root, we need to connect to the user's session bus
# using the dbus socket. Using the dbus.SessionBus() won't work because it would
# try to find root's session bus (which does not exist)
# the desired user must be passed to this script as user name.
bus_socket = "unix:path=/run/user/%s/bus" % euid
# try to connect to the bus. if it fails, just bail out.
try:
notfy_intf = dbus.Interface(dbus.bus.BusConnection(bus_socket).get_object(item, "/"+item.replace(".", "/")), item)
notfy_intf.Notify("New e-Mail message", 0, "emblem-mail",
decoded_subject, decoded_from, [],
{"urgency": 1, "action-icons": True, "desktop-entry": desktop_entry}, 5000)
notfy_intf.close();
# print(msg)
except dbus.exceptions.DBusException:
sys.exit(0)
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment