Skip to content

Commit

Permalink
Update email config and add email notification push on sync run statu…
Browse files Browse the repository at this point in the history
…s change
  • Loading branch information
karthik-sivadas committed Apr 10, 2024
1 parent cb7a36f commit 1c063e2
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 18 deletions.
1 change: 1 addition & 0 deletions server/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,4 @@ end
# gem "image_processing", "~> 1.2" # For image variants if you decide to use Active Storage

# NOTE: Removed unused or commented-out gems for better readability.
gem "premailer-rails"
12 changes: 12 additions & 0 deletions server/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,8 @@ GEM
fiber-local
json
crass (1.0.6)
css_parser (1.17.1)
addressable
csv (3.3.0)
date (3.3.4)
declarative (0.0.20)
Expand Down Expand Up @@ -1805,6 +1807,7 @@ GEM
googleapis-common-protos-types (~> 1.0)
hana (1.3.7)
hashie (5.0.0)
htmlentities (4.3.4)
httpclient (2.8.3)
hubspot-api-client (18.0.0)
json (~> 2.1, >= 2.1.0)
Expand Down Expand Up @@ -1913,6 +1916,14 @@ GEM
pg (1.5.4)
pg_query (5.0.0)
google-protobuf (>= 3.22.3)
premailer (1.23.0)
addressable
css_parser (>= 1.12.0)
htmlentities (>= 4.0.0)
premailer-rails (1.12.0)
actionmailer (>= 3)
net-smtp
premailer (~> 1.7, >= 1.7.9)
protocol-hpack (1.4.3)
protocol-http (0.26.1)
protocol-http1 (0.18.0)
Expand Down Expand Up @@ -2124,6 +2135,7 @@ DEPENDENCIES
parallel
pg (~> 1.1)
pg_query
premailer-rails
puma (>= 5.0)
rack-cors
rails (~> 7.1.1)
Expand Down
13 changes: 11 additions & 2 deletions server/app/mailers/sync_run_mailer.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
# frozen_string_literal: true

class SyncRunMailer < ApplicationMailer
default from: ENV['SMTP_USERNAME']
default from: Rails.configuration.x.mail_from

def status_email
@sync_run = params[:sync_run]
@sync = @sync_run.sync
@sync_status = @sync_run.status
mail(to: params[:recipient], subject: "Sync run status update")
@source_connector_name = @sync_run.sync.source.name
@destination_connector_name = @sync_run.sync.destination.name
host = Rails.configuration.action_mailer.default_url_options[:host]
@sync_run_url = "#{host}/activate/syncs/#{@sync.id}/run/#{@sync_run.id}"
mail(to: params[:recipient], subject: "Sync run status update") do |format|
format.html { render layout: false }
end
end
end
5 changes: 5 additions & 0 deletions server/app/models/application_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@

class ApplicationRecord < ActiveRecord::Base
primary_abstract_class

def notification_email_enabled?
Rails.configuration.action_mailer.perform_deliveries &&
Rails.configuration.action_mailer.smtp_settings[:user_name].present?
end
end
21 changes: 21 additions & 0 deletions server/app/models/sync_run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class SyncRun < ApplicationRecord

after_initialize :set_defaults, if: :new_record?
after_discard :perform_post_discard_sync_run
after_commit :send_status_email, if: :status_changed_to_success_or_failed?

aasm column: :status, whiny_transitions: true do
state :pending, initial: true
Expand Down Expand Up @@ -89,4 +90,24 @@ def update_success
complete!
sync.complete!
end

def send_status_email
return unless notification_email_enabled?

recipients.each do |recipient|
SyncRunMailer.with(sync_run: self, recipient:).status_email.deliver_now
end
end

def recipients
if ENV["RECIPIENT_EMAIL"].present?
[ENV["RECIPIENT_EMAIL"]]
else
sync.workspace.workspace_users.admins.map { |workspace_user| workspace_user.user.email }
end
end

def status_changed_to_success_or_failed?
saved_change_to_status? && (status == "success" || status == "failed")
end
end
12 changes: 5 additions & 7 deletions server/app/views/sync_run_mailer/status_email.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<!-- app/views/sync_run_mailer/status_email.html.erb -->
<!DOCTYPE html>
<html>
<head>
<style>
<% color = @sync_status == "success" ? '#33C0A7' : '#F54C3D' %>
.email-body {
background-color: #333;
color: white;
Expand All @@ -17,25 +17,23 @@
display: inline-block;
padding: 10px 20px;
margin: 20px 0;
background-color: <%= color %>;
background-color: <%= @sync_status == "success" ? '#33C0A7' : '#F54C3D' %>;
color: white;
text-decoration: none;
font-weight: bold;
border-radius: 5px;
}
.status {
color: <%= color %>;
color: <%= @sync_status == "success" ? '#33C0A7' : '#F54C3D' %>;
font-weight: bold;
}
</style>
</head>
<body>
<div class="email-body">
<p>Salesforce to SFTP Test job was <%= @sync_status == "success" ? '<span class="status">successful</span>' : '<span class="status">failure</span>' %>.
Please click the Sync Run link below to view more details.
</p>
<p><%= @source_connector_name %> to <%= @destination_connector_name %> job was <span class="status"><%= @sync_status == "success" ? "successful" : "failure" %></span>. Please click the Sync Run link below to view more details.</p>
<div class="button-container">
<a href="<%= @url %>" class="button">Sync Run</a>
<a href="<%= @sync_run_url %>" class="button">Sync Run</a>
</div>
</div>
</body>
Expand Down
17 changes: 9 additions & 8 deletions server/config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,20 @@ class Application < Rails::Application
# Skip views, helpers and assets when generating a new resource.
config.api_only = true
config.middleware.insert_before Rails::Rack::Logger, MultiwovenServer::QuietLogger
# email setup

