Skip to content

Commit

Permalink
Fixes #3091 - Enhanced/reworked message header of forwarded mails.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantas authored and thorsteneckel committed Jul 15, 2020
1 parent 41bba5d commit 1f76712
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 10 deletions.
Expand Up @@ -148,7 +148,7 @@ class EmailReply extends App.Controller
selected = App.Utils.text2html(selected)

if selected
quote_header = @fullQuoteHeader(article)
quote_header = @replyQuoteHeader(article)

selected = "<div><br><br/></div><div><blockquote type=\'cite\'>#{quote_header}#{selected}<br></blockquote></div><div><br></div>"

Expand Down Expand Up @@ -196,7 +196,7 @@ class EmailReply extends App.Controller
body = App.Utils.textCleanup(article.body)
body = App.Utils.text2html(body)

quote_header = @fullQuoteHeader(article)
quote_header = App.FullQuoteHeader.fullQuoteHeaderForward(article)

body = "<br/><div>---Begin forwarded message:---<br/><br/></div><div><blockquote type=\"cite\">#{quote_header}#{body}</blockquote></div><div><br></div>"

Expand Down Expand Up @@ -339,7 +339,7 @@ class EmailReply extends App.Controller

true

@fullQuoteHeader: (article) ->
@replyQuoteHeader: (article) ->
if !App.Config.get('ui_ticket_zoom_article_email_full_quote_header')
return ''

Expand All @@ -348,4 +348,5 @@ class EmailReply extends App.Controller

App.i18n.translateInline('On %s, %s wrote:', date, name) + '<br><br>'


App.Config.set('200-EmailReply', EmailReply, 'TicketZoomArticleAction')
79 changes: 79 additions & 0 deletions app/assets/javascripts/app/lib/app_post/full_quote_header.coffee
@@ -0,0 +1,79 @@
class App.FullQuoteHeader
@fullQuoteHeaderForward: (article) ->
if !App.Config.get('ui_ticket_zoom_article_email_full_quote_header')
return ''

output = document.createElement('div')

data = {
Subject: article.subject
Date: App.i18n.translateTimestamp(article.created_at)
From: @fullQuoteHeaderForwardFrom(article)
To: @fullQuoteHeaderForwardTo(article)
CC: @fullQuoteHeaderForwardCC(article)
}

for key, value of data
if value
output.append App.i18n.translateContent(key), ': ', value, document.createElement('br')

output.append document.createElement('br')

output.outerHTML

@fullQuoteHeaderForwardFrom: (article) ->
user_id = article.origin_by_id || article.created_by_id

@fullQuoteHeaderEnsurePrivacy(user_id) || @fullQuoteHeaderEnsurePrivacy(article.from) || article.from

@fullQuoteHeaderForwardTo: (article) ->
if article.type.name is 'email' || article.type.name is 'web'
@fullQuoteHeaderEnsurePrivacy(article.to) || article.to
else if article.sender.name is 'Customer' && article.type.name is 'phone'
if email_address_id = App.Group.findByAttribute('name', article.to)?.email_address_id
App.EmailAddress.find(email_address_id).displayName()
else
article.to
else if article.sender.name is 'Agent' && article.type.name is 'phone'
ticket = App.Ticket.find article.ticket_id
@fullQuoteHeaderEnsurePrivacy(ticket.customer_id) || @fullQuoteHeaderEnsurePrivacy(article.to) || article.to
else
article.to

@fullQuoteHeaderForwardCC: (article) ->
return if !article.cc

article
.cc
.split(',')
.map (elem) ->
elem.trim()
.map (elem) =>
@fullQuoteHeaderEnsurePrivacy(elem) || elem
.join(', ')

@fullQuoteHeaderEnsurePrivacyParseInput: (input) ->
switch typeof input
when 'number'
App.User.find input
when 'string'
if email = @fullQuoteHeaderExtractEmail(input)
App.User.findByAttribute('email', email)
when 'object'
input

