Skip to content

Commit

Permalink
added mailtrap provider integration
Browse files Browse the repository at this point in the history
  • Loading branch information
kortirso committed Sep 25, 2024
1 parent d7647b7 commit 37367e3
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 27 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased
### Added
- mailtrap provider integration

## [0.8.4] - 2024-09-13
### Modified
- enum definition for Emailbutler::Message
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ require 'emailbutler/adapters/active_record'

Emailbutler.configure do |config|
config.adapter = Emailbutler::Adapters::ActiveRecord.new # required
config.providers = %w[sendgrid smtp2go resend mailjet] # optional
config.providers = %w[sendgrid smtp2go resend mailjet mailtrap] # optional
config.ui_username = 'username' # optional
config.ui_password = 'password' # optional
config.ui_secured_environments = ['production'] # optional
Expand Down
6 changes: 6 additions & 0 deletions app/controllers/emailbutler/webhooks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def receiver_mapper
when 'smtp2go' then Emailbutler::Container.resolve(:smtp2go_mapper)
when 'resend' then Emailbutler::Container.resolve(:resend_mapper)
when 'mailjet' then Emailbutler::Container.resolve(:mailjet_mapper)
when 'mailtrap' then Emailbutler::Container.resolve(:mailtrap_mapper)
end
end

Expand All @@ -35,6 +36,7 @@ def mapper_params
when 'smtp2go' then smtp2go_params
when 'resend' then resend_params
when 'mailjet' then mailjet_params
when 'mailtrap' then mailtrap_params
end
end

Expand All @@ -53,5 +55,9 @@ def resend_params
def mailjet_params
params.permit('event', 'time', 'Message_GUID')
end

def mailtrap_params
params.permit('events' => %w[event timestamp message_id])
end
end
end
2 changes: 1 addition & 1 deletion lib/emailbutler/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Configuration
AVAILABLE_ADAPTERS = %w[
Emailbutler::Adapters::ActiveRecord
].freeze
AVAILABLE_PROVIDERS = %w[sendgrid smtp2go resend mailjet].freeze
AVAILABLE_PROVIDERS = %w[sendgrid smtp2go resend mailjet mailtrap].freeze

attr_accessor :adapter, :providers, :ui_username, :ui_password, :ui_secured_environments

Expand Down
2 changes: 2 additions & 0 deletions lib/emailbutler/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require 'emailbutler/webhooks/mappers/smtp2go'
require 'emailbutler/webhooks/mappers/resend'
require 'emailbutler/webhooks/mappers/mailjet'
require 'emailbutler/webhooks/mappers/mailtrap'
require 'emailbutler/webhooks/receiver'

module Emailbutler
Expand All @@ -24,6 +25,7 @@ def register(key)
register(:smtp2go_mapper) { Emailbutler::Webhooks::Mappers::Smtp2Go.new }
register(:resend_mapper) { Emailbutler::Webhooks::Mappers::Resend.new }
register(:mailjet_mapper) { Emailbutler::Webhooks::Mappers::Mailjet.new }
register(:mailtrap_mapper) { Emailbutler::Webhooks::Mappers::Mailtrap.new }

# webhook receiver
register(:webhooks_receiver) { Emailbutler::Webhooks::Receiver.new }
Expand Down
10 changes: 3 additions & 7 deletions lib/emailbutler/webhooks/mappers/mailjet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,15 @@ class Mailjet
DELIVERABILITY_MAPPER = {
'sent' => 'processed',
'open' => 'delivered',
'click' => 'delivered',
'unsub' => 'failed',
'blocked' => 'failed',
'bounce' => 'failed',
'spam' => 'failed'
'click' => 'delivered'
}.freeze

def call(payload:)
payload.stringify_keys!
# message-id contains data like <uuid>
message_uuid = payload['Message_GUID']
status = DELIVERABILITY_MAPPER[payload['event']]
return [] if message_uuid.nil? || status.nil?
status = DELIVERABILITY_MAPPER[payload['event']] || Emailbutler::Message::FAILED
return [] if message_uuid.nil?

