this post was submitted on 19 Dec 2023
20 points (91.7% liked)

Selfhosted

40219 readers
1060 users here now

A place to share alternatives to popular online services that can be self-hosted without giving up privacy or locking you into a service you don't control.

Rules:

  1. Be civil: we're here to support and learn from one another. Insults won't be tolerated. Flame wars are frowned upon.

  2. No spam posting.

  3. Posts have to be centered around self-hosting. There are other communities for discussing hardware or home computing. If it's not obvious why your post topic revolves around selfhosting, please include details to make it clear.

  4. Don't duplicate the full text of your blog or github here. Just post the link for folks to click.

  5. Submission headline should match the article title (don’t cherry-pick information from the title to fit your agenda).

  6. No trolling.

Resources:

Any issues on the community? Report it using the report flag.

Questions? DM the mods!

founded 1 year ago
MODERATORS
 

Hi fellow self-hosting lemmings,

In an SME setting, I'm looking for a service to regularly fetch mails from an IMAP server and print incoming mails and attachments on a local network printer based on rules (e.g., only print mails where the subject contains a specific word.)

Does a solution like that exist, ideally with a browser frontend to set it up?

Thank you!

you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 2 points 11 months ago* (last edited 11 months ago) (1 children)

You might use Node Red with this node to obtain the attachments, then send to an IPP printer with this node.

[–] [email protected] 2 points 11 months ago* (last edited 11 months ago) (2 children)

Now this is an idea I like. Thank you so much, I never would have considered Node-RED for this application!

[–] [email protected] 1 points 11 months ago* (last edited 11 months ago) (1 children)

I actually use NR to keep an eye on my CUPS print queue for jobs waiting, and it sends a wakeup to a tasmota wall plug to turn on the printer and then turn it off in 5 minutes. This lets me have a network printer always ready, but not using power in idle. This might work in with your project.

spoiler[{"id":"6f4056a8.eb32","type":"inject","z":"f268801.6c137","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":240,"wires":[["5e57130e.32c56c"]]},{"id":"5a7d9cb9.82e2ac","type":"html","z":"f268801.6c137","name":"","property":"payload","outproperty":"payload","tag":".list > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(1) > a:nth-child(1)","ret":"html","as":"single","x":370,"y":300,"wires":[["667f6421.e13924"]]},{"id":"5e57130e.32c56c","type":"http request","z":"f268801.6c137","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://10.10.251.50:631/jobs?","tls":"","persist":false,"proxy":"","authType":"","x":420,"y":240,"wires":[["5a7d9cb9.82e2ac"]]},{"id":"667f6421.e13924","type":"split","z":"f268801.6c137","name":"","splt":"\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":180,"y":380,"wires":[["836d047d.c5a41"]]},{"id":"836d047d.c5a41","type":"switch","z":"f268801.6c137","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"HP_LaserJet_4000_Series","vt":"str"},{"t":"null"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":380,"wires":[["474b85e1.a317ec"],[]]},{"id":"be8ec1f.57fad4","type":"Tasmota Switch","z":"f268801.6c137","broker":"4ba22e0f7edb8148","device":"tasmota_LJ4000","name":"","outputs":1,"uidisabler":false,"fullTopic":"","cmndPrefix":"","statPrefix":"","telePrefix":"","x":700,"y":380,"wires":[[]]},{"id":"474b85e1.a317ec","type":"trigger","z":"f268801.6c137","name":"","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"5","extend":true,"overrideDelay":false,"units":"min","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":510,"y":380,"wires":[["be8ec1f.57fad4"]]},{"id":"316b902c.639208","type":"comment","z":"f268801.6c137","name":"LaserJet 4k Wakeup on Print","info":"","x":140,"y":200,"wires":[]},{"id":"4ba22e0f7edb8148","type":"tasmota-mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"keepalive":"60","cleansession":true}]

[–] [email protected] 1 points 11 months ago

I do actually use Node-RED myself for my zigbee home automation. Funny how it never crossed my mind to pick it up for this. It's perfect as I want a non-programmer to be able to maintain it.

I doubt my solution will be much more than ingest and print, but I'll report back. Still fighting to get that hp p3015 to do something over IPP...

[–] [email protected] 1 points 11 months ago (1 children)

BTW, if you do end up using this method, I'd love to see your implementation some day. Node Red is so useful and intuitive IMO, and people sharing their solutions is valuable.

[–] [email protected] 2 points 10 months ago* (last edited 10 months ago) (1 children)

One deep dive into the IPP protocol, printer drivers, and specific supported formats ("what the hell is an octet-stream?!") later, I have something functional.

I'm not a JS guy, so I don't know if it's a very node-y way to do it. But except for the pages coming out a little scaled this works:

