added services

This commit is contained in:
Mike Sutton
2022-11-16 01:02:18 +01:00
parent 329e66c949
commit 9d256dfcba
52 changed files with 1419 additions and 0 deletions

View File

View File

@ -0,0 +1,63 @@
# frozen_string_literal: true
require 'mail'
require 'bunny'
# in module for neatness
module Bettermail
# The General purpose consumer
class Consumer
def initialize
end
def default_smtp_settings
{
address: ENV['DEFAULT_SMTP_HOST'],
port: ENV['DEFAULT_SMTP_PORT'],
user_name: ENV['DEFAULT_SMTP_UID'],
password: ENV['DEFAULT_SMTP_PWD'],
enable_starttls_auto: true,
authentication: 'plain',
}
end
def start
begin
puts ' [*] Waiting for messages. To exit press CTRL+C'
new_mail_queue = bunny_channel.queue(ENV['RABBIT_MAIL_QUEUE'])
new_mail_queue.subscribe(block: true) do |_delivery_info, _properties, body|
instructions = JSON.parse(body)
recipient = Recipient.create_or_find_by(id: instructions["recipient"])
email = ReceivedMail.find_by(message_id: instructions["message"])
recipient.emails.create(received_mail: email, delivery_status: 'queued')
end
sns_queue = bunny_channel.queue(ENV['RABBIT_SNS_QUEUE'])
sns_queue.subscribe(block: true) do |_delivery_info, _properties, body|
puts " [x] Received #{_delivery_info}"
end
rescue Interrupt => _
stop
end
end
def send_mail(mail)
mail.delivery_method :smtp, default_smtp_settings
mail.deliver!
end
def stop
@bunny_conn&.close
end
def bunny_channel
if @bunny_channel.nil?
@bunny_conn = Bunny.new
@bunny_conn.start
@bunny_channel = @bunny_conn.create_channel
end
@bunny_channel
end
end
end

View File

@ -0,0 +1,79 @@
# frozen_string_literal: true
require 'midi-smtp-server'
require 'mail'
require 'bunny'
require 'securerandom'
# in module for neatness
module Bettermail
# The SMTPProxy
class Proxy < MidiSmtpServer::Smtpd
def stop(wait_seconds_before_close: nil, gracefully: nil)
super()
@bunny_conn&.close
end
def bunny
if @bunny.nil?
@bunny_conn = Bunny.new
@bunny_conn.start
ch = @bunny_conn.create_channel
ch.direct(ENV['RABBIT_CHANNEL'])
ch.queue(ENV['RABBIT_MAIL_QUEUE'])
@bunny = ch.default_exchange
end
@bunny
end
# update local welcome and helo response
def on_connect_event(ctx)
ctx[:server][:local_response] = 'Client connected'
ctx[:server][:helo_response] = 'Welcome to the BetterMail proxy - an SMTP drop in replacement'
end
def on_message_data_headers_event(ctx)
# check and append all headers
ctx[:message][:data] << "X-bettermail: Received by proxy at #{Time.now}" << ctx[:message][:crlf]
end
# check the authentication
# if any value returned, that will be used for ongoing processing
# otherwise the original value will be used for authorization_id
def on_auth_event(ctx, authorization_id, authentication_id, authentication)
# to proceed this test use commands ...
# auth plain
# > AGFkbWluaXN0cmF0b3IAcGFzc3dvcmQ=
# auth login
# > YWRtaW5pc3RyYXRvcg==
# > cGFzc3dvcmQ=
# if authorization_id == '' && authentication_id == 'administrator' && authentication == 'password'
# # yes
# return 'supervisor'
# end
# # otherwise exit with authentication exception
# raise MidiSmtpServer::Smtpd535Exception
logger.debug("Authenticated id: #{authentication_id} with authentication: #{authentication} from: #{ctx[:server][:remote_ip]}:#{ctx[:server][:remote_port]}")
authentication_id
end
def save_mail(ctx, sender)
mail = Mail.read_from_string(ctx[:message][:data])
sender = Sender.create_or_find_by(id: sender)
message_id = "#{SecureRandom.uuid}@bettermail.wizewerx.tech"
saved_mail = sender.sent_mails.create(message_id: message_id, body: mail.to_s)
message_id
end
def on_mail_from_event(ctx, mail_from_data)
# tag the message here OR write it once to the database
ctx[:message][:message_id] = save_mail(ctx, mail_from_data)
end
# simple rewrite and return value
def on_rcpt_to_event(ctx, data)
bunny.publish({message: ctx[:message][:message_id], recipient: data}.to_json, :headers => { }, :routing_key => ENV["RABBIT_MAIL_QUEUE"])
end
end
end

0
services/lib/tasks/.keep Normal file
View File

View File

@ -0,0 +1,46 @@
namespace :consumer do
task start: :environment do
service_name = 'BetterMail::Consumer'
# Create a new server instance for listening at localhost interfaces 127.0.0.1:2525
# and accepting a maximum of 4 simultaneous connections per default
service = Bettermail::Consumer.new
# save flag for Ctrl-C pressed
flag_status_ctrl_c_pressed = false
# try to gracefully shutdown on Ctrl-C
trap('INT') do
# print an empty line right after ^C
puts
# notify flag about Ctrl-C was pressed
flag_status_ctrl_c_pressed = true
# signal exit to app
exit 0
end
# Output for debug
puts("Starting #{service_name}")
# setup exit code
at_exit do
# check to shutdown connection
if service
# Output for debug
puts('Ctrl-C interrupted, exit now...') if flag_status_ctrl_c_pressed
# info about shutdown
puts("Shutdown #{service_name}...")
# stop all threads and connections gracefully
service.stop
end
# Output for debug
puts "#{service_name} stopped!"
end
# Start the server
service.start
# Run on server forever
service.join
end
end

View File

@ -0,0 +1,58 @@
namespace :proxy do
task start: :environment do
# Create a new server instance for listening at localhost interfaces 127.0.0.1:2525
# and accepting a maximum of 4 simultaneous connections per default
service = Bettermail::Proxy.new(
ports: ENV['PROXY_PORTS'],
hosts: ENV['PROXY_HOSTS'],
max_processings: 10,
auth_mode: :AUTH_REQUIRED,
tls_mode: :TLS_REQUIRED,
tls_cert_path: './ssl/cert.pem',
tls_key_path: './ssl/key.pem'
)
service_name = 'BetterMail::SMTPProxy'
# Create a new server instance for listening at localhost interfaces 127.0.0.1:2525
# and accepting a maximum of 4 simultaneous connections per default
# save flag for Ctrl-C pressed
flag_status_ctrl_c_pressed = false
# try to gracefully shutdown on Ctrl-C
trap('INT') do
# print an empty line right after ^C
puts
# notify flag about Ctrl-C was pressed
flag_status_ctrl_c_pressed = true
# signal exit to app
exit(0)
end
# Output for debug
puts("Starting #{service_name}")
# setup exit code
at_exit do
# check to shutdown connection
if service
# Output for debug
puts('Ctrl-C interrupted, exit now...') if flag_status_ctrl_c_pressed
# info about shutdown
puts("Shutdown #{service_name}...")
# stop all threads and connections gracefully
service.stop
end
# Output for debug
puts "#{service_name} stopped!"
end
# Start the server
service.start
# Run on server forever
service.join
end
end