[
{
Expand Down
30 changes: 30 additions & 0 deletions lib/emailbutler/webhooks/mappers/mailtrap.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Emailbutler
module Webhooks
module Mappers
class Mailtrap
DELIVERABILITY_MAPPER = {
'delivery' => 'delivered',
'open' => 'delivered',
'click' => 'delivered'
}.freeze

def call(payload:)
payload['events'].filter_map { |message|
message.stringify_keys!
message_uuid = message['message_id']
status = DELIVERABILITY_MAPPER[message['event']] || Emailbutler::Message::FAILED
next if message_uuid.nil?

{
message_uuid: message_uuid,
status: status,
timestamp: message['timestamp'] ? Time.at(message['timestamp']).utc.to_datetime : nil
}
}
end
end
end
end
end
9 changes: 3 additions & 6 deletions lib/emailbutler/webhooks/mappers/resend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ class Resend
'email.sent' => 'processed',
'email.delivered' => 'delivered',
'email.opened' => 'delivered',
'email.clicked' => 'delivered',
'email.delivered_delayed' => 'failed',
'email.bounced' => 'failed',
'email.complained' => 'failed'
'email.clicked' => 'delivered'
}.freeze

def call(payload:)
payload.stringify_keys!
message_uuid = payload.dig('data', 'email_id')
status = DELIVERABILITY_MAPPER[payload['type']]
return [] if message_uuid.nil? || status.nil?
status = DELIVERABILITY_MAPPER[payload['type']] || Emailbutler::Message::FAILED
return [] if message_uuid.nil?

[
{
Expand Down
8 changes: 2 additions & 6 deletions lib/emailbutler/webhooks/mappers/sendgrid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@ class Sendgrid
'processed' => 'processed',
'delivered' => 'delivered',
'open' => 'delivered',
'click' => 'delivered',
'deferred' => 'failed',
'bounce' => 'failed',
'dropped' => 'failed',
'spamreport' => 'failed'
'click' => 'delivered'
}.freeze

def call(payload:)
payload['_json'].filter_map { |message|
message.stringify_keys!
message_uuid = message['smtp-id'] || message['sg_message_id']
status = DELIVERABILITY_MAPPER[message['event']]
status = DELIVERABILITY_MAPPER[message['event']] || Emailbutler::Message::FAILED
next if message_uuid.nil? || status.nil?

{
Expand Down
9 changes: 3 additions & 6 deletions lib/emailbutler/webhooks/mappers/smtp2go.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@ class Smtp2Go
'processed' => 'processed',
'delivered' => 'delivered',
'open' => 'delivered',
'click' => 'delivered',
'bounce' => 'failed',
'reject' => 'failed',
'spam' => 'failed'
'click' => 'delivered'
}.freeze

def call(payload:)
payload.stringify_keys!
# message-id contains data like <uuid>
message_uuid = payload['message-id'][1..-2]
status = DELIVERABILITY_MAPPER[payload['event']]
return [] if message_uuid.nil? || status.nil?
status = DELIVERABILITY_MAPPER[payload['event']] || Emailbutler::Message::FAILED
return [] if message_uuid.nil?

[
{
Expand Down
19 changes: 19 additions & 0 deletions spec/emailbutler/webhooks/receiver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,23 @@
expect(message.timestamp).to eq Time.at(timestamp).utc.to_datetime
end
end

context 'for mailtrap' do
let(:mapper) { Emailbutler::Container.resolve(:mailtrap_mapper) }
let(:payload) {
{
'events' => [
{ 'message_id' => message.uuid, 'event' => 'open', 'timestamp' => timestamp },
{ 'message_id' => 'unexisting', 'event' => 'click', 'timestamp' => timestamp }
]
}
}

it 'updates message', :aggregate_failures do
receiver_call

expect(message.reload.status).to eq 'delivered'
expect(message.timestamp).to eq Time.at(timestamp).utc.to_datetime
end
end
end

0 comments on commit 37367e3

Please sign in to comment.