Print mails with LPD

Je vous propose ici une méthode sous Linux permettant de créer une imprimante virtuelle qui va envoyer l’impression en pièce jointe par mail. On utilisera ici le bon vieux service lpd

Configuration

Pour configurer cette imprimante il convient de modifier le fichier /etc/printcap.local et d’ajouter l’entrée suivante:

VirtualMailPrinter:\
    :ml#0:\
    :mx#0:\
    :sd=/var/spool/lpd/VirtualMailPrinter:\
    :sh:\
    :lp=/dev/null:\
    :if=/usr/local/bin/copy_lpd_to_mail.py:
  • ml: nombre minimum de caractères pour imprimer
  • mx: taille maximale du job
  • sd: spooler
  • sh: S’il faut supprimer les en-têtes
  • lp: sortie d’impression (ici nulle part)
  • if: filtre avant impression. C’est lui qui va capturer le contenu pour l’envoyer par mail

On redémarre ensuite le service lpd. Celui-ci va lire les entrées dans /etc/printcap.local et les ajouter dans /etc/printcap.

On va ensuite créer le script python (v2.7) /usr/local/bin/copy_lpd_to_mail.py qui va se charger de lire l’entrée standard (stdin), écrire le contenu dans un fichier temporaire puis le joint par mail avant de l’envoyer à la personne configurée.

Le choix de python est dû au fait que bash ne gère pas correctement la lecture de stdin pour des fichiers dans un format non textuel. Si votre interpréteur python n’est pas celui ci-dessous, changez le également.

#! /usr/local/bin/python2.7
import sys, os
import smtplib
import mimetypes
from email.mime.base import MIMEBase
from email import encoders
from email.mime.multipart import MIMEMultipart

# Params
tmpfileName = '/tmp/mail.tmp'
mailDest = "destination@example.org"
mailSrc = "lpd@myserver.example.org"

# Write stdin (printer) to file
f = open(tmpfileName, 'w')
for line in sys.stdin:
        f.write(line)
f.close()

# Create E-mail
outer = MIMEMultipart()
outer['Subject'] = 'Impression To Mail'
outer['To'] = mailDest
outer['From'] = mailSrc
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'

# Read our file and join it to mail
ctype, encoding = mimetypes.guess_type(tmpfileName)
if ctype is None or encoding is not None:
        # No guess could be made, or the file is encoded (compressed), so
        # use a generic bag-of-bits type.
        ctype = 'application/octet-stream'

maintype, subtype = ctype.split('/', 1)

fp = open(tmpfileName, 'rb')
msg = MIMEBase(maintype, subtype)
msg.set_payload(fp.read())
fp.close()
encoders.encode_base64(msg)
msg.add_header('Content-Disposition', 'attachment', filename="export_lpd.txt")
outer.attach(msg)
composed = outer.as_string()

# Send the mail
s = smtplib.SMTP('localhost')
s.sendmail(mailSrc, mailDest, composed)
s.quit()

See Also