Edit to briefly explain what this does: The mail node ingests unread emails and passes them forward to a function node that checks for pdf attachments. Those are passed forward one by one to a function node that takes care of converting the pdf to pcl (my printer supposedly knows how to handle pdf 1.7 but doesn't, so I had to resort to this) and passes it to the IPP node as a data buffer .

spoiler[ { "id": "86082bed0ed29155", "type": "IPPrint", "z": "08cc7c15668f2f65", "name": "Print to Network", "IP": "10.10.0.19:631/ipp/print", "JOB_name": "default_job_name", "authuser": "", "authpassword": "", "authcheck": "", "x": 780, "y": 120, "wires": [ [ "b1a8b92ede8a78a5" ] ] }, { "id": "b1a8b92ede8a78a5", "type": "debug", "z": "08cc7c15668f2f65", "name": "debug 1", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 960, "y": 120, "wires": [] }, { "id": "1fb7fc3843af8e05", "type": "function", "z": "08cc7c15668f2f65", "name": "Convert PDF to PCL", "func": "const baseOptions = {\n width: 2480,\n height: 3508,\n density: 300,\n preserveAspectRatio: true,\n format: 'PCL'\n};\n\n// prepare conversion function\nconst convert = await pdf2pic.fromBuffer(msg.payload, baseOptions);\n// set additional conversion options\nconvert.setGM\n// bulk convert the whole input buffer to a pcl output buffer\nconvert.bulk(-1, {responseType: \"buffer\"}).then((outputs)=>{\n // pass each page on to the printer\n outputs.forEach((output, index) => {\n msg.payload = output.buffer;\n if(msg.topic){\n let jobname = msg.topic\n }\n msg.JOBName = (msg.topic ? msg.topic : \"Mailjob\").concat(\" \", index+1, \"/\", outputs.length);\n msg.docFormat = \"application/octet-stream\";\n node.send(msg);\n });\n});\n", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [ { "var": "pdf2pic", "module": "pdf2pic" } ], "x": 560, "y": 120, "wires": [ [ "86082bed0ed29155" ] ] }, { "id": "224317e794da3cb5", "type": "e-mail in", "z": "08cc7c15668f2f65", "name": "Mail ingest", "protocol": "IMAP", "server": "test.mail.com", "useSSL": false, "autotls": "always", "port": "143", "authtype": "BASIC", "saslformat": true, "token": "oauth2Response.access_token", "box": "INBOX", "disposition": "Read", "criteria": "UNSEEN", "repeat": "300", "fetch": "auto", "inputs": 0, "x": 160, "y": 80, "wires": [ [ "2fedaa18c9394b89" ] ] }, { "id": "2fedaa18c9394b89", "type": "function", "z": "08cc7c15668f2f65", "name": "PDF Filter", "func": "if(msg.attachments.length > 0){\n msg.attachments.forEach(function(attachment) {\n if(attachment.contentType == \"application/pdf\"){\n var newmsg = {};\n newmsg.topic = msg.topic;\n newmsg.filename = attachment.filename;\n newmsg.payload = attachment.content;\n node.send(newmsg);\n }\n });\n}", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 360, "y": 80, "wires": [ [ "1fb7fc3843af8e05" ] ] }, { "id": "3d8f7ad8e6b56d46", "type": "inject", "z": "08cc7c15668f2f65", "name": "Test print", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 160, "y": 160, "wires": [ [ "683ed6fe7c10540d" ] ] }, { "id": "683ed6fe7c10540d", "type": "file in", "z": "08cc7c15668f2f65", "name": "", "filename": "/data/2517.pdf", "filenameType": "str", "format": "", "chunk": false, "sendError": false, "encoding": "none", "allProps": false, "x": 340, "y": 160, "wires": [ [ "1fb7fc3843af8e05" ] ] } ]

[–] [email protected] 2 points 10 months ago* (last edited 10 months ago) (1 children)

Nicely done, for not a JS guy. I'd have be a while longer figuring out that process.

Not sure what to suggest on the scaling, that might be happening in your conversion to PCL, you might be able to execute that as a ghostscript process on the host and then just stream the resulting file out of the filesystem to the print node, or even just drop it to a queue folder and cut the IPP node out entirely to eliminate it as a source of the scaling.

Edit: https://github.com/NickNaso/ghostscript4js

[–] [email protected] 2 points 10 months ago* (last edited 10 months ago)

A very welcome compliment after this ordeal. Thank you! :)

The cleanest way to solve the scaling issue would probably be to go into the pdf2pic module and hack it open to accept the "pcl:fit-to-page" option that GraphicsMagick (the underlying software package doing the actual conversion from PDF to PCL) supports. (Supposing it actually does what it says. I'm not so sure about anything in printer land anymore.)

But since this whole thing is for internal documents only and the scaling can probably be estimated by choosing better values for width/height to account for printer margins I most likely won't bother.

Thanks again for suggesting Node-RED. I'm very happy with the result.