@fullQuoteHeaderEnsurePrivacy: (input) =>
user = @fullQuoteHeaderEnsurePrivacyParseInput(input)

return if !user

output = "#{user.displayName()}"

if !user.permission('ticket.agent') && user.email
output += " <#{user.email}>"

output

@fullQuoteHeaderExtractEmail: (input) ->
if match = input.match(/<?(\S+@\S[^>]+)(>?)/)
match[1]
89 changes: 82 additions & 7 deletions spec/system/ticket/update/full_quote_header_spec.rb
Expand Up @@ -23,7 +23,7 @@
click_forward

within(:richtext) do
expect(page).to contain_full_quote(ticket_article)
expect(page).to contain_full_quote(ticket_article).formatted_for(:forward)
end
end
end
Expand All @@ -33,7 +33,21 @@
highlight_and_click_reply

within(:richtext) do
expect(page).to contain_full_quote(ticket_article)
expect(page).to contain_full_quote(ticket_article).formatted_for(:reply)
end
end
end

context 'when customer is agent' do
let(:customer) { create(:agent) }

it 'includes OP without email when forwarding' do
within(:active_content) do
click_forward

within(:richtext) do
expect(page).to contain_full_quote(ticket_article).formatted_for(:forward).ensuring_privacy(true)
end
end
end
end
Expand All @@ -47,7 +61,7 @@
click_forward

within(:richtext) do
expect(page).not_to contain_full_quote(ticket_article)
expect(page).not_to contain_full_quote(ticket_article).formatted_for(:forward)
end
end
end
Expand All @@ -57,7 +71,7 @@
highlight_and_click_reply

within(:richtext) do
expect(page).not_to contain_full_quote(ticket_article)
expect(page).not_to contain_full_quote(ticket_article).formatted_for(:reply)
end
end
end
Expand All @@ -82,11 +96,65 @@ def highlight_and_click_reply

define :contain_full_quote do
match do
citation.has_text?(name) && citation.has_no_text?(email) && citation.has_text?(timestamp)
confirm_content && confirm_style
end

match_when_negated do
citation.has_no_text?(name) && citation.has_no_text?(email) && citation.has_no_text?(timestamp)
confirm_no_content
end

# sets expected quote format
# @param [Symbol] :forward or :reply, defaults to :reply if not set
chain :formatted_for do |style|
@style = style
end

def style
@style || :reply # rubocop:disable RSpec/InstanceVariable
end

# sets expected privacy level
# @param [Boolean] defaults to false if not set
chain :ensuring_privacy do |flag|
@ensuring_privacy = flag
end

def ensure_privacy?
@ensuring_privacy || false # rubocop:disable RSpec/InstanceVariable
end

def confirm_content
case style
when :reply
confirm_content_reply
when :forward
confirm_content_forward
end
end

def confirm_content_reply
citation.has_text?(name) && citation.has_no_text?(email) && citation.has_text?(timestamp_reply)
end

def confirm_content_forward
if ensure_privacy?
citation.has_text?(name) && citation.has_no_text?(email) && citation.has_text?(timestamp_forward)
else
citation.has_text?(name) && citation.has_text?(email) && citation.has_text?(timestamp_forward)
end
end

def confirm_no_content
citation.has_no_text?(name) && citation.has_no_text?(email) && citation.has_no_text?(timestamp_reply) && citation.has_no_text?(timestamp_forward)
end

def confirm_style
case style
when :forward
citation.text.match?(/Subject(.+)\nDate(.+)/)
when :reply
citation.text.match?(/^On(.+)wrote:$/)
end
end

def citation
Expand All @@ -101,11 +169,18 @@ def email
expected.created_by.email
end

def timestamp
def timestamp_reply
expected
.created_at
.in_time_zone('Europe/London')
.strftime('%A, %B %1d, %Y, %1I:%M:%S %p')
end

def timestamp_forward
expected
.created_at
.in_time_zone('Europe/London')
.strftime('%m/%d/%Y %H:%M')
end
end
end

0 comments on commit 1f76712

Please sign in to comment.