mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-30 18:47:51 +00:00
Merge branch 'develop' into feat/CW-5648
This commit is contained in:
@@ -178,7 +178,13 @@ class Messages::MessageBuilder
|
|||||||
email_attributes = ensure_indifferent_access(@message.content_attributes[:email] || {})
|
email_attributes = ensure_indifferent_access(@message.content_attributes[:email] || {})
|
||||||
normalized_content = normalize_email_body(@message.content)
|
normalized_content = normalize_email_body(@message.content)
|
||||||
|
|
||||||
email_attributes[:html_content] = build_html_content(normalized_content)
|
# Use custom HTML content if provided, otherwise generate from message content
|
||||||
|
email_attributes[:html_content] = if custom_email_content_provided?
|
||||||
|
build_custom_html_content
|
||||||
|
else
|
||||||
|
build_html_content(normalized_content)
|
||||||
|
end
|
||||||
|
|
||||||
email_attributes[:text_content] = build_text_content(normalized_content)
|
email_attributes[:text_content] = build_text_content(normalized_content)
|
||||||
email_attributes
|
email_attributes
|
||||||
end
|
end
|
||||||
@@ -213,4 +219,17 @@ class Messages::MessageBuilder
|
|||||||
|
|
||||||
ChatwootMarkdownRenderer.new(content).render_message.to_s
|
ChatwootMarkdownRenderer.new(content).render_message.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def custom_email_content_provided?
|
||||||
|
@params[:email_html_content].present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_custom_html_content
|
||||||
|
html_content = ensure_indifferent_access(@message.content_attributes.dig(:email, :html_content) || {})
|
||||||
|
|
||||||
|
html_content[:full] = @params[:email_html_content]
|
||||||
|
html_content[:reply] = @params[:email_html_content]
|
||||||
|
|
||||||
|
html_content
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<% if @message.content %>
|
<% if @message.content_attributes.dig('email', 'html_content', 'reply').present? %>
|
||||||
|
<%= @message.content_attributes.dig('email', 'html_content', 'reply').html_safe %>
|
||||||
|
<% elsif @message.content %>
|
||||||
<%= ChatwootMarkdownRenderer.new(@message.outgoing_content).render_message %>
|
<%= ChatwootMarkdownRenderer.new(@message.outgoing_content).render_message %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if @large_attachments.present? %>
|
<% if @large_attachments.present? %>
|
||||||
|
|||||||
@@ -179,6 +179,63 @@ describe Messages::MessageBuilder do
|
|||||||
expect(message.content_attributes[:cc_emails]).to eq ['test1@test.com', 'test2@test.com', 'test3@test.com']
|
expect(message.content_attributes[:cc_emails]).to eq ['test1@test.com', 'test2@test.com', 'test3@test.com']
|
||||||
expect(message.content_attributes[:bcc_emails]).to eq ['test1@test.com', 'test2@test.com', 'test3@test.com']
|
expect(message.content_attributes[:bcc_emails]).to eq ['test1@test.com', 'test2@test.com', 'test3@test.com']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when custom email content is provided' do
|
||||||
|
before do
|
||||||
|
account.enable_features('quoted_email_reply')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates message with custom HTML email content' do
|
||||||
|
params = ActionController::Parameters.new({
|
||||||
|
content: 'Regular message content',
|
||||||
|
email_html_content: '<p>Custom <strong>HTML</strong> content</p>'
|
||||||
|
})
|
||||||
|
|
||||||
|
message = described_class.new(user, conversation, params).perform
|
||||||
|
|
||||||
|
expect(message.content_attributes.dig('email', 'html_content', 'full')).to eq '<p>Custom <strong>HTML</strong> content</p>'
|
||||||
|
expect(message.content_attributes.dig('email', 'html_content', 'reply')).to eq '<p>Custom <strong>HTML</strong> content</p>'
|
||||||
|
expect(message.content_attributes.dig('email', 'text_content', 'full')).to eq 'Regular message content'
|
||||||
|
expect(message.content_attributes.dig('email', 'text_content', 'reply')).to eq 'Regular message content'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not process custom email content when quoted_email_reply feature is disabled' do
|
||||||
|
account.disable_features('quoted_email_reply')
|
||||||
|
params = ActionController::Parameters.new({
|
||||||
|
content: 'Regular message content',
|
||||||
|
email_html_content: '<p>Custom HTML content</p>'
|
||||||
|
})
|
||||||
|
|
||||||
|
message = described_class.new(user, conversation, params).perform
|
||||||
|
|
||||||
|
expect(message.content_attributes.dig('email', 'html_content')).to be_nil
|
||||||
|
expect(message.content_attributes.dig('email', 'text_content')).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not process custom email content for private messages' do
|
||||||
|
params = ActionController::Parameters.new({
|
||||||
|
content: 'Regular message content',
|
||||||
|
email_html_content: '<p>Custom HTML content</p>',
|
||||||
|
private: true
|
||||||
|
})
|
||||||
|
|
||||||
|
message = described_class.new(user, conversation, params).perform
|
||||||
|
|
||||||
|
expect(message.content_attributes.dig('email', 'html_content')).to be_nil
|
||||||
|
expect(message.content_attributes.dig('email', 'text_content')).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'falls back to default behavior when no custom email content is provided' do
|
||||||
|
params = ActionController::Parameters.new({
|
||||||
|
content: 'Regular **markdown** content'
|
||||||
|
})
|
||||||
|
|
||||||
|
message = described_class.new(user, conversation, params).perform
|
||||||
|
|
||||||
|
expect(message.content_attributes.dig('email', 'html_content', 'full')).to include('<strong>markdown</strong>')
|
||||||
|
expect(message.content_attributes.dig('email', 'text_content', 'full')).to eq 'Regular **markdown** content'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -335,6 +335,118 @@ RSpec.describe ConversationReplyMailer do
|
|||||||
expect(mail.body.encoded).not_to match(%r{<a [^>]*>avatar\.png</a>})
|
expect(mail.body.encoded).not_to match(%r{<a [^>]*>avatar\.png</a>})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with custom email content' do
|
||||||
|
it 'uses custom HTML content when available and creates multipart email' do
|
||||||
|
message_with_custom_content = create(:message,
|
||||||
|
conversation: conversation,
|
||||||
|
account: account,
|
||||||
|
message_type: 'outgoing',
|
||||||
|
content: 'Regular message content',
|
||||||
|
content_attributes: {
|
||||||
|
email: {
|
||||||
|
html_content: {
|
||||||
|
reply: '<p>Custom <strong>HTML</strong> content for email</p>'
|
||||||
|
},
|
||||||
|
text_content: {
|
||||||
|
reply: 'Custom text content for email'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mail = described_class.email_reply(message_with_custom_content).deliver_now
|
||||||
|
|
||||||
|
# Check HTML part contains custom HTML content
|
||||||
|
html_part = mail.html_part || mail
|
||||||
|
expect(html_part.body.encoded).to include('<p>Custom <strong>HTML</strong> content for email</p>')
|
||||||
|
expect(html_part.body.encoded).not_to include('Regular message content')
|
||||||
|
|
||||||
|
# Check text part contains custom text content
|
||||||
|
text_part = mail.text_part
|
||||||
|
if text_part
|
||||||
|
expect(text_part.body.encoded).to include('Custom text content for email')
|
||||||
|
expect(text_part.body.encoded).not_to include('Regular message content')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'falls back to markdown rendering when custom HTML content is not available' do
|
||||||
|
message_without_custom_content = create(:message,
|
||||||
|
conversation: conversation,
|
||||||
|
account: account,
|
||||||
|
message_type: 'outgoing',
|
||||||
|
content: 'Regular **markdown** content')
|
||||||
|
|
||||||
|
mail = described_class.email_reply(message_without_custom_content).deliver_now
|
||||||
|
|
||||||
|
html_part = mail.html_part || mail
|
||||||
|
expect(html_part.body.encoded).to include('<strong>markdown</strong>')
|
||||||
|
expect(html_part.body.encoded).to include('Regular')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'handles empty custom HTML content gracefully' do
|
||||||
|
message_with_empty_content = create(:message,
|
||||||
|
conversation: conversation,
|
||||||
|
account: account,
|
||||||
|
message_type: 'outgoing',
|
||||||
|
content: 'Regular **markdown** content',
|
||||||
|
content_attributes: {
|
||||||
|
email: {
|
||||||
|
html_content: {
|
||||||
|
reply: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mail = described_class.email_reply(message_with_empty_content).deliver_now
|
||||||
|
|
||||||
|
html_part = mail.html_part || mail
|
||||||
|
expect(html_part.body.encoded).to include('<strong>markdown</strong>')
|
||||||
|
expect(html_part.body.encoded).to include('Regular')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'handles nil custom HTML content gracefully' do
|
||||||
|
message_with_nil_content = create(:message,
|
||||||
|
conversation: conversation,
|
||||||
|
account: account,
|
||||||
|
message_type: 'outgoing',
|
||||||
|
content: 'Regular **markdown** content',
|
||||||
|
content_attributes: {
|
||||||
|
email: {
|
||||||
|
html_content: {
|
||||||
|
reply: nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mail = described_class.email_reply(message_with_nil_content).deliver_now
|
||||||
|
|
||||||
|
expect(mail.body.encoded).to include('<strong>markdown</strong>')
|
||||||
|
expect(mail.body.encoded).to include('Regular')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'uses custom text content in text part when only text is provided' do
|
||||||
|
message_with_text_only = create(:message,
|
||||||
|
conversation: conversation,
|
||||||
|
account: account,
|
||||||
|
message_type: 'outgoing',
|
||||||
|
content: 'Regular message content',
|
||||||
|
content_attributes: {
|
||||||
|
email: {
|
||||||
|
text_content: {
|
||||||
|
reply: 'Custom text content only'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mail = described_class.email_reply(message_with_text_only).deliver_now
|
||||||
|
|
||||||
|
text_part = mail.text_part
|
||||||
|
if text_part
|
||||||
|
expect(text_part.body.encoded).to include('Custom text content only')
|
||||||
|
expect(text_part.body.encoded).not_to include('Regular message content')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when smtp enabled for email channel' do
|
context 'when smtp enabled for email channel' do
|
||||||
|
|||||||
Reference in New Issue
Block a user