Fixed issue #1006 - Reply-To is not considered for automatic responses (triggers).

This commit is contained in:
Rolf Schmidt 2017-05-02 13:34:18 +02:00
parent 9f990f8352
commit da69501531
3 changed files with 453 additions and 34 deletions

View file

@ -304,18 +304,31 @@ class App.UiElement.ticket_perform_action
return if elementRow.find('.js-setNotification .js-body').get(0) return if elementRow.find('.js-setNotification .js-body').get(0)
options = options =
'article_last_sender': 'Article Last Sender'
'ticket_owner': 'Owner' 'ticket_owner': 'Owner'
'ticket_customer': 'Customer' 'ticket_customer': 'Customer'
'ticket_agents': 'All Agents' 'ticket_agents': 'All Agents'
name = "#{attribute.name}::notification.email" name = "#{attribute.name}::notification.email"
selection = $("<select class=\"form-control\" name=\"#{name}::recipient\" ></select>") # meta.recipient was a string in the past (single-select) so we convert it to array if needed
if !_.isArray(meta.recipient)
meta.recipient = [meta.recipient]
column_select_options = []
for key, value of options for key, value of options
selected = '' selected = undefined
if key is meta.recipient for recipient in meta.recipient
selected = 'selected="selected"' if key is recipient
selection.append("<option value=\"#{key}\" #{selected}>#{App.i18n.translateInline(value)}</option>") selected = true
column_select_options.push({ value: key, name: App.i18n.translateInline(value), selected: selected })
column_select = new App.ColumnSelect
attribute:
name: "#{name}::recipient"
options: column_select_options
selection = column_select.element()
notificationElement = $( App.view('generic/ticket_perform_action/notification_email')( notificationElement = $( App.view('generic/ticket_perform_action/notification_email')(
attribute: attribute attribute: attribute

View file

@ -745,53 +745,87 @@ perform changes on ticket
# send notification # send notification
if object_name == 'notification' if object_name == 'notification'
recipients = []
if value['recipient'] == 'ticket_customer' # value['recipient'] was a string in the past (single-select) so we convert it to array if needed
recipients.push User.lookup(id: customer_id) value_recipient = value['recipient']
elsif value['recipient'] == 'ticket_owner' if !value_recipient.is_a?(Array)
recipients.push User.lookup(id: owner_id) value_recipient = [value_recipient]
elsif value['recipient'] == 'ticket_agents'
recipients = recipients.concat(agent_of_group)
else
logger.error "Unknown email notification recipient '#{value['recipient']}'"
next
end end
recipient_string = ''
recipient_already = {} recipients_raw = []
recipients.each { |user| value_recipient.each { |recipient|
if recipient == 'article_last_sender'
if item && item[:article_id]
article = Ticket::Article.lookup(id: item[:article_id])
if article.reply_to.present?
recipients_raw.push(article.reply_to)
elsif article.from.present?
recipients_raw.push(article.from)
elsif article.origin_by_id
email = User.lookup(id: article.origin_by_id).email
recipients_raw.push(email)
elsif article.created_by_id
email = User.lookup(id: article.created_by_id).email
recipients_raw.push(email)
end
end
elsif recipient == 'ticket_customer'
email = User.lookup(id: customer_id).email
recipients_raw.push(email)
elsif recipient == 'ticket_owner'
email = User.lookup(id: owner_id).email
recipients_raw.push(email)
elsif recipient == 'ticket_agents'
agent_of_group.each { |user|
recipients_raw.push(user.email)
}
else
logger.error "Unknown email notification recipient '#{recipient}'"
next
end
}
recipients_checked = []
recipients_raw.each { |recipient_email|
# send notifications only to email adresses # send notifications only to email adresses
next if !user.email next if !recipient_email
next if user.email !~ /@/ next if recipient_email !~ /@/
# check if address is valid
begin
recipient_email = Mail::Address.new(recipient_email).address
rescue
next # because unable to parse
end
# do not sent notifications to this recipients # do not sent notifications to this recipients
send_no_auto_response_reg_exp = Setting.get('send_no_auto_response_reg_exp') send_no_auto_response_reg_exp = Setting.get('send_no_auto_response_reg_exp')
begin begin
next if user.email =~ /#{send_no_auto_response_reg_exp}/i next if recipient_email =~ /#{send_no_auto_response_reg_exp}/i
rescue => e rescue => e
logger.error "ERROR: Invalid regex '#{send_no_auto_response_reg_exp}' in setting send_no_auto_response_reg_exp" logger.error "ERROR: Invalid regex '#{send_no_auto_response_reg_exp}' in setting send_no_auto_response_reg_exp"
logger.error 'ERROR: ' + e.inspect logger.error 'ERROR: ' + e.inspect
next if user.email =~ /(mailer-daemon|postmaster|abuse|root)@.+?\..+?/i next if recipient_email =~ /(mailer-daemon|postmaster|abuse|root)@.+?\..+?/i
end end
# check if notification should be send because of customer emails # check if notification should be send because of customer emails
if item && item[:article_id] if item && item[:article_id]
article = Ticket::Article.lookup(id: item[:article_id]) article = Ticket::Article.lookup(id: item[:article_id])
if article && article.preferences['is-auto-response'] == true && article.from && article.from =~ /#{Regexp.quote(user.email)}/i if article && article.preferences['is-auto-response'] == true && article.from && article.from =~ /#{Regexp.quote(recipient_email)}/i
logger.info "Send not trigger based notification to #{user.email} because of auto response tagged incoming email" logger.info "Send not trigger based notification to #{recipient_email} because of auto response tagged incoming email"
next next
end end
end end
email = user.email.downcase.strip email = recipient_email.downcase.strip
next if recipient_already[email] next if recipients_checked.include?(email)
recipient_already[email] = true recipients_checked.push(email)
if recipient_string != ''
recipient_string += ', '
end
recipient_string += email
} }
next if recipient_string == ''
next if recipients_checked.blank?
recipient_string = recipients_checked.join(', ')
group = self.group group = self.group
next if !group next if !group
email_address = group.email_address email_address = group.email_address
@ -808,8 +842,6 @@ perform changes on ticket
objects = { objects = {
ticket: self, ticket: self,
article: articles.last, article: articles.last,
#recipient: user,
#changes: changes,
} }
# get subject # get subject

View file

@ -2471,4 +2471,378 @@ class TicketTriggerTest < ActiveSupport::TestCase
} }
end end
test 'article_last_sender trigger -> reply_to' do
trigger = Trigger.create_or_update(
name: 'auto reply',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
'ticket.state_id' => {
'operator' => 'is',
'value' => Ticket::State.lookup(name: 'new').id.to_s,
}
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'article_last_sender',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
ticket1 = Ticket.create(
title: "some <b>title</b>\n äöüß",
group: Group.lookup(name: 'Users'),
customer: User.lookup(email: 'nicole.braun@zammad.org'),
updated_by_id: 1,
created_by_id: 1,
)
Ticket::Article.create(
ticket_id: ticket1.id,
from: 'some_sender@example.com',
to: 'some_recipient+from@example.com',
reply_to: 'some_recipient+reply_to@example.com',
subject: 'some subject',
message_id: 'some@id',
body: "some message <b>note</b>\nnew line",
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
type: Ticket::Article::Type.find_by(name: 'note'),
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
ticket1.reload
assert_equal('new', ticket1.state.name, 'ticket1.state new')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
auto_response = ticket1.articles.last
assert_match('Zammad <zammad@localhost>', auto_response.from)
assert_match('some_recipient+reply_to@example.com', auto_response.to)
end
test 'article_last_sender trigger -> from' do
trigger = Trigger.create_or_update(
name: 'auto reply',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
'ticket.state_id' => {
'operator' => 'is',
'value' => Ticket::State.lookup(name: 'new').id.to_s,
}
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'article_last_sender',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
ticket1 = Ticket.create(
title: "some <b>title</b>\n äöüß",
group: Group.lookup(name: 'Users'),
customer: User.lookup(email: 'nicole.braun@zammad.org'),
updated_by_id: 1,
created_by_id: 1,
)
Ticket::Article.create(
ticket_id: ticket1.id,
from: 'some_sender+from@example.com',
to: 'some_recipient@example.com',
subject: 'some subject',
message_id: 'some@id',
body: "some message <b>note</b>\nnew line",
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Customer'),
type: Ticket::Article::Type.find_by(name: 'email'),
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
ticket1.reload
assert_equal('new', ticket1.state.name, 'ticket1.state new')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
auto_response = ticket1.articles.last
assert_match('Zammad <zammad@localhost>', auto_response.from)
assert_match('some_sender+from@example.com', auto_response.to)
end
test 'article_last_sender trigger -> origin_by_id' do
trigger = Trigger.create_or_update(
name: 'auto reply',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
'ticket.state_id' => {
'operator' => 'is',
'value' => Ticket::State.lookup(name: 'new').id.to_s,
}
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'article_last_sender',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
roles = Role.where(name: 'Customer')
customer1 = User.create_or_update(
login: 'customer+origin_by_id@example.com',
firstname: 'Trigger',
lastname: 'Customer1',
email: 'customer+origin_by_id@example.com',
password: 'customerpw',
active: true,
roles: roles,
updated_at: '2015-02-05 16:37:00',
updated_by_id: 1,
created_by_id: 1,
)
ticket1 = Ticket.create(
title: "some <b>title</b>\n äöüß",
group: Group.lookup(name: 'Users'),
customer: User.lookup(email: 'nicole.braun@zammad.org'),
updated_by_id: 1,
created_by_id: 1,
)
Ticket::Article.create(
ticket_id: ticket1.id,
to: 'some_recipient@example.com',
subject: 'some subject',
message_id: 'some@id',
body: "some message <b>note</b>\nnew line",
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Customer'),
type: Ticket::Article::Type.find_by(name: 'email'),
origin_by_id: customer1.id,
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
ticket1.reload
assert_equal('new', ticket1.state.name, 'ticket1.state new')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
auto_response = ticket1.articles.last
assert_match('Zammad <zammad@localhost>', auto_response.from)
assert_match('customer+origin_by_id@example.com', auto_response.to)
end
test 'article_last_sender trigger -> created_by_id' do
trigger = Trigger.create_or_update(
name: 'auto reply',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
'ticket.state_id' => {
'operator' => 'is',
'value' => Ticket::State.lookup(name: 'new').id.to_s,
}
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'article_last_sender',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
roles = Role.where(name: 'Customer')
customer1 = User.create_or_update(
login: 'customer+created_by_id@example.com',
firstname: 'Trigger',
lastname: 'Customer1',
email: 'customer+created_by_id@example.com',
password: 'customerpw',
active: true,
roles: roles,
updated_at: '2015-02-05 16:37:00',
updated_by_id: 1,
created_by_id: 1,
)
ticket1 = Ticket.create(
title: "some <b>title</b>\n äöüß",
group: Group.lookup(name: 'Users'),
customer: User.lookup(email: 'nicole.braun@zammad.org'),
updated_by_id: 1,
created_by_id: 1,
)
Ticket::Article.create(
ticket_id: ticket1.id,
to: 'some_recipient@example.com',
subject: 'some subject',
message_id: 'some@id',
body: "some message <b>note</b>\nnew line",
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Customer'),
type: Ticket::Article::Type.find_by(name: 'email'),
updated_by_id: customer1.id,
created_by_id: customer1.id,
)
Observer::Transaction.commit
ticket1.reload
assert_equal('new', ticket1.state.name, 'ticket1.state new')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
auto_response = ticket1.articles.last
assert_match('Zammad <zammad@localhost>', auto_response.from)
assert_match('customer+created_by_id@example.com', auto_response.to)
end
test 'multiple recipients owner_id, article_last_sender(reply_to) trigger' do
trigger = Trigger.create_or_update(
name: 'auto reply',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
'ticket.state_id' => {
'operator' => 'is',
'value' => Ticket::State.lookup(name: 'new').id.to_s,
}
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => %w(ticket_owner article_last_sender),
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
admin = User.create_or_update(
login: 'admin+owner_recipient@example.com',
firstname: 'Role',
lastname: "Admin#{name}",
email: 'admin+owner_recipient@example.com',
password: 'adminpw',
active: true,
roles: Role.where(name: %w(Admin Agent)),
updated_by_id: 1,
created_by_id: 1,
)
ticket1 = Ticket.create(
title: "some <b>title</b>\n äöüß",
group: Group.lookup(name: 'Users'),
customer: User.lookup(email: 'nicole.braun@zammad.org'),
owner_id: admin.id,
updated_by_id: 1,
created_by_id: 1,
)
Ticket::Article.create(
ticket_id: ticket1.id,
from: 'some_sender@example.com',
to: 'some_recipient+from@example.com',
reply_to: 'some_recipient+reply_to@example.com',
subject: 'some subject',
message_id: 'some@id',
body: "some message <b>note</b>\nnew line",
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
type: Ticket::Article::Type.find_by(name: 'note'),
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
ticket1.reload
assert_equal('new', ticket1.state.name, 'ticket1.state new')
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
auto_response = ticket1.articles.last
assert_match('Zammad <zammad@localhost>', auto_response.from)
assert_match('some_recipient+reply_to@example.com', auto_response.to)
assert_match('admin+owner_recipient@example.com', auto_response.to)
end
test 'article_last_sender trigger -> invalid reply_to' do
trigger = Trigger.create_or_update(
name: 'auto reply',
condition: {
'ticket.action' => {
'operator' => 'is',
'value' => 'create',
},
'ticket.state_id' => {
'operator' => 'is',
'value' => Ticket::State.lookup(name: 'new').id.to_s,
}
},
perform: {
'notification.email' => {
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
'recipient' => 'article_last_sender',
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
},
},
disable_notification: true,
active: true,
created_by_id: 1,
updated_by_id: 1,
)
ticket1 = Ticket.create(
title: "some <b>title</b>\n äöüß",
group: Group.lookup(name: 'Users'),
customer: User.lookup(email: 'nicole.braun@zammad.org'),
updated_by_id: 1,
created_by_id: 1,
)
Ticket::Article.create(
ticket_id: ticket1.id,
from: 'some_sender@example.com',
to: 'some_recipient+from@example.com',
reply_to: 'Blub blub blub some_recipient+reply_to@example',
subject: 'some subject',
message_id: 'some@id',
body: "some message <b>note</b>\nnew line",
internal: false,
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
type: Ticket::Article::Type.find_by(name: 'note'),
updated_by_id: 1,
created_by_id: 1,
)
Observer::Transaction.commit
ticket1.reload
assert_equal('new', ticket1.state.name, 'ticket1.state new')
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
end
end end