From d3be685b082193d06873d0905d87ef3932164566 Mon Sep 17 00:00:00 2001 From: Mike Sutton Date: Tue, 15 Nov 2022 01:03:15 +0100 Subject: [PATCH] basic proxy and consumer done --- .drone.yml | 6 +-- consumer/.ruby-gemset | 1 + consumer/.ruby-version | 1 + consumer/Gemfile | 17 ++---- consumer/Gemfile.lock | 32 +++++++++++ consumer/bettermail_consumer.rb | 88 ++++++++++++++++++++++++++++++ consumer/start.sh | 1 + proxy/.ruby-gemset | 1 + proxy/.ruby-version | 1 + proxy/Gemfile | 18 ++----- proxy/Gemfile.lock | 34 ++++++++++++ proxy/bettermail_proxy.rb | 94 +++++++++++++++++++++++++++------ proxy/ssl/cert.pem | 32 +++++++++++ proxy/ssl/key.pem | 52 ++++++++++++++++++ proxy/start.sh | 1 + 15 files changed, 334 insertions(+), 45 deletions(-) create mode 100644 consumer/.ruby-gemset create mode 100644 consumer/.ruby-version create mode 100644 consumer/Gemfile.lock create mode 100644 consumer/bettermail_consumer.rb create mode 100755 consumer/start.sh create mode 100644 proxy/.ruby-gemset create mode 100644 proxy/.ruby-version create mode 100644 proxy/Gemfile.lock create mode 100644 proxy/ssl/cert.pem create mode 100644 proxy/ssl/key.pem create mode 100755 proxy/start.sh diff --git a/.drone.yml b/.drone.yml index a628c44..bfcac05 100644 --- a/.drone.yml +++ b/.drone.yml @@ -50,7 +50,7 @@ steps: - export BM_COMPONENT=portal - export BUILD_TARGET=wizewerx/bettermail_${BM_COMPONENT}:${DRONE_COMMIT_BRANCH} - docker pull $BUILD_TARGET - - docker build --cache-from $BUILD_TARGET --build-arg GEM_CACHE=$BUILD_TARGET -f ./consumer/docker/Dockerfile -t $BUILD_TARGET . + - docker build --cache-from $BUILD_TARGET --build-arg GEM_CACHE=$BUILD_TARGET -f ./${BM_COMPONENT}/docker/Dockerfile -t $BUILD_TARGET . - docker push $BUILD_TARGET - name: proxy image: wizewerx/wizewerx-docker-compose @@ -65,7 +65,7 @@ steps: - export BM_COMPONENT=proxy - export BUILD_TARGET=wizewerx/bettermail_${BM_COMPONENT}:${DRONE_COMMIT_BRANCH} - docker pull $BUILD_TARGET - - docker build --cache-from $BUILD_TARGET --build-arg GEM_CACHE=$BUILD_TARGET -f ./consumer/docker/Dockerfile -t $BUILD_TARGET . + - docker build --cache-from $BUILD_TARGET --build-arg GEM_CACHE=$BUILD_TARGET -f ./${BM_COMPONENT}/docker/Dockerfile -t $BUILD_TARGET . - docker push $BUILD_TARGET - name: notifications image: wizewerx/wizewerx-docker-compose @@ -80,7 +80,7 @@ steps: - export BM_COMPONENT=notifications - export BUILD_TARGET=wizewerx/bettermail_${BM_COMPONENT}:${DRONE_COMMIT_BRANCH} - docker pull $BUILD_TARGET - - docker build --cache-from $BUILD_TARGET --build-arg GEM_CACHE=$BUILD_TARGET -f ./consumer/docker/Dockerfile -t $BUILD_TARGET . + - docker build --cache-from $BUILD_TARGET --build-arg GEM_CACHE=$BUILD_TARGET -f ./${BM_COMPONENT}/docker/Dockerfile -t $BUILD_TARGET . - docker push $BUILD_TARGET - name: notify_end image: plugins/slack diff --git a/consumer/.ruby-gemset b/consumer/.ruby-gemset new file mode 100644 index 0000000..74ed08e --- /dev/null +++ b/consumer/.ruby-gemset @@ -0,0 +1 @@ +bettermail_consumer diff --git a/consumer/.ruby-version b/consumer/.ruby-version new file mode 100644 index 0000000..2eb2fe9 --- /dev/null +++ b/consumer/.ruby-version @@ -0,0 +1 @@ +ruby-2.7.2 diff --git a/consumer/Gemfile b/consumer/Gemfile index db05c52..13abcf4 100644 --- a/consumer/Gemfile +++ b/consumer/Gemfile @@ -1,15 +1,6 @@ source 'https://rubygems.org' -ruby '2.6.5' -gem 'dotenv-rails' - -# Reduces boot times through caching; required in config/boot.rb -gem 'bootsnap', '>= 1.4.2', require: false - -group :development do - gem 'web-console', '>= 3.3.0' - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' - gem 'spring-watcher-listen', '~> 2.0.0' -end - +ruby '2.7.2' +gem 'dotenv' gem 'bunny' +gem 'mail' +gem 'pg' diff --git a/consumer/Gemfile.lock b/consumer/Gemfile.lock new file mode 100644 index 0000000..94db6aa --- /dev/null +++ b/consumer/Gemfile.lock @@ -0,0 +1,32 @@ +GEM + remote: https://rubygems.org/ + specs: + amq-protocol (2.3.2) + bunny (2.19.0) + amq-protocol (~> 2.3, >= 2.3.1) + sorted_set (~> 1, >= 1.0.2) + dotenv (2.8.1) + mail (2.7.1) + mini_mime (>= 0.1.1) + mini_mime (1.1.2) + pg (1.4.4) + rbtree (0.4.5) + set (1.0.3) + sorted_set (1.0.3) + rbtree + set (~> 1.0) + +PLATFORMS + ruby + +DEPENDENCIES + bunny + dotenv + mail + pg + +RUBY VERSION + ruby 2.7.2p137 + +BUNDLED WITH + 2.1.4 diff --git a/consumer/bettermail_consumer.rb b/consumer/bettermail_consumer.rb new file mode 100644 index 0000000..b5f8105 --- /dev/null +++ b/consumer/bettermail_consumer.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +require 'dotenv/load' +require 'pg' +require 'mail' +require 'bunny' + +# Server class +class BettermailConsumer + def initialize + @pg = PG::Connection.new(ENV['DATABASE_URL']) + end + + def start + begin + puts ' [*] Waiting for messages. To exit press CTRL+C' + mail_queue = bunny_channel.queue(ENV['RABBIT_MAIL_QUEUE']) + mail_queue.subscribe(block: true) do |_delivery_info, _properties, body| + mail = Mail.read_from_string(body) + puts mail + 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 stop + @bunny_conn&.close + @pg&.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 + +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 = BettermailConsumer.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 diff --git a/consumer/start.sh b/consumer/start.sh new file mode 100755 index 0000000..d475420 --- /dev/null +++ b/consumer/start.sh @@ -0,0 +1 @@ +ruby ./bettermail_consumer.rb diff --git a/proxy/.ruby-gemset b/proxy/.ruby-gemset new file mode 100644 index 0000000..2afb3ee --- /dev/null +++ b/proxy/.ruby-gemset @@ -0,0 +1 @@ +bettermail_proxy diff --git a/proxy/.ruby-version b/proxy/.ruby-version new file mode 100644 index 0000000..2eb2fe9 --- /dev/null +++ b/proxy/.ruby-version @@ -0,0 +1 @@ +ruby-2.7.2 diff --git a/proxy/Gemfile b/proxy/Gemfile index 22cc50e..d17444b 100644 --- a/proxy/Gemfile +++ b/proxy/Gemfile @@ -1,17 +1,7 @@ source 'https://rubygems.org' -ruby '2.6.5' -gem 'dotenv-rails' - -# Reduces boot times through caching; required in config/boot.rb -gem 'bootsnap', '>= 1.4.2', require: false - -group :development do - gem 'web-console', '>= 3.3.0' - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' - gem 'spring-watcher-listen', '~> 2.0.0' -end - +ruby '2.7.2' +gem 'dotenv' gem 'bunny' gem 'midi-smtp-server', '~> 3.0.1' -gem 'openssl', '~> 2.1.0' +gem 'mail' +gem 'openssl' diff --git a/proxy/Gemfile.lock b/proxy/Gemfile.lock new file mode 100644 index 0000000..af728cd --- /dev/null +++ b/proxy/Gemfile.lock @@ -0,0 +1,34 @@ +GEM + remote: https://rubygems.org/ + specs: + amq-protocol (2.3.2) + bunny (2.19.0) + amq-protocol (~> 2.3, >= 2.3.1) + sorted_set (~> 1, >= 1.0.2) + dotenv (2.8.1) + mail (2.7.1) + mini_mime (>= 0.1.1) + midi-smtp-server (3.0.3) + mini_mime (1.1.2) + openssl (3.0.1) + rbtree (0.4.5) + set (1.0.3) + sorted_set (1.0.3) + rbtree + set (~> 1.0) + +PLATFORMS + ruby + +DEPENDENCIES + bunny + dotenv + mail + midi-smtp-server (~> 3.0.1) + openssl + +RUBY VERSION + ruby 2.7.2p137 + +BUNDLED WITH + 2.1.4 diff --git a/proxy/bettermail_proxy.rb b/proxy/bettermail_proxy.rb index bb06526..21ec89e 100644 --- a/proxy/bettermail_proxy.rb +++ b/proxy/bettermail_proxy.rb @@ -1,24 +1,87 @@ # frozen_string_literal: true +require 'dotenv/load' require 'midi-smtp-server' +require 'mail' +require 'bunny' # Server class class BettermailProxy < 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 + + # get each message after DATA . def on_message_data_event(ctx) # Just decode message once to make sure, that this message ist readable - mail = Mail.read_from_string(ctx[:message]) - - # Publish to rabbit - @bunny_exchange.publish(mail.to_s, :headers => { 'x-smtp' => mail.header.to_s }, :routing_key => "new_email") + mail = Mail.read_from_string(ctx[:message][:data]) + logger.info('Message good. Sending to queue for processing') + bunny.publish(mail.to_s, :headers => { 'x-smtp' => mail.header.to_s }, :routing_key => ENV["RABBIT_MAIL_QUEUE"]) + logger.info('Done') end - end # 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 -server = MySmtpd.new +service = BettermailProxy.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 @@ -30,29 +93,30 @@ trap('INT') do # notify flag about Ctrl-C was pressed flag_status_ctrl_c_pressed = true # signal exit to app - exit 0 + exit(0) end # Output for debug -server.logger.info("Starting MySmtpd [#{MidiSmtpServer::VERSION::STRING}|#{MidiSmtpServer::VERSION::DATE}] (Basic usage) ...") +puts("Starting #{service_name}") # setup exit code at_exit do # check to shutdown connection - if server + if service # Output for debug - server.logger.info('Ctrl-C interrupted, exit now...') if flag_status_ctrl_c_pressed + puts('Ctrl-C interrupted, exit now...') if flag_status_ctrl_c_pressed # info about shutdown - server.logger.info('Shutdown MySmtpd...') + puts("Shutdown #{service_name}...") # stop all threads and connections gracefully - server.stop + service.stop end + # Output for debug - server.logger.info('MySmtpd down!') + puts "#{service_name} stopped!" end # Start the server -server.start +service.start # Run on server forever -server.join +service.join diff --git a/proxy/ssl/cert.pem b/proxy/ssl/cert.pem new file mode 100644 index 0000000..3a56cd6 --- /dev/null +++ b/proxy/ssl/cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFbTCCA1WgAwIBAgIUAf9HBsl8FOGp9rGyrroaRmBraFAwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMjExMTQxMTA5MjJaGA80NzYw +MTAxMTExMDkyMlowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBALaBN6wMI6kuMcebP7KTnj/uVCaw6fq5AnnRtHRl +2g26KQDhvyLjBi3Bbp/zRgm2uEprhkHJ+orAXDshjMZOU4mBlWxlX9mZCoVJfbU6 +4jvEtzNHXXfgWj6ec/l1jLkpfn51MBYXER3zcgTiCBs5JgvWtxw9/0uSwEeN/HY4 +U1yzYRlQQeEWZFovTA2wYJhN6xZy0mmLe5LBCdJSpXit2mrYAFZGvH+MnbEnXLXE +FgeJe+w9otjfqq37LxxUjfe2xEeTtliE/x6iuTew7/k04vTi1Dk0tHmeMhkA/tUW +snxRGkZHqnZKhmv3NNTFV6NSwRXrm9N/gefSA1/DOB3WpH2U0YCXsiTpR+31ounG +/60ox9XrVIzDkHNR7qc+91KpD6xyttt2qdeC4bnwQWK/KqYcpL54Io6P06JWstFQ +nR5bvvK7NVWDWwM5nqw28aCEZ63X2mq/GO7wQqhKIB8+oGFqm/Bu8ciLzK/89Cxw +KW4hy0sXJ+PU5gPECS4q57NgVU39Auyue3vziNsQ3NusoAjqqQ7mMmBWrzGEyoc7 +tirNnNRbdz+9M+1CHu8622BiU55KAgL27/H1WiWqaMLLRn0NhYGZipH+THdVxhJl +H1rqDa8o0j0DL2kQkjUvMQG5q6tMavbbmEB4vyPwxTBNVcKnkg9++r0JQiIshDXV +tgElAgMBAAGjUzBRMB0GA1UdDgQWBBSL6Xv5EJCvf/MJO7U/HABHivI9dTAfBgNV +HSMEGDAWgBSL6Xv5EJCvf/MJO7U/HABHivI9dTAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQAArEGEwU/uvTSg9ekkufsOYr7yKnlmXdoHN9BTN/6V +7sXhWdFQguW41/u/Xzm24SvaSSr0DCVs2h75tgnms/Bf9x2OK9WGTNCLmI9YDWyD +By050oQ+0BDWdDXxVAX1tz5dm4H0fTU+jzr58CoQpR1wIkmSNBdWwbWvMQeqAL8r +b6pLVElM5LdCX0OZYDt1E3Hpja6UYBro0ziGnfVLO4/UWVYBgHWU+IpiM1bZI1Iq +SYIqJwy1bC3duU0z76YvvUkNA0UiGMQbbjqorrR8ltzArV4qZaV3JcLZa1LpvTGc +7qLGNutkJvmksahvgklreb6oEc1FbFt5wew8FUgLeAZXgy8LwTyKXLq1YSLJc/QE +OaJfb7Tork2sd+/9kGwyPQ36/YaRRGIs6OaNbFTjCJs73Zyycu+RFaxewjo8offP +sozyilQAU6jl4XGO7fQOVJsUgb33pOrgI7f8EMbUAYZHGUwrbiCxNoiJRxM5e4J+ +7AsPU4C21mIysndXT6v14HZBTMLbjfPASOr+FdZw7L+rtHk2iLvAfFeeMDPd4Zrb +1/xtQ6iAd64RkmwlrFvbLPWLuFK7QVRHIpAGa/aFRPq7xECuHI8cGupU+lZtrORo +YBRsYyizGXwiuMstzx8ZV+CpeW4hBfCvHiYqshceAeQd+89ljoc/iJNf0PdUgN+Q +og== +-----END CERTIFICATE----- diff --git a/proxy/ssl/key.pem b/proxy/ssl/key.pem new file mode 100644 index 0000000..0dec64b --- /dev/null +++ b/proxy/ssl/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +5ZADVjSHf21VhXCmSSGtL59GcaMYVA== +-----END PRIVATE KEY----- diff --git a/proxy/start.sh b/proxy/start.sh new file mode 100755 index 0000000..a3cd011 --- /dev/null +++ b/proxy/start.sh @@ -0,0 +1 @@ +ruby ./bettermail_proxy.rb