email-to-print
My family emails a PDF or a photo to a print address on our domain. A small
Python script watches that mailbox, checks the sender against a list of four
people, converts the file if it needs converting, and hands it to CUPS. The
printer is a boring HP laser from 2017. That's the whole system.
A bunch of people asked for a writeup after I posted about this, so this
README is the writeup. Fair warning that none of it is clever. It's mostly
plumbing, and half of it is a mail filter.
The expanded version — full architecture walkthrough plus answers to every
question from the Reddit thread (duplex control, dedup, the watched-folder and
QR-card variants) — lives here:
https://benchnotes.net/blog/email-to-print-self-hosted/
The reason it exists is dumber than the system. My wife would airdrop me a
permission slip, I'd open it on my desktop, print it, and wonder why I was
involved at all. The printer vendors solve this with their cloud print
services, but I didn't want school forms bouncing through someone else's
servers, and those services have a habit of getting discontinued.
This is the actual code running in my house, with my personal values
stripped out. It's been printing homework and permission slips since spring
2026.
The pieces
phone/laptop
| email with attachment
v
your mail provider -> (ProtonMail Bridge, if Proton) -> IMAP folder
|
print-poller (this repo)
|
allowlist check -> convert -> lp
|
CUPS -> printer
The mailbox is a Proton account I already had. Proton doesn't do plain IMAP,
so ProtonMail Bridge runs in Docker and exposes the account as IMAP on
localhost. The bridge uses a self-signed cert, which is why the example env
sets TLS_VERIFY=false; that setting is for localhost only, and verification
stays on for anything else. If you use Gmail or anything normal you can skip
the bridge entirely and point straight at your provider. The compose pins
the bridge image to the exact digest running in my house; it's a community
image, so read the comment above it bef