config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
host = ENV.fetch('SMTP_HOST', 'multiwoven.com') # Replace 'multiwoven.com' with SMTP_HOST value if needed
config.action_mailer.perform_deliveries = true
host = ENV.fetch('SMTP_HOST', 'multiwoven.com')
config.action_mailer.default_url_options = { host: host }
config.x.mail_from = %("Multiwoven" <noreply@multiwoven.com>)
ActionMailer::Base.smtp_settings = {
address: ENV['SMTP_ADDRESS'],
port: ENV.fetch('SMTP_PORT', '587'), # '587' is the default value if SMTP_PORT is not set
authentication: :plain,
config.x.mail_from = "#{ENV.fetch('BRAND_NAME', 'Multiwoven')} <#{ENV.fetch('SMTP_SENDER_EMAIL', 'noreply@multiwoven.com')}>"
config.action_mailer.smtp_settings = {
address: ENV['SMTP_ADDRESS'],
port: ENV.fetch('SMTP_PORT', '587'),
authentication: :login,
user_name: ENV['SMTP_USERNAME'],
password: ENV['SMTP_PASSWORD'],
enable_starttls_auto: true
}
config.action_mailer.default_url_options = { host: ENV['UI_HOST'] || 'localhost:8000' }
end
end
4 changes: 4 additions & 0 deletions server/config/initializers/premailer_rails.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Premailer::Rails.config.merge!(
adapter: :nokogiri,
generate_text_part: false
)
39 changes: 38 additions & 1 deletion server/spec/mailers/sync_run_mailer_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe SyncRunMailer, type: :mailer do
pending "add some examples to (or delete) #{__FILE__}"
describe "#status_email" do
let(:source) do
create(:connector, connector_type: "source", connector_name: "Snowflake")
end
let(:destination) { create(:connector, connector_type: "destination") }
let!(:catalog) { create(:catalog, connector: destination) }
let(:sync) { create(:sync, source:, destination:) }
let(:sync_run) do
create(:sync_run, sync:, workspace: sync.workspace, source:, destination:, model: sync.model, status: "success")
end
let(:sync_run_pending) do
create(:sync_run, sync:, workspace: sync.workspace, source:, destination:, model: sync.model, status: "pending")
end
let(:recipient) { "test@example.com" }
let(:mail) { SyncRunMailer.with(sync_run:, recipient:).status_email }

it "renders the headers" do
expect(mail.subject).to eq("Sync run status update")
expect(mail.to).to eq([recipient])
expect(mail.from).to eq(["noreply@multiwoven.com"])
end

it "renders the body" do
expect(mail.body.encoded).to match(sync_run.status)
expect(mail.body.encoded).to match(sync.source.name)
expect(mail.body.encoded).to match(sync.destination.name)
host = Rails.configuration.action_mailer.default_url_options[:host]
url = "#{host}/activate/syncs/#{sync.id}/run/#{sync_run.id}"
expect(mail.body.encoded).to match(url)
end

it "assigns @sync_run_url" do
expect(mail.body.encoded).to match(sync_run.sync.id.to_s)
expect(mail.body.encoded).to match(sync_run.id.to_s)
end
end
end
28 changes: 28 additions & 0 deletions server/spec/models/sync_run_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,32 @@
expect(sync_record.sync_run_id).to be_nil
end
end

describe "#send_status_email" do
let(:source) do
create(:connector, connector_type: "source", connector_name: "Snowflake")
end
let(:destination) { create(:connector, connector_type: "destination") }
let!(:catalog) { create(:catalog, connector: destination) }
let(:sync) { create(:sync, sync_interval: 3, sync_interval_unit: "hours", source:, destination:) }
let(:sync_run) { create(:sync_run, sync:, status: :pending) }

it "calls send_status_email after commit when status changes to success" do
allow(sync_run).to receive(:send_status_email)
sync_run.update!(status: :success)
expect(sync_run).to have_received(:send_status_email)
end

it "calls send_status_email after commit when status changes to failed" do
allow(sync_run).to receive(:send_status_email)
sync_run.update!(status: :failed)
expect(sync_run).to have_received(:send_status_email)
end

it "does not call send_status_email if status does not change to success or failed" do
allow(sync_run).to receive(:send_status_email)
sync_run.update!(status: :in_progress)
expect(sync_run).not_to have_received(:send_status_email)
end
end
end

0 comments on commit 1c063e2

Please sign in to comment.