Moved to new postmaster filter ui with contains and contains not feature.

This commit is contained in:
Martin Edenhofer 2015-09-20 02:26:33 +02:00
parent 5d871673be
commit 89acbb933b
6 changed files with 668 additions and 298 deletions

View file

@ -1,176 +1,242 @@
class App.UiElement.postmaster_match class App.UiElement.postmaster_match
@render: (attribute, params, form_controller) -> @defaults: ->
addItem = (key, displayName, el, defaultValue = '') => groups =
add = { name: key, display: displayName, tag: 'input', null: false, default: defaultValue } general:
itemInput = $( form_controller.formGenItem( add ).append('<svg class="icon icon-diagonal-cross remove"><use xlink:href="#icon-diagonal-cross"></use></svg>' ) ) name: 'Basic Settings'
options: [
{
value: 'from'
name: 'From'
},
{
value: 'to'
name: 'To'
},
{
value: 'cc'
name: 'Cc'
},
{
value: 'x-any-recipient'
name: 'Any Recipient'
},
{
value: 'subject'
name: 'Subject'
},
{
value: 'body'
name: 'Body'
},
]
expert:
name: 'Expert Settings'
options: [
{
value: 'x-spam-flag'
name: 'X-Spam-Flag'
},
{
value: 'x-spam-level'
name: 'X-Spam-Level'
},
{
value: 'x-spam-score'
name: 'X-Spam-Score'
},
{
value: 'x-spam-status'
name: 'X-Spam-Status'
},
{
value: 'importance'
name: 'Importance'
},
{
value: 'x-priority'
name: 'X-Priority'
},
# remove on click {
itemInput.find('.remove').bind('click', (e) -> value: 'organization'
e.preventDefault() name: 'Organization'
key = $(e.target).closest('.form-group').find('select, input').attr('name') },
return if !key
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').show()
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').prop('disabled', false)
$(e.target).closest('.form-group').remove()
)
# add new item {
control = el.closest('.postmaster_match') value: 'x-original-to'
control.find('.list').append(itemInput) name: 'X-Original-To'
control.find('.addSelection select').val('') },
control.find('.addSelection select option[value="' + key + '"]').prop('disabled', true) {
control.find('.addSelection select option[value="' + key + '"]').hide() value: 'delivered-to'
name: 'Delivered-To'
},
{
value: 'envelope-to'
name: 'Envelope-To'
},
{
value: 'return-path'
name: 'Return-Path'
},
{
value: 'mailing-list'
name: 'Mailing-List'
},
{
value: 'list-id'
name: 'List-Id'
},
{
value: 'list-archive'
name: 'List-Archive'
},
{
value: 'mailing-list'
name: 'Mailing-List'
},
{
value: 'auto-submitted'
name: 'Auto-Submitted'
},
{
value: 'x-loop'
name: 'X-Loop'
},
]
groups
@render: (attribute, params = {}) ->
groups = @defaults()
selector = @buildAttributeSelector(groups, attribute)
# scaffold of match elements # scaffold of match elements
item = $(' item = $( App.view('generic/postmaster_match')( attribute: attribute ) )
<div class="postmaster_match"> item.find('.js-attributeSelector').prepend(selector)
<hr>
<div class="list"></div>
<hr>
<div>
<div class="addSelection"></div>
<svg class="icon icon-plus add"><use xlink:href="#icon-plus"></use></svg>
</div>
</div>')
# select shown attributes # add filter
loopData = [ item.find('.js-add').bind('click', (e) =>
{ element = $(e.target).closest('.js-filterElement')
value: 'from' elementClone = element.clone(true)
name: 'From' element.after(elementClone)
}, elementClone.find('.js-attributeSelector select').trigger('change')
{
value: 'to'
name: 'To'
},
{
value: 'cc'
name: 'Cc'
},
{
value: 'subject'
name: 'Subject'
},
{
value: 'body'
name: 'Body'
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-any-recipient'
name: 'Any Recipient'
},
{
value: ''
name: '-'
disable: true
},
{
value: ''
name: '- ' + App.i18n.translateInline('expert settings') + ' -'
disable: true
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-spam-flag'
name: 'X-Spam-Flag'
},
{
value: 'x-spam-level'
name: 'X-Spam-Level'
},
{
value: 'x-spam-score'
name: 'X-Spam-Score'
},
{
value: 'x-spam-status'
name: 'X-Spam-Status'
},
{
value: 'importance'
name: 'Importance'
},
{
value: 'x-priority'
name: 'X-Priority'
},
{
value: 'organization'
name: 'Organization'
},
{
value: 'x-original-to'
name: 'X-Original-To'
},
{
value: 'delivered-to'
name: 'Delivered-To'
},
{
value: 'envelope-to'
name: 'Envelope-To'
},
{
value: 'return-path'
name: 'Return-Path'
},
{
value: 'mailing-list'
name: 'Mailing-List'
},
{
value: 'list-id'
name: 'List-Id'
},
{
value: 'list-archive'
name: 'List-Archive'
},
{
value: 'mailing-list'
name: 'Mailing-List'
},
{
value: 'auto-submitted'
name: 'Auto-Submitted'
},
{
value: 'x-loop'
name: 'X-Loop'
},
]
for listItem in loopData
listItem.value = "#{ attribute.name }::#{listItem.value}"
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true, required: false }
item.find('.addSelection').append( form_controller.formGenItem( add ) )
# bind add click
item.find('.add').bind('click', (e) ->
e.preventDefault()
name = $(@).closest('.controls').find('.addSelection').find('select').val()
displayName = $(@).closest('.controls').find('.addSelection').find('select option:selected').html()
return if !name
addItem( name, displayName, $(@) )
) )
# show default values # remove filter
loopDataValue = {} item.find('.js-remove').bind('click', (e) =>
if attribute.value $(e.target).closest('.js-filterElement').remove()
for key, value of attribute.value @rebuildAttributeSelectors(item)
displayName = key )
for listItem in loopData
if listItem.value is "#{ attribute.name }::#{key}" # change attribute selector
addItem( "#{ attribute.name }::#{key}", listItem.name, item.find('.add'), value ) item.find('.js-attributeSelector select').bind('change', (e) =>
key = $(e.target).find('option:selected').attr('value')
elementRow = $(e.target).closest('.js-filterElement')
@rebuildAttributeSelectors(item, elementRow, key, attribute)
@rebuildOperater(item, elementRow, key, groups, undefined, attribute)
@buildValue(item, elementRow, key, groups, undefined, undefined, attribute)
)
# change operator
item.find('.js-operator select').bind('change', (e) =>
key = $(e.target).find('.js-attributeSelector option:selected').attr('value')
operator = $(e.target).find('option:selected').attr('value')
elementRow = $(e.target).closest('.js-filterElement')
@buildValue(item, elementRow, key, groups, undefined, operator, attribute)
)
# build inital params
if !_.isEmpty(params[attribute.name])
selectorExists = false
for key, meta of params[attribute.name]
selectorExists = true
operator = meta.operator
value = meta.value
# get selector rows
elementFirst = item.find('.js-filterElement').first()
elementLast = item.find('.js-filterElement').last()
# clone, rebuild and append
elementClone = elementFirst.clone(true)
@rebuildAttributeSelectors(item, elementClone, key, attribute)
@rebuildOperater(item, elementClone, key, groups, operator, attribute)
@buildValue(item, elementClone, key, groups, value, operator, attribute)
elementLast.after(elementClone)
# remove first dummy row
if selectorExists
item.find('.js-filterElement').first().remove()
item item
@buildValue: (elementFull, elementRow, key, groups, value, operator, attribute) ->
# do nothing if item already exists
name = "#{attribute.name}::#{key}::value"
return if elementRow.find("[name=\"#{name}\"]").get(0)
config =
name: name
tag: 'input'
type: 'text'
value: value
item = App.UiElement[config.tag].render(config, {})
elementRow.find('.js-value').html(item)
@buildAttributeSelector: (groups, attribute) ->
selection = $('<select class="form-control"></select>')
for groupKey, groupMeta of groups
displayName = App.i18n.translateInline(groupMeta.name)
selection.closest('select').append("<optgroup label=\"#{displayName}\" class=\"js-#{groupKey}\"></optgroup>")
optgroup = selection.find("optgroup.js-#{groupKey}")
for entry in groupMeta.options
displayName = App.i18n.translateInline(entry.name)
optgroup.append("<option value=\"#{entry.value}\">#{displayName}</option>")
selection
@rebuildAttributeSelectors: (elementFull, elementRow, key, attribute) ->
# enable all
elementFull.find('.js-attributeSelector select option').removeAttr('disabled')
# disable all used attributes
elementFull.find('.js-attributeSelector select').each(->
keyLocal = $(@).val()
elementFull.find('.js-attributeSelector select option[value="' + keyLocal + '"]').attr('disabled', true)
)
# disable - if we only have one attribute
if elementFull.find('.js-attributeSelector select').length > 1
elementFull.find('.js-remove').removeClass('is-disabled')
else
elementFull.find('.js-remove').addClass('is-disabled')
# set attribute
if key
elementRow.find('.js-attributeSelector select').val(key)
@buildOperator: (elementFull, elementRow, key, groups, current_operator, attribute) ->
selection = $("<select class=\"form-control\" name=\"#{attribute.name}::#{key}::operator\"></select>")
for operator in ['contains', 'contains not']
operatorName = App.i18n.translateInline(operator)
selected = ''
if current_operator is operator
selected = 'selected="selected"'
selection.append("<option value=\"#{operator}\" #{selected}>#{operatorName}</option>")
selection
@rebuildOperater: (elementFull, elementRow, key, groups, current_operator, attribute) ->
return if !key
# do nothing if item already exists
name = "#{attribute.name}::#{key}::operator"
return if elementRow.find("[name=\"#{name}\"]").get(0)
# render new operator
operator = @buildOperator(elementFull, elementRow, key, groups, current_operator, attribute)
elementRow.find('.js-operator select').replaceWith(operator)

