Skip to content

Instantly share code, notes, and snippets.

@zealot128 zealot128/README.md

Last active Apr 21, 2020
Embed
What would you like to do?
Papercut simple replacement = IMAP to print

Papercut replacement

  • imap to print
  • use case: on a Raspi oder Office server that hangs in the same LAN like the printer and can print via cups/system using "lp"
  • just uses lp under the hood
  • uses the awesome mail_room Gem under the hood to handle imap connection, which does most of the lifting

Send Mail as a authorized return-path (via regex matching) to your mailbox, it will print all pdf Attachments.

USAGE

create config.yml

---
:email: "print@mycompany.de"
:password: "securepassword"
:host: 'imap.mycompany.de'
:port: 993
:ssl: true
:start_ssl: false
:delete_after_delivery: true
:expunge_deleted: true
:name: "inbox"
:search_command: 'NEW'
:delivery_method: "print_attachments"
:delivery_options:
  :whitelist_from: ".*@mycompany.de$"
  # Modify lp command to change media format, or address, see lp -h for all options
  :lp_command: "lp -o media=a4 -o sides=two-sided-long-edge"
ruby run.rb

Or wrap with your favourite init tool.

require 'bundler/inline'
gemfile do
source "https://rubygems.org"
gem 'mail'
gem 'mail_room'
gem 'pry'
end
require 'open3'
module MailRoom
module Delivery
class PrintAttachments
Options = Class.new do
def initialize(config)
@config = config.delivery_options
@logger = config.logger
super()
end
attr_reader :config
attr_reader :logger
def lp_command
@config[:lp_command] || "lp"
end
def whitelisted?(mail)
return true if @config[:whitelist_from].nil? || @config[:whitelist_from] == ""
regex = Regexp.new(@config[:whitelist_from])
mail.return_path[regex]
end
end
def initialize(config)
@config = config
end
def deliver(*args)
mail = Mail.new(args.first)
if @config.whitelisted?(mail)
print!(mail)
else
@config.logger.warn "unpermitted return-path #{mail.return_path} #{mail.message_id}"
end
true
end
def print!(mail)
attachments = mail.attachments.select { |i| i.content_type['application/pdf'] }
if attachments.length == 0
@config.logger.warn "No pdf attachments found in mail #{mail.message_id}"
return
end
attachments.each do |pdf|
print_attachment(pdf)
end
end
def print_attachment(pdf)
save_name = pdf.filename.gsub(/[^\w\.]+/, '-')
tf = Tempfile.new(['mail_room_print_attachments', save_name])
tf.binmode
tf.write pdf.body.decoded
tf.rewind
command = "#{@config.lp_command} #{Shellwords.escape(tf.path)}"
stdout, stderr, status = Open3.capture3(command)
if status.success?
@config.logger.info("Printing #{save_name}: #{command}")
else
@config.logger.error("Printing failed: #{stderr}")
end
end
end
end
end
class MailRoom::Mailbox
def delivery_klass
MailRoom::Delivery::PrintAttachments
end
end
mailboxes = [
mb = MailRoom::Mailbox.new(YAML.load_file('config.yml'))
]
logger = Logger.new(STDOUT)
logger.formatter = proc do |severity, datetime, progname, msg|
"#{severity} #{datetime.strftime("%Y-%m-%dT%H:%M:%S")}: #{msg}\n"
end
mailboxes.first.instance_variable_set("@logger", logger)
$coordinator = MailRoom::Coordinator.new(mailboxes)
def start
Signal.trap(:INT) do
$coordinator.running = false
end
Signal.trap(:TERM) do
exit
end
puts "Starting MailRoom Server"
$coordinator.run
rescue Exception => e # not just Errors, but includes lower-level Exceptions
p e
puts e.backtrace
exit
end
start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.