#!/usr/bin/env ruby

ENV_FILE    = "/etc/postfix/mail-receiver-environment.json"
EX_TEMPFAIL = 75
EX_SUCCESS  = 0

require 'syslog'
require 'json'
require "uri"
require "net/http"

def logger
	@logger ||= Syslog.open("receive-mail", Syslog::LOG_PID, Syslog::LOG_MAIL)
end

def fatal(*args)
	logger.crit *args
	exit EX_TEMPFAIL
end

def main
	unless File.exists?(ENV_FILE)
		fatal "Config file %s does not exist. Aborting.", ENV_FILE
	end

	real_env = JSON.parse(File.read(ENV_FILE))

	%w{DISCOURSE_BASE_URL DISCOURSE_API_KEY DISCOURSE_API_USERNAME}.each do |kw|
		fatal "env var %s is required", kw unless real_env[kw]
	end

	recipient = ARGV.first
	mail      = $stdin.read

	logger.debug "Recipient: #{recipient}"
	fatal "No recipient passed on command line." unless recipient
	fatal "No message passed on stdin." if mail.nil? || mail.empty?

	post_email(recipient, mail, real_env)
rescue StandardError => ex
	logger.err "Unexpected error while invoking mail processor: %s (%s)", ex.message, ex.class
	logger.err ex.backtrace.map { |l| "  #{l}" }.join("\n")

	exit EX_TEMPFAIL
end

def post_email(_recipient, mail, env)
	endpoint = "#{env['DISCOURSE_BASE_URL']}/admin/email/handle_mail"	
	key      = env["DISCOURSE_API_KEY"]
	username = env["DISCOURSE_API_USERNAME"]

	uri = URI.parse(endpoint)

	begin
		http = Net::HTTP.new(uri.host, uri.port)
		http.use_ssl = uri.scheme == "https"
		post = Net::HTTP::Post.new(uri.request_uri,"api-key" => "#{key}", "api-username" =>  "#{username}")
		post.set_form_data(email: mail)

		response = http.request(post)
	rescue StandardError => ex
		logger.err "Failed to POST the e-mail to %s: %s (%s)", endpoint, ex.message, ex.class
		logger.err ex.backtrace.map { |l| "  #{l}" }.join("\n")
		exit EX_TEMPFAIL
	ensure
		http.finish if http && http.started?
	end

	exit EX_SUCCESS if Net::HTTPSuccess === response

	logger.err "Failed to POST the e-mail to %s: %s", endpoint, response.code
	exit EX_TEMPFAIL
end

main if __FILE__ == $0
