#!/usr/bin/python
#
# Usage: faxnotify log-file image-file [image-file ...]
#
# This script converts received fax TIFF files to a PDF
# file and delivers them according to the fax preferences.
#
import os, sys, string
import shutil, errno, socket
from email import Encoders
from email.Message import Message
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
def defaults_read(key, domain = '/Library/Preferences/com.apple.print.FaxPrefs'):
"""Read the value of 'key' from the defaults system"""
i,o,e = os.popen3('/usr/bin/defaults read ' + domain + ' ' + key)
i.close()
value = string.rstrip(o.read())
o.close()
e.close()
return value
def quote(x):
"""Add quotes to a shell command argument string"""
if '\'' not in x :
return '\'' + x + '\''
s = '"'
for c in x:
if c in '\\$"`':
s = s + '\\'
s = s + c
s = s + '"'
return s
def remote_id():
"""Find the sender's phone number so it can be used in the PDF name"""
try:
remote_id = os.environ['REMID']
except:
remote_id = '?'
if remote_id == '?' :
remote_id = 'Unknown'
return remote_id
def copy_versioned_file(srcfile, dstdir):
"""Copy a file to a directory adding versioning as needed"""
fsrc = None
fdst = None
if not os.path.isdir(dstdir) :
print >> sys.stderr, 'faxnotify: Save to directory missing ' + quote(dstdir.encode('unicode-escape'))
return -1
old_uid = os.getuid()
old_mask = os.umask(002)
try:
# open src as root
fsrc = open(srcfile, 'rb')
# get the owner of the destination directory
dstdir_owner = os.lstat(dstdir).st_uid
# step down to the dir owner's uid before creating the file
os.seteuid(dstdir_owner)
# create the full path for the destination file and seperate
# the components in case we have to version it
dstfile = dstdir + '/' + os.path.split(srcfile)[1]
name, ext = os.path.splitext(dstfile)
for i in xrange(1, 10000):
try:
fd = os.open(dstfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
fdst = os.fdopen(fd, 'wb')
break
except (OSError, IOError), e:
if e.errno != errno.EEXIST:
raise
# file exists, find next available version
dstfile = '%s %d%s' % (name, i, ext)
# we've created a new unique file, now copy the contents of src into it
shutil.copyfileobj(fsrc, fdst)
except (OSError, IOError), e:
print >> sys.stderr, 'faxnotify: Save to failed;' , e
except:
print >> sys.stderr, 'faxnotify: Save to ' + quote(dstdir.encode('unicode-escape')) + ' failed'
pass
if fsrc:
fsrc.close()
if fdst:
fdst.close()
os.umask(old_mask)
os.seteuid(old_uid)
return 0
def email_fax(receipents, sender, pdffile):
"""Send email to the receipents with an attached file"""
msg = MIMEMultipart()
msg['Subject'] = pdffile
msg['To'] = receipents
msg['From'] = sender
msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
# To guarantee the message ends with a newline
msg.epilogue = ''
fp = open(pdffile)
pdf = MIMEBase('application', 'pdf')
pdf.set_payload(fp.read())
fp.close()
# Encode the payload using Base64
Encoders.encode_base64(pdf)
# Set the filename parameter
pdf.add_header('Content-Disposition', 'attachment', filename=pdffile)
msg.attach(pdf)
stdout, stdin = os.popen2('/usr/sbin/sendmail -oi -t -r' + quote(sender))
stdout.write(msg.as_string())
stdout.close()
stdin.close()
#
# Make sure we have enough arguments
#
if len(sys.argv) == 1 :
print >> sys.stderr, 'Usage: faxnotify log-file image-file [image-file ...]'
sys.exit(2)
# If there are no tiff files to process just exit quietly.
if len(sys.argv) == 2 :
sys.exit(0)
tiff_files = string.join(map(quote, sys.argv[2:]))
pdf_file = 'FAX from ' + remote_id() + '.pdf'
try:
# Convert TIFFs into a single PDF
command = '/usr/libexec/fax/imagestopdf ' + tiff_files + ' ' + quote(pdf_file)
if os.system(command) :
print >> sys.stderr, 'faxnotify: ' + command + ' failed'
sys.exit(1)
# Print on printer
if defaults_read('PrintFax') == '1' :
printer = quote(defaults_read('PrinterID'))
faxuser = defaults_read('FaxUser')
if faxuser == '' :
faxuser = 'FaxNotify'
faxuser = quote(faxuser)
command = '/usr/bin/lpr -P ' + printer + ' -U ' + faxuser + ' ' + quote(pdf_file)
if os.system(command) :
print >> sys.stderr, 'faxnotify: Print on printer ' + printer + ' failed'
# Save to
if defaults_read('SaveFax') == '1' :
copy_versioned_file(pdf_file, unicode(defaults_read('SavePath'), 'unicode-escape'))
# Email to
if defaults_read('EmailFax') == '1' :
recipients = defaults_read('EmailRecipient')
sender = defaults_read('EmailSender')
if sender == '' :
if socket.gethostname()[-7:] == '.local.' :
sender = recipients.split(',')[0].strip(whitespace + '<>')
else :
sender = 'FaxNotify'
email_fax(recipients, sender, pdf_file)
finally:
# Remove the TIFFs and converted PDF
map(os.remove, sys.argv[2:])
if os.path.exists(pdf_file):
os.remove(pdf_file)