this is a python3 example of how one might use Dispatch to send notifications on events. it's nothing robust but it gets the job done, generally
122 lines
3.9 KiB
Python
122 lines
3.9 KiB
Python
"""
|
|
procmail-to-dispatch.py --- use dr.botzo's Dispatch to send mail notifications
|
|
|
|
"""
|
|
|
|
import argparse
|
|
import getpass
|
|
import glob
|
|
import logging
|
|
import os
|
|
import re
|
|
import sys
|
|
import time
|
|
import xmlrpc.client
|
|
|
|
# set up some basic logging
|
|
logger = logging.getLogger()
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
logger.addHandler(handler)
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
# set up config flags
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-f', '--filename')
|
|
parser.add_argument('-k', '--key')
|
|
parser.add_argument('-l', '--location')
|
|
parser.add_argument('-u', '--user')
|
|
args = parser.parse_args()
|
|
|
|
if (args.filename == None or args.key == None or args.user == None or
|
|
args.location == None):
|
|
print("script needs -f/--filename (location of .procmailrc.log) -k/--key (dispatch key to use) "
|
|
"-l/--location (url to connect to) -u/--user (user to authenticate to XML-RPC as)")
|
|
sys.exit(2)
|
|
|
|
password = getpass.getpass("password for {0:s}: ".format(args.user))
|
|
|
|
drbotzo = xmlrpc.client.ServerProxy("https://{0:s}:{1:s}@{2:s}".format(args.user, password, args.location))
|
|
if 'dispatch' not in drbotzo.system.listMethods():
|
|
print("remote dr.botzo instance doesn't seem to implement 'dispatch'!")
|
|
sys.exit(2)
|
|
|
|
file = open(args.filename, 'r')
|
|
|
|
folderre = re.compile("^ Folder: (\S+)\s+\d+$")
|
|
senderre = re.compile("^From: (.*)$")
|
|
subjectre = re.compile("^Subject: (.*)$")
|
|
|
|
# start file at the end
|
|
st_results = os.stat(args.filename)
|
|
st_size = st_results[6]
|
|
file.seek(st_size)
|
|
|
|
def get_mail_items(filename):
|
|
sender = None
|
|
subject = None
|
|
|
|
for num, line in enumerate(open(filename)):
|
|
if senderre.search(line):
|
|
match = senderre.search(line)
|
|
sender = match.group(1)
|
|
if subjectre.search(line):
|
|
match = subjectre.search(line)
|
|
subject = match.group(1)
|
|
|
|
if sender and subject:
|
|
return (sender, subject)
|
|
|
|
if sender:
|
|
return (sender, "[no subject]")
|
|
|
|
while 1:
|
|
try:
|
|
filename = None
|
|
|
|
where = file.tell()
|
|
line = file.readline()
|
|
if not line:
|
|
time.sleep(1)
|
|
file.seek(where)
|
|
else:
|
|
if folderre.search(line):
|
|
sender = None
|
|
subject = None
|
|
|
|
match = folderre.search(line)
|
|
filename = match.group(1)
|
|
|
|
# ignore /dev/null, of course
|
|
if filename == "/dev/null":
|
|
logger.debug("skipping message forwarded to /dev/null")
|
|
continue
|
|
|
|
# ignore Spam
|
|
if filename.find(".Spam") > 0:
|
|
logger.debug("skipping spam '{0:s}'".format(filename))
|
|
continue
|
|
|
|
# try opening the actual path. this is a bit racey
|
|
logger.debug("trying to open '{0:s}'".format(filename))
|
|
if os.path.isfile(filename):
|
|
logger.debug("opening '{0:s}'".format(filename))
|
|
(sender, subject) = get_mail_items(filename)
|
|
else:
|
|
# ok... maybe something already moved it into cur. in addition
|
|
# they probably added flags at the end
|
|
filepattern = filename.replace("/new", "/cur") + "*"
|
|
for globhit in glob.glob(filepattern):
|
|
logger.debug("trying to open '{0:s}'".format(globhit))
|
|
if os.path.isfile(globhit):
|
|
logger.debug("opening '{0:s}'".format(globhit))
|
|
(sender, subject) = get_mail_items(globhit)
|
|
|
|
if sender and subject:
|
|
logger.debug("notifying: '{0:s}' from {1:s}".format(subject, sender))
|
|
drbotzo.dispatch(args.key, "'{0:s}' from {1:s}".format(subject, sender))
|
|
except UnicodeDecodeError as e:
|
|
logger.error("Error: " + str(e) + ", skipping")
|
|
pass
|
|
|
|
# vi:tabstop=4:expandtab:autoindent
|