Fixes #3091 - Enhanced/reworked message header of forwarded mails.
This commit is contained in:
parent
41bba5dda3
commit
1f76712933
3 changed files with 165 additions and 10 deletions
|
@ -148,7 +148,7 @@ class EmailReply extends App.Controller
|
||||||
selected = App.Utils.text2html(selected)
|
selected = App.Utils.text2html(selected)
|
||||||
|
|
||||||
if 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>"
|
selected = "<div><br><br/></div><div><blockquote type=\'cite\'>#{quote_header}#{selected}<br></blockquote></div><div><br></div>"
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ class EmailReply extends App.Controller
|
||||||
body = App.Utils.textCleanup(article.body)
|
body = App.Utils.textCleanup(article.body)
|
||||||
body = App.Utils.text2html(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>"
|
body = "<br/><div>---Begin forwarded message:---<br/><br/></div><div><blockquote type=\"cite\">#{quote_header}#{body}</blockquote></div><div><br></div>"
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ class EmailReply extends App.Controller
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|
||||||
@fullQuoteHeader: (article) ->
|
@replyQuoteHeader: (article) ->
|
||||||
if !App.Config.get('ui_ticket_zoom_article_email_full_quote_header')
|
if !App.Config.get('ui_ticket_zoom_article_email_full_quote_header')
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
@ -348,4 +348,5 @@ class EmailReply extends App.Controller
|
||||||
|
|
||||||
App.i18n.translateInline('On %s, %s wrote:', date, name) + '<br><br>'
|
App.i18n.translateInline('On %s, %s wrote:', date, name) + '<br><br>'
|
||||||
|
|
||||||
|
|
||||||
App.Config.set('200-EmailReply', EmailReply, 'TicketZoomArticleAction')
|
App.Config.set('200-EmailReply', EmailReply, 'TicketZoomArticleAction')
|
||||||
|
|
|
@ -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]
|
|
@ -23,7 +23,7 @@ RSpec.describe 'Ticket > Update > Full Quote Header', type: :system, time_zone:
|
||||||
click_forward
|
click_forward
|
||||||
|
|
||||||
within(:richtext) do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -33,7 +33,21 @@ RSpec.describe 'Ticket > Update > Full Quote Header', type: :system, time_zone:
|
||||||
highlight_and_click_reply
|
highlight_and_click_reply
|
||||||
|
|
||||||
within(:richtext) do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -47,7 +61,7 @@ RSpec.describe 'Ticket > Update > Full Quote Header', type: :system, time_zone:
|
||||||
click_forward
|
click_forward
|
||||||
|
|
||||||
within(:richtext) do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,7 +71,7 @@ RSpec.describe 'Ticket > Update > Full Quote Header', type: :system, time_zone:
|
||||||
highlight_and_click_reply
|
highlight_and_click_reply
|
||||||
|
|
||||||
within(:richtext) do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -82,11 +96,65 @@ RSpec.describe 'Ticket > Update > Full Quote Header', type: :system, time_zone:
|
||||||
|
|
||||||
define :contain_full_quote do
|
define :contain_full_quote do
|
||||||
match do
|
match do
|
||||||
citation.has_text?(name) && citation.has_no_text?(email) && citation.has_text?(timestamp)
|
confirm_content && confirm_style
|
||||||
end
|
end
|
||||||
|
|
||||||
match_when_negated do
|
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
|
end
|
||||||
|
|
||||||
def citation
|
def citation
|
||||||
|
@ -101,11 +169,18 @@ RSpec.describe 'Ticket > Update > Full Quote Header', type: :system, time_zone:
|
||||||
expected.created_by.email
|
expected.created_by.email
|
||||||
end
|
end
|
||||||
|
|
||||||
def timestamp
|
def timestamp_reply
|
||||||
expected
|
expected
|
||||||
.created_at
|
.created_at
|
||||||
.in_time_zone('Europe/London')
|
.in_time_zone('Europe/London')
|
||||||
.strftime('%A, %B %1d, %Y, %1I:%M:%S %p')
|
.strftime('%A, %B %1d, %Y, %1I:%M:%S %p')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def timestamp_forward
|
||||||
|
expected
|
||||||
|
.created_at
|
||||||
|
.in_time_zone('Europe/London')
|
||||||
|
.strftime('%m/%d/%Y %H:%M')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue