chore: Fix emails being sent with the wrong translations (#2236)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
@@ -38,6 +38,8 @@ class Api::V1::Accounts::AgentsController < Api::V1::Accounts::BaseController
|
|||||||
@user = User.find_by(email: new_agent_params[:email])
|
@user = User.find_by(email: new_agent_params[:email])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: move this to a builder and combine the save account user method into a builder
|
||||||
|
# ensure the account user association is also created in a single transaction
|
||||||
def create_user
|
def create_user
|
||||||
return if @user
|
return if @user
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
|||||||
end
|
end
|
||||||
|
|
||||||
def transcript
|
def transcript
|
||||||
ConversationReplyMailer.conversation_transcript(@conversation, params[:email])&.deliver_later if params[:email].present?
|
render json: { error: 'email param missing' }, status: :unprocessable_entity and return if params[:email].blank?
|
||||||
|
|
||||||
|
ConversationReplyMailer.with(account: @conversation.account).conversation_transcript(@conversation, params[:email])&.deliver_later
|
||||||
head :ok
|
head :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController
|
|||||||
|
|
||||||
def transcript
|
def transcript
|
||||||
if permitted_params[:email].present? && conversation.present?
|
if permitted_params[:email].present? && conversation.present?
|
||||||
ConversationReplyMailer.conversation_transcript(
|
ConversationReplyMailer.with(account: conversation.account).conversation_transcript(
|
||||||
conversation,
|
conversation,
|
||||||
permitted_params[:email]
|
permitted_params[:email]
|
||||||
)&.deliver_later
|
)&.deliver_later
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class ApplicationMailer < ActionMailer::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def ensure_current_account(account)
|
def ensure_current_account(account)
|
||||||
|
Current.reset
|
||||||
Current.account = account if account.present?
|
Current.account = account if account.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ module Reauthorizable
|
|||||||
# could used to manually prompt reauthorization if auth scope changes
|
# could used to manually prompt reauthorization if auth scope changes
|
||||||
def prompt_reauthorization!
|
def prompt_reauthorization!
|
||||||
::Redis::Alfred.set(reauthorization_required_key, true)
|
::Redis::Alfred.set(reauthorization_required_key, true)
|
||||||
AdministratorNotifications::ChannelNotificationsMailer.slack_disconnect(account)&.deliver_later if (is_a? Integrations::Hook) && slack?
|
return unless (is_a? Integrations::Hook) && slack?
|
||||||
|
|
||||||
|
AdministratorNotifications::ChannelNotificationsMailer.with(account: account).slack_disconnect(account)&.deliver_later
|
||||||
end
|
end
|
||||||
|
|
||||||
# call this after you successfully Reauthorized the object in UI
|
# call this after you successfully Reauthorized the object in UI
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class User < ApplicationRecord
|
|||||||
scope :order_by_full_name, -> { order('lower(name) ASC') }
|
scope :order_by_full_name, -> { order('lower(name) ASC') }
|
||||||
|
|
||||||
def send_devise_notification(notification, *args)
|
def send_devise_notification(notification, *args)
|
||||||
devise_mailer.send(notification, self, *args).deliver_later
|
devise_mailer.with(account: Current.account).send(notification, self, *args).deliver_later
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_password_and_uid
|
def set_password_and_uid
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ class ::EmailTemplates::DbResolverService < ActionView::Resolver
|
|||||||
handler = ActionView::Template.registered_template_handler(:liquid)
|
handler = ActionView::Template.registered_template_handler(:liquid)
|
||||||
|
|
||||||
template_details = {
|
template_details = {
|
||||||
|
locals: [],
|
||||||
format: Mime['html'].to_sym,
|
format: Mime['html'].to_sym,
|
||||||
updated_at: @db_template.updated_at,
|
|
||||||
virtual_path: virtual_path(path, partial)
|
virtual_path: virtual_path(path, partial)
|
||||||
}
|
}
|
||||||
|
|
||||||
[ActionView::Template.new(@db_template.body, "DB Template - #{@db_template.id}", handler, template_details)]
|
[ActionView::Template.new(@db_template.body, "DB Template - #{@db_template.id}", handler, **template_details)]
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<p>Welcome, <%= @resource.name %>!</p>
|
<p>Welcome, <%= @resource.name %>!</p>
|
||||||
|
|
||||||
<% if @resource&.inviter.present? %>
|
<% account_user = @resource&.account_users&.first %>
|
||||||
<p><%= @resource.inviter.name %>, with <%= @resource.inviter.account.name %>, has invited you to try out Chatwoot! </p>
|
<% if account_user&.inviter.present? %>
|
||||||
|
<p><%= account_user.inviter.name %>, with <%= account_user.account.name %>, has invited you to try out Chatwoot! </p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<p>You can confirm your account email through the link below:</p>
|
<p>You can confirm your account email through the link below:</p>
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ class ConversationReplyEmailWorker
|
|||||||
|
|
||||||
# send the email
|
# send the email
|
||||||
if @conversation.messages.incoming&.last&.content_type == 'incoming_email' || email_inbox?
|
if @conversation.messages.incoming&.last&.content_type == 'incoming_email' || email_inbox?
|
||||||
ConversationReplyMailer.reply_without_summary(@conversation, queued_time).deliver_later
|
ConversationReplyMailer.with(account: @conversation.account).reply_without_summary(@conversation, queued_time).deliver_later
|
||||||
else
|
else
|
||||||
ConversationReplyMailer.reply_with_summary(@conversation, queued_time).deliver_later
|
ConversationReplyMailer.with(account: @conversation.account).reply_with_summary(@conversation, queued_time).deliver_later
|
||||||
end
|
end
|
||||||
|
|
||||||
# delete the redis set from the first new message on the conversation
|
# delete the redis set from the first new message on the conversation
|
||||||
|
|||||||
16
db/seeds.rb
16
db/seeds.rb
@@ -16,6 +16,10 @@ unless Rails.env.production?
|
|||||||
name: 'Acme Inc'
|
name: 'Acme Inc'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
secondary_account = Account.create!(
|
||||||
|
name: 'Acme Org'
|
||||||
|
)
|
||||||
|
|
||||||
user = User.new(name: 'John', email: 'john@acme.inc', password: 'Password1!')
|
user = User.new(name: 'John', email: 'john@acme.inc', password: 'Password1!')
|
||||||
user.skip_confirmation!
|
user.skip_confirmation!
|
||||||
user.save!
|
user.save!
|
||||||
@@ -26,6 +30,18 @@ unless Rails.env.production?
|
|||||||
role: :administrator
|
role: :administrator
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AccountUser.create!(
|
||||||
|
account_id: secondary_account.id,
|
||||||
|
user_id: user.id,
|
||||||
|
role: :administrator
|
||||||
|
)
|
||||||
|
|
||||||
|
# Enables creating additional accounts from dashboard
|
||||||
|
installation_config = InstallationConfig.find_by(name: 'CREATE_NEW_ACCOUNT_FROM_DASHBOARD')
|
||||||
|
installation_config.value = true
|
||||||
|
installation_config.save!
|
||||||
|
GlobalConfig.clear_cache
|
||||||
|
|
||||||
web_widget = Channel::WebWidget.create!(account: account, website_url: 'https://acme.inc')
|
web_widget = Channel::WebWidget.create!(account: account, website_url: 'https://acme.inc')
|
||||||
|
|
||||||
inbox = Inbox.create!(channel: web_widget, account: account, name: 'Acme Support')
|
inbox = Inbox.create!(channel: web_widget, account: account, name: 'Acme Support')
|
||||||
|
|||||||
@@ -374,14 +374,24 @@ RSpec.describe 'Conversations API', type: :request do
|
|||||||
let(:params) { { email: 'test@test.com' } }
|
let(:params) { { email: 'test@test.com' } }
|
||||||
|
|
||||||
it 'mutes conversation' do
|
it 'mutes conversation' do
|
||||||
allow(ConversationReplyMailer).to receive(:conversation_transcript)
|
mailer = double
|
||||||
|
allow(ConversationReplyMailer).to receive(:with).and_return(mailer)
|
||||||
|
allow(mailer).to receive(:conversation_transcript)
|
||||||
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/transcript",
|
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/transcript",
|
||||||
headers: agent.create_new_auth_token,
|
headers: agent.create_new_auth_token,
|
||||||
params: params,
|
params: params,
|
||||||
as: :json
|
as: :json
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(ConversationReplyMailer).to have_received(:conversation_transcript).with(conversation, 'test@test.com')
|
expect(mailer).to have_received(:conversation_transcript).with(conversation, 'test@test.com')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders error when parameter missing' do
|
||||||
|
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/transcript",
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
params: {},
|
||||||
|
as: :json
|
||||||
|
expect(response).to have_http_status(:unprocessable_entity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -104,7 +104,9 @@ RSpec.describe '/api/v1/widget/conversations/toggle_typing', type: :request do
|
|||||||
describe 'POST /api/v1/widget/conversations/transcript' do
|
describe 'POST /api/v1/widget/conversations/transcript' do
|
||||||
context 'with a conversation' do
|
context 'with a conversation' do
|
||||||
it 'sends transcript email' do
|
it 'sends transcript email' do
|
||||||
allow(ConversationReplyMailer).to receive(:conversation_transcript)
|
mailer = double
|
||||||
|
allow(ConversationReplyMailer).to receive(:with).and_return(mailer)
|
||||||
|
allow(mailer).to receive(:conversation_transcript)
|
||||||
|
|
||||||
post '/api/v1/widget/conversations/transcript',
|
post '/api/v1/widget/conversations/transcript',
|
||||||
headers: { 'X-Auth-Token' => token },
|
headers: { 'X-Auth-Token' => token },
|
||||||
@@ -112,7 +114,7 @@ RSpec.describe '/api/v1/widget/conversations/toggle_typing', type: :request do
|
|||||||
as: :json
|
as: :json
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(ConversationReplyMailer).to have_received(:conversation_transcript).with(conversation, 'test@test.com')
|
expect(mailer).to have_received(:conversation_transcript).with(conversation, 'test@test.com')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,43 +15,43 @@ describe ::EmailTemplates::DbResolverService do
|
|||||||
email_template = create(:email_template, name: 'test', body: 'test')
|
email_template = create(:email_template, name: 'test', body: 'test')
|
||||||
handler = ActionView::Template.registered_template_handler(:liquid)
|
handler = ActionView::Template.registered_template_handler(:liquid)
|
||||||
template_details = {
|
template_details = {
|
||||||
|
locals: [],
|
||||||
format: Mime['html'].to_sym,
|
format: Mime['html'].to_sym,
|
||||||
updated_at: email_template.updated_at,
|
|
||||||
virtual_path: 'test'
|
virtual_path: 'test'
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
resolver.find_templates('test', '', false, []).first.to_json
|
resolver.find_templates('test', '', false, []).first.inspect
|
||||||
).to eq(
|
).to eq(
|
||||||
ActionView::Template.new(
|
ActionView::Template.new(
|
||||||
email_template.body,
|
email_template.body,
|
||||||
"DB Template - #{email_template.id}", handler, template_details
|
"DB Template - #{email_template.id}", handler, **template_details
|
||||||
).to_json
|
).inspect
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when account template exists in db' do
|
context 'when account template exists in db' do
|
||||||
let(:account) { create(:account) }
|
let(:account) { create(:account) }
|
||||||
let(:installation_template) { create(:email_template, name: 'test', body: 'test') }
|
let!(:installation_template) { create(:email_template, name: 'test', body: 'test') }
|
||||||
let(:account_template) { create(:email_template, name: 'test', body: 'test2', account: account) }
|
let!(:account_template) { create(:email_template, name: 'test', body: 'test2', account: account) }
|
||||||
|
|
||||||
it 'return account template for current account' do
|
it 'return account template for current account' do
|
||||||
Current.account = account
|
Current.account = account
|
||||||
handler = ActionView::Template.registered_template_handler(:liquid)
|
handler = ActionView::Template.registered_template_handler(:liquid)
|
||||||
template_details = {
|
template_details = {
|
||||||
|
locals: [],
|
||||||
format: Mime['html'].to_sym,
|
format: Mime['html'].to_sym,
|
||||||
updated_at: account_template.updated_at,
|
|
||||||
virtual_path: 'test'
|
virtual_path: 'test'
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
resolver.find_templates('test', '', false, []).first.to_json
|
resolver.find_templates('test', '', false, []).first.inspect
|
||||||
).to eq(
|
).to eq(
|
||||||
ActionView::Template.new(
|
ActionView::Template.new(
|
||||||
account_template.body,
|
account_template.body,
|
||||||
"DB Template - #{account_template.id}", handler, template_details
|
"DB Template - #{account_template.id}", handler, **template_details
|
||||||
).to_json
|
).inspect
|
||||||
)
|
)
|
||||||
Current.account = nil
|
Current.account = nil
|
||||||
end
|
end
|
||||||
@@ -60,18 +60,18 @@ describe ::EmailTemplates::DbResolverService do
|
|||||||
Current.account = create(:account)
|
Current.account = create(:account)
|
||||||
handler = ActionView::Template.registered_template_handler(:liquid)
|
handler = ActionView::Template.registered_template_handler(:liquid)
|
||||||
template_details = {
|
template_details = {
|
||||||
|
locals: [],
|
||||||
format: Mime['html'].to_sym,
|
format: Mime['html'].to_sym,
|
||||||
updated_at: installation_template.updated_at,
|
|
||||||
virtual_path: 'test'
|
virtual_path: 'test'
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
resolver.find_templates('test', '', false, []).first.to_json
|
resolver.find_templates('test', '', false, []).first.inspect
|
||||||
).to eq(
|
).to eq(
|
||||||
ActionView::Template.new(
|
ActionView::Template.new(
|
||||||
installation_template.body,
|
installation_template.body,
|
||||||
"DB Template - #{installation_template.id}", handler, template_details
|
"DB Template - #{installation_template.id}", handler, **template_details
|
||||||
).to_json
|
).inspect
|
||||||
)
|
)
|
||||||
Current.account = nil
|
Current.account = nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ require 'rails_helper'
|
|||||||
RSpec.describe 'Confirmation Instructions', type: :mailer do
|
RSpec.describe 'Confirmation Instructions', type: :mailer do
|
||||||
describe :notify do
|
describe :notify do
|
||||||
let(:account) { create(:account) }
|
let(:account) { create(:account) }
|
||||||
let(:confirmable_user) { build(:user, inviter: inviter_val, account: account) }
|
let(:confirmable_user) { create(:user, inviter: inviter_val, account: account) }
|
||||||
let(:inviter_val) { nil }
|
let(:inviter_val) { nil }
|
||||||
let(:mail) { Devise::Mailer.confirmation_instructions(confirmable_user, nil, {}) }
|
let(:mail) { Devise::Mailer.confirmation_instructions(confirmable_user, nil, {}) }
|
||||||
|
|
||||||
@@ -27,11 +27,9 @@ RSpec.describe 'Confirmation Instructions', type: :mailer do
|
|||||||
let(:inviter_val) { create(:user, :administrator, skip_confirmation: true, account: account) }
|
let(:inviter_val) { create(:user, :administrator, skip_confirmation: true, account: account) }
|
||||||
|
|
||||||
it 'refers to the inviter and their account' do
|
it 'refers to the inviter and their account' do
|
||||||
Current.account = account
|
|
||||||
expect(mail.body).to match(
|
expect(mail.body).to match(
|
||||||
"#{CGI.escapeHTML(inviter_val.name)}, with #{CGI.escapeHTML(inviter_val.account.name)}, has invited you to try out Chatwoot!"
|
"#{CGI.escapeHTML(inviter_val.name)}, with #{CGI.escapeHTML(account.name)}, has invited you to try out Chatwoot!"
|
||||||
)
|
)
|
||||||
Current.account = nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,15 +6,18 @@ RSpec.describe ConversationReplyEmailWorker, type: :worker do
|
|||||||
let(:scheduled_job) { described_class.perform_at(perform_at, 1, Time.zone.now) }
|
let(:scheduled_job) { described_class.perform_at(perform_at, 1, Time.zone.now) }
|
||||||
let(:conversation) { build(:conversation, display_id: nil) }
|
let(:conversation) { build(:conversation, display_id: nil) }
|
||||||
let(:message) { build(:message, conversation: conversation, content_type: 'incoming_email', inbox: conversation.inbox) }
|
let(:message) { build(:message, conversation: conversation, content_type: 'incoming_email', inbox: conversation.inbox) }
|
||||||
|
let(:mailer) { double }
|
||||||
|
let(:mailer_action) { double }
|
||||||
|
|
||||||
describe 'testing ConversationSummaryEmailWorker' do
|
describe 'testing ConversationSummaryEmailWorker' do
|
||||||
before do
|
before do
|
||||||
conversation.save!
|
conversation.save!
|
||||||
allow(Conversation).to receive(:find).and_return(conversation)
|
allow(Conversation).to receive(:find).and_return(conversation)
|
||||||
mailer = double
|
allow(ConversationReplyMailer).to receive(:with).and_return(mailer)
|
||||||
allow(ConversationReplyMailer).to receive(:reply_with_summary).and_return(mailer)
|
allow(ConversationReplyMailer).to receive(:with).and_return(mailer)
|
||||||
allow(ConversationReplyMailer).to receive(:reply_without_summary).and_return(mailer)
|
allow(mailer).to receive(:reply_with_summary).and_return(mailer_action)
|
||||||
allow(mailer).to receive(:deliver_later).and_return(true)
|
allow(mailer).to receive(:reply_without_summary).and_return(mailer_action)
|
||||||
|
allow(mailer_action).to receive(:deliver_later).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'worker jobs are enqueued in the mailers queue' do
|
it 'worker jobs are enqueued in the mailers queue' do
|
||||||
@@ -32,13 +35,13 @@ RSpec.describe ConversationReplyEmailWorker, type: :worker do
|
|||||||
context 'with actions performed by the worker' do
|
context 'with actions performed by the worker' do
|
||||||
it 'calls ConversationSummaryMailer#reply_with_summary when last incoming message was not email' do
|
it 'calls ConversationSummaryMailer#reply_with_summary when last incoming message was not email' do
|
||||||
described_class.new.perform(1, Time.zone.now)
|
described_class.new.perform(1, Time.zone.now)
|
||||||
expect(ConversationReplyMailer).to have_received(:reply_with_summary)
|
expect(mailer).to have_received(:reply_with_summary)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls ConversationSummaryMailer#reply_without_summary when last incoming message was from email' do
|
it 'calls ConversationSummaryMailer#reply_without_summary when last incoming message was from email' do
|
||||||
message.save
|
message.save
|
||||||
described_class.new.perform(1, Time.zone.now)
|
described_class.new.perform(1, Time.zone.now)
|
||||||
expect(ConversationReplyMailer).to have_received(:reply_without_summary)
|
expect(mailer).to have_received(:reply_without_summary)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user