View file

@ -1,124 +1,171 @@
class App.UiElement.postmaster_set class App.UiElement.postmaster_set
@render: (attribute, params, form_controller) -> @defaults: ->
addItem = (key, displayName, el, defaultValue = '') => groups =
collection = undefined general:
for listItem in loopData name: 'Ticket'
if listItem.value is key options: [
collection = listItem {
if collection.relation value: 'x-zammad-ticket-priority_id'
add = { name: key, display: displayName, tag: 'select', multiple: false, null: false, nulloption: true, relation: collection.relation, translate: true, default: defaultValue } name: 'Priority'
else if collection.options relation: 'TicketPriority'
add = { name: key, display: displayName, tag: 'select', multiple: false, null: false, nulloption: true, options: collection.options, translate: true, default: defaultValue } },
else {
add = { name: key, display: displayName, tag: 'input', null: false, default: defaultValue } value: 'x-zammad-ticket-state_id'
itemInput = $( form_controller.formGenItem( add ).append('<svg class="icon icon-diagonal-cross remove"><use xlink:href="#icon-diagonal-cross"></use></svg>' ) ) name: 'State'
relation: 'TicketState'
},
{
value: 'x-zammad-ticket-customer'
name: 'Customer'
},
{
# remove on click value: 'x-zammad-ticket-group_id'
itemInput.find('.remove').bind('click', (e) -> name: 'Group'
e.preventDefault() relation: 'Group'
key = $(e.target).closest('.form-group').find('select, input').attr('name') },
return if !key {
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').show() value: 'x-zammad-ticket-owner'
$(e.target).closest('.controls').find('.addSelection select option[value="' + key + '"]').prop('disabled', false) name: 'Owner'
$(e.target).closest('.form-group').remove() relation: 'User',
) tag: 'user_autocompletion',
},
{
value: 'x-zammad-ignore'
name: 'Ignore Message'
options: { true: 'Yes', false: 'No'}
},
]
expert:
name: 'Article'
options: [
{
value: 'x-zammad-article-internal'
name: 'Internal'
options: { true: 'Yes', false: 'No'}
},
{
value: 'x-zammad-article-type_id'
name: 'Type'
relation: 'TicketArticleType'
},
{
value: 'x-zammad-article-sender_id'
name: 'Sender'
relation: 'TicketArticleSender'
},
]
# add new item groups
control = el.closest('.perform_set')
control.find('.list').append(itemInput)
control.find('.addSelection select').val('')
control.find('.addSelection select option[value="' + key + '"]').prop('disabled', true)
control.find('.addSelection select option[value="' + key + '"]').hide()
# scaffold of perform elements @render: (attribute, params = {}) ->
item = $('
<div class="perform_set">
<hr>
<div class="list"></div>
<hr>
<div>
<div class="addSelection"></div>
<svg class="icon icon-plus add"><use xlink:href="#icon-plus"></use></svg>
</div>
</div>')
groups = @defaults()
# select shown attributes selector = @buildAttributeSelector(groups, attribute)
loopData = [
{
value: 'x-zammad-ticket-priority_id'
name: 'Ticket Priority'
relation: 'TicketPriority'
},
{
value: 'x-zammad-ticket-state_id'
name: 'Ticket State'
relation: 'TicketState'
},
{
value: 'x-zammad-ticket-customer'
name: 'Ticket Customer'
},
{
value: 'x-zammad-ticket-group_id'
name: 'Ticket Group'
relation: 'Group'
},
{
value: 'x-zammad-ticket-owner'
name: 'Ticket Owner'
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-zammad-article-internal'
name: 'Article Internal'
options: { true: 'Yes', false: 'No'}
},
{
value: 'x-zammad-article-type_id'
name: 'Article Type'
relation: 'TicketArticleType'
},
{
value: 'x-zammad-article-sender_id'
name: 'Article Sender'
relation: 'TicketArticleSender'
},
{
value: ''
name: '-'
disable: true
},
{
value: 'x-zammad-ignore'
name: 'Ignore Message'
options: { true: 'Yes', false: 'No'}
},
]
for listItem in loopData
listItem.value = "#{ attribute.name }::#{listItem.value}"
add = { name: '', display: '', tag: 'select', multiple: false, null: false, nulloption: true, options: loopData, translate: true, required: false }
item.find('.addSelection').append( form_controller.formGenItem( add ) )
item.find('.add').bind('click', (e) -> # scaffold of match elements
e.preventDefault() item = $( App.view('generic/postmaster_set')( attribute: attribute ) )
name = $(@).closest('.controls').find('.addSelection').find('select').val() item.find('.js-attributeSelector').prepend(selector)
displayName = $(@).closest('.controls').find('.addSelection').find('select option:selected').html()
return if !name # add filter
addItem( name, displayName, $(@) ) item.find('.js-add').bind('click', (e) =>
element = $(e.target).closest('.js-filterElement')
elementClone = element.clone(true)
element.after(elementClone)
elementClone.find('.js-attributeSelector select').trigger('change')
) )
# show default values # remove filter
loopDataValue = {} item.find('.js-remove').bind('click', (e) =>
if attribute.value $(e.target).closest('.js-filterElement').remove()
for key, value of attribute.value @rebuildAttributeSelectors(item)
displayName = key )
for listItem in loopData
if listItem.value is "#{ attribute.name }::#{key}" # change attribute selector
addItem( "#{ attribute.name }::#{key}", listItem.name, item.find('.add'), value ) item.find('.js-attributeSelector select').bind('change', (e) =>
key = $(e.target).find('option:selected').attr('value')
elementRow = $(e.target).closest('.js-filterElement')
@rebuildAttributeSelectors(item, elementRow, key, attribute)
@buildValue(item, elementRow, key, groups, undefined, undefined, attribute)
)
# build inital params
if !_.isEmpty(params[attribute.name])
selectorExists = false
for key, meta of params[attribute.name]
selectorExists = true
operator = meta.operator
value = meta.value
# get selector rows
elementFirst = item.find('.js-filterElement').first()
elementLast = item.find('.js-filterElement').last()
# clone, rebuild and append
elementClone = elementFirst.clone(true)
@rebuildAttributeSelectors(item, elementClone, key, attribute)
@buildValue(item, elementClone, key, groups, value, operator, attribute)
elementLast.after(elementClone)
# remove first dummy row
if selectorExists
item.find('.js-filterElement').first().remove()
item
@buildValue: (elementFull, elementRow, key, groups, value, operator, attribute) ->
# do nothing if item already exists
name = "#{attribute.name}::#{key}::value"
return if elementRow.find("[name=\"#{name}\"]").get(0)
config = {}
for groupName, meta of groups
for entry in meta.options
if entry.value is key
config = entry
if !config.tag
if config.relation || config.options
config['tag'] = 'select'
else
config['tag'] = 'input'
config['type'] = 'text'
config['name'] = name
config['value'] = value
item = App.UiElement[config.tag].render(config, {})
elementRow.find('.js-value').html(item)
@buildAttributeSelector: (groups, attribute) ->
selection = $('<select class="form-control"></select>')
for groupKey, groupMeta of groups
displayName = App.i18n.translateInline(groupMeta.name)
selection.closest('select').append("<optgroup label=\"#{displayName}\" class=\"js-#{groupKey}\"></optgroup>")
optgroup = selection.find("optgroup.js-#{groupKey}")
for entry in groupMeta.options
displayName = App.i18n.translateInline(entry.name)
optgroup.append("<option value=\"#{entry.value}\">#{displayName}</option>")
selection
@rebuildAttributeSelectors: (elementFull, elementRow, key, attribute) ->
# enable all
elementFull.find('.js-attributeSelector select option').removeAttr('disabled')
# disable all used attributes
elementFull.find('.js-attributeSelector select').each(->
keyLocal = $(@).val()
elementFull.find('.js-attributeSelector select option[value="' + keyLocal + '"]').attr('disabled', true)
)
# disable - if we only have one attribute
if elementFull.find('.js-attributeSelector select').length > 1
elementFull.find('.js-remove').removeClass('is-disabled')
else
elementFull.find('.js-remove').addClass('is-disabled')
# set attribute
if key
elementRow.find('.js-attributeSelector select').val(key)
item

View file

@ -0,0 +1,26 @@
<div class="horizontal-filters">
<div class="horizontal-filter js-filterElement">
<div class="horizontal-filter-body">
<div class="controls">
<div class="u-positionOrigin js-attributeSelector">
<%- @Icon('arrow-down', 'dropdown-arrow') %>
</div>
</div>
<div class="controls">
<div class="u-positionOrigin js-operator">
<select></select>
<%- @Icon('arrow-down', 'dropdown-arrow') %>
</div>
</div>
<div class="controls js-value"></div>
</div>
<div class="filter-controls">
<div class="filter-control filter-control-remove js-remove" title="<%- @T('Remove rule') %>">
<%- @Icon('minus') %>
</div>
<div class="filter-control filter-control-add js-add" title="<%- @T('Add new rule') %>">
<%- @Icon('plus') %>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,20 @@
<div class="horizontal-filters">
<div class="horizontal-filter js-filterElement">
<div class="horizontal-filter-body">
<div class="controls">
<div class="u-positionOrigin js-attributeSelector">
<%- @Icon('arrow-down', 'dropdown-arrow') %>
</div>
</div>
<div class="controls js-value"></div>
</div>
<div class="filter-controls">
<div class="filter-control filter-control-remove js-remove" title="<%- @T('Remove rule') %>">
<%- @Icon('minus') %>
</div>
<div class="filter-control filter-control-add js-add" title="<%- @T('Add new rule') %>">
<%- @Icon('plus') %>
</div>
</div>
</div>
</div>

View file

@ -6,38 +6,44 @@ module Channel::Filter::Database
def self.run( _channel, mail ) def self.run( _channel, mail )
# process postmaster filter # process postmaster filter
filters = PostmasterFilter.where( active: true, channel: 'email' ) filters = PostmasterFilter.where( active: true, channel: 'email' ).order(:name)
filters.each {|filter| filters.each {|filter|
Rails.logger.info " proccess filter #{filter.name} ..." Rails.logger.info " proccess filter #{filter.name} ..."
match = true all_matches_ok = true
looped = false min_one_rule_exists = false
filter[:match].each {|key, value| filter[:match].each {|key, meta|
looped = true
begin begin
next if !meta || !meta['value'] || meta['value'].empty?
min_one_rule_exists = true
scan = [] scan = []
if mail if mail
scan = mail[ key.downcase.to_sym ].scan(/#{value}/i) scan = mail[ key.downcase.to_sym ].scan(/#{meta['value']}/i)
end end
if match && scan[0] if scan[0]
Rails.logger.info " matching #{key.downcase}:'#{mail[ key.downcase.to_sym ]}' on #{value}" if meta[:operator] == 'contains not'
match = true all_matches_ok = false
end
Rails.logger.info " matching #{key.downcase}:'#{mail[ key.downcase.to_sym ]}' on #{meta['value']}"
else else
Rails.logger.info " is not matching #{key.downcase}:'#{mail[ key.downcase.to_sym ]}' on #{value}" if meta[:operator] == 'contains'
match = false all_matches_ok = false
end
Rails.logger.info " not matching #{key.downcase}:'#{mail[ key.downcase.to_sym ]}' on #{meta['value']}"
end end
break if !all_matches_ok
rescue => e rescue => e
match = false all_matches_ok = false
Rails.logger.error "can't use match rule #{value} on #{mail[ key.to_sym ]}" Rails.logger.error "can't use match rule #{meta['value']} on #{mail[ key.to_sym ]}"
Rails.logger.error e.inspect Rails.logger.error e.inspect
end end
} }
next if !looped next if !min_one_rule_exists
next if !match next if !all_matches_ok
filter[:perform].each {|key, value| filter[:perform].each {|key, meta|
Rails.logger.info " perform '#{key.downcase}' = '#{value}'" Rails.logger.info " perform '#{key.downcase}' = '#{meta.inspect}'"
mail[ key.downcase.to_sym ] = value mail[ key.downcase.to_sym ] = meta['value']
} }
} }

View file

@ -0,0 +1,205 @@
# encoding: utf-8
# rubocop:disable all
require 'test_helper'
class EmailPostmasterTest < ActiveSupport::TestCase
test 'process with postmaster filter' do
group1 = Group.create_if_not_exists(
name: 'Test Group1',
created_by_id: 1,
updated_by_id: 1,
)
group2 = Group.create_if_not_exists(
name: 'Test Group2',
created_by_id: 1,
updated_by_id: 1,
)
PostmasterFilter.destroy_all
PostmasterFilter.create(
name: 'not used',
match: {
from: {
operator: 'contains',
value: 'nobody@example.com',
},
},
perform: {
'X-Zammad-Ticket-priority' => {
value: '3 high',
},
},
channel: 'email',
active: true,
created_by_id: 1,
updated_by_id: 1,
)
PostmasterFilter.create(
name: 'used',
match: {
from: {
operator: 'contains',
value: 'me@example.com',
},
},
perform: {
'X-Zammad-Ticket-group_id' => {
value: group1.id,
},
'x-Zammad-Article-Internal' => {
value: true,
},
},
channel: 'email',
active: true,
created_by_id: 1,
updated_by_id: 1,
)
PostmasterFilter.create(
name: 'used x-any-recipient',
match: {
'x-any-recipient' => {
operator: 'contains',
value: 'any@example.com',
},
},
perform: {
'X-Zammad-Ticket-group_id' => {
value: group2.id,
},
'x-Zammad-Article-Internal' => {
value: true,
},
},
channel: 'email',
active: true,
created_by_id: 1,
updated_by_id: 1,
)
data = 'From: me@example.com
To: customer@example.com
Subject: some subject
Some Text'
parser = Channel::EmailParser.new
ticket, article, user = parser.process( { trusted: false }, data )
assert_equal('Test Group1', ticket.group.name)
assert_equal('2 normal', ticket.priority.name)
assert_equal('some subject', ticket.title)
assert_equal('Customer', article.sender.name)
assert_equal('email', article.type.name)
assert_equal(true, article.internal)
data = 'From: Some Body <somebody@example.com>
To: Bob <bod@example.com>
Cc: any@example.com
Subject: some subject
Some Text'
parser = Channel::EmailParser.new
ticket, article, user = parser.process( { trusted: false }, data )
assert_equal('Test Group2', ticket.group.name)
assert_equal('2 normal', ticket.priority.name)
assert_equal('some subject', ticket.title)
assert_equal('Customer', article.sender.name)
assert_equal('email', article.type.name)
assert_equal(true, article.internal)
PostmasterFilter.create(
name: 'used x-any-recipient',
match: {
'x-any-recipient' => {
operator: 'contains not',
value: 'any_not@example.com',
},
},
perform: {
'X-Zammad-Ticket-group_id' => {
value: group2.id,
},
'X-Zammad-Ticket-priority_id' => {
value: '1',
},
'x-Zammad-Article-Internal' => {
value: 'false',
},
},
channel: 'email',
active: true,
created_by_id: 1,
updated_by_id: 1,
)
data = 'From: Some Body <somebody@example.com>
To: Bob <bod@example.com>
Cc: any@example.com
Subject: some subject2
Some Text'
parser = Channel::EmailParser.new
ticket, article, user = parser.process( { trusted: false }, data )
assert_equal('Test Group2', ticket.group.name)
assert_equal('1 low', ticket.priority.name)
assert_equal('some subject2', ticket.title)
assert_equal('Customer', article.sender.name)
assert_equal('email', article.type.name)
assert_equal(false, article.internal)
PostmasterFilter.destroy_all
PostmasterFilter.create(
name: 'used - empty selector',
match: {
from: {
operator: 'contains',
value: '',
},
},
perform: {
'X-Zammad-Ticket-group_id' => {
value: group2.id,
},
'X-Zammad-Ticket-priority_id' => {
value: '1',
},
'x-Zammad-Article-Internal' => {
value: true,
},
},
channel: 'email',
active: true,
created_by_id: 1,
updated_by_id: 1,
)
data = 'From: Some Body <somebody@example.com>
To: Bob <bod@example.com>
Cc: any@example.com
Subject: some subject - no selector
Some Text'
parser = Channel::EmailParser.new
ticket, article, user = parser.process( { trusted: false }, data )
assert_equal('Users', ticket.group.name)
assert_equal('2 normal', ticket.priority.name)
assert_equal('some subject - no selector', ticket.title)
assert_equal('Customer', article.sender.name)
assert_equal('email', article.type.name)
assert_equal(false, article.internal)
PostmasterFilter.destroy_all
end
end