Merge branch 'develop' of github.com:martini/zammad into develop

This commit is contained in:
Felix Niklas 2016-02-04 14:29:05 +01:00
commit 1597278a43
24 changed files with 418 additions and 236 deletions

View file

@ -76,6 +76,7 @@ job_integration_twitter:
stage: test stage: test
tags: tags:
- core - core
- twitter
script: script:
- export RAILS_ENV=test - export RAILS_ENV=test
- rake db:drop; - rake db:drop;

View file

@ -38,6 +38,7 @@ gem 'twitter'
gem 'koala' gem 'koala'
gem 'mail' gem 'mail'
gem 'email_verifier' gem 'email_verifier'
gem 'htmlentities'
gem 'mime-types' gem 'mime-types'

View file

@ -120,6 +120,7 @@ GEM
guard-compat (~> 1.0) guard-compat (~> 1.0)
multi_json (~> 1.8) multi_json (~> 1.8)
hashie (3.4.3) hashie (3.4.3)
htmlentities (4.3.4)
http (1.0.2) http (1.0.2)
addressable (~> 2.3) addressable (~> 2.3)
http-cookie (~> 1.0) http-cookie (~> 1.0)
@ -341,6 +342,7 @@ DEPENDENCIES
execjs execjs
guard (>= 2.2.2) guard (>= 2.2.2)
guard-livereload guard-livereload
htmlentities
icalendar icalendar
json json
koala koala

View file

@ -1,18 +1,22 @@
class App.FirstStepsClues extends App.Controller class App.FirstStepsClues extends App.Controller
clues: [ clues: [
{
container: '.js-dashboardMenuItem'
headline: 'Dashboard'
text: 'Here you see a quick overview about your and other agents performance.'
actions: [
'hover'
]
}
{ {
container: '.search-holder' container: '.search-holder'
headline: 'Search' headline: 'Search'
text: 'Here you can search for ticket, customers and organizations. To find everything use the <kbd>*</kbd>-Placeholder' text: 'Here you can search for ticket, customers and organizations. To find everything use the §*§-Placeholder'
#headline: 'Suche'
#text: 'Um alles zu finden nutze den <kbd>*</kbd>-Platzhalter'
} }
{ {
container: '.user-menu' container: '.user-menu'
headline: 'Create' headline: 'Create'
text: 'Here you can create new tickets. Also if you have the permissions you can create new customers and organizations.' text: 'Here you can create new tickets. Also if you have the permissions you can create new customers and organizations.'
#headline: 'Erstellen'
#text: 'Hier kannst du Tickets, Kunden und Organisationen anlegen.'
actions: [ actions: [
'click .add .js-action', 'click .add .js-action',
'hover .add' 'hover .add'
@ -22,8 +26,6 @@ class App.FirstStepsClues extends App.Controller
container: '.user-menu' container: '.user-menu'
headline: 'Personal Settings' headline: 'Personal Settings'
text: 'Here you can sign out, change the frontend language or see your latest views items.' text: 'Here you can sign out, change the frontend language or see your latest views items.'
#headline: 'Persönliches Menü'
#text: 'Hier findest du den Logout, den Weg zu deinen Einstellungen und deinen Verlauf.'
actions: [ actions: [
'click .user .js-action', 'click .user .js-action',
'hover .user' 'hover .user'
@ -33,18 +35,6 @@ class App.FirstStepsClues extends App.Controller
container: '.js-overviewsMenuItem' container: '.js-overviewsMenuItem'
headline: 'Overviews' headline: 'Overviews'
text: 'Here you find your ticket overviews for open, my assigned or escalated tickets.' text: 'Here you find your ticket overviews for open, my assigned or escalated tickets.'
#headline: 'Übersichten'
#text: 'Hier findest du eine Liste aller Tickets.'
actions: [
'hover'
]
}
{
container: '.js-dashboardMenuItem'
headline: 'Dashboard'
text: 'Here you see a quick overview about your and other agents performance.'
#headline: 'Dashboard'
#text: 'Hier siehst du auf einem Blick ob sich alle Agenten an die Spielregeln halten.'
actions: [ actions: [
'hover' 'hover'
] ]
@ -78,8 +68,6 @@ class App.FirstStepsClues extends App.Controller
onComplete: a callback for when the user is done onComplete: a callback for when the user is done
### ###
@options.onComplete = -> null
@position = 0 @position = 0
@render() @render()
@ -235,7 +223,7 @@ class App.FirstStepsClues extends App.Controller
left = maxWidth - modal.width left = maxWidth - modal.width
if top < 0 if top < 0
moveArrow = modal.height/2 + height moveArrow = modal.height/2 + top
top = 0 top = 0
else if top + modal.height > maxHeight else if top + modal.height > maxHeight
moveArrow = modal.height/2 + maxHeight - (top + modal.height) moveArrow = modal.height/2 + maxHeight - (top + modal.height)

View file

@ -1,4 +1,5 @@
class App.Dashboard extends App.Controller class App.Dashboard extends App.Controller
clueAccess: true
events: events:
'click .tabs .tab': 'toggle' 'click .tabs .tab': 'toggle'
'click .intro': 'clues' 'click .intro': 'clues'
@ -7,7 +8,7 @@ class App.Dashboard extends App.Controller
super super
if @isRole('Customer') if @isRole('Customer')
@navigate '#', true @clueAccess = false
return return
# render page # render page
@ -18,6 +19,8 @@ class App.Dashboard extends App.Controller
return if !@authenticate(true) return if !@authenticate(true)
@render() @render()
@mayBeClues()
render: -> render: ->
@html App.view('dashboard')( @html App.view('dashboard')(
@ -34,14 +37,34 @@ class App.Dashboard extends App.Controller
limit: 25 limit: 25
) )
mayBeClues: =>
return if !@clueAccess
return if !@activeState
preferences = @Session.get('preferences')
@clueAccess = false
return if preferences['intro']
@clues()
clues: (e) => clues: (e) =>
e.preventDefault() @clueAccess = false
if e
e.preventDefault()
new App.FirstStepsClues( new App.FirstStepsClues(
el: @el el: @el
onComplete: =>
@ajax(
id: 'preferences'
type: 'PUT'
url: @apiPath + '/users/preferences'
data: JSON.stringify({user:{intro:true}})
processData: true
)
) )
active: (state) => active: (state) =>
@activeState = state @activeState = state
if state
@mayBeClues()
isActive: => isActive: =>
@activeState @activeState
@ -51,6 +74,10 @@ class App.Dashboard extends App.Controller
show: (params) => show: (params) =>
if @isRole('Customer')
@navigate '#', true
return
# set title # set title
@title 'Dashboard' @title 'Dashboard'

View file

@ -151,7 +151,11 @@ class Index extends App.ControllerContent
success: (data, status, xhr) => success: (data, status, xhr) =>
if data.result is 'import_done' if data.result is 'import_done'
window.location.reload() delay = 0
if @Config.get('developer_mode') is true
delay = 5000
@delay(window.location.reload, delay)
return return
if data.result is 'error' if data.result is 'error'

View file

@ -184,6 +184,12 @@ class _i18nSingleton extends Spine.Module
translated = App.Utils.htmlEscape(@translate(string, args)) translated = App.Utils.htmlEscape(@translate(string, args))
# apply inline markup
translated
.replace(/\*(.+?)\*/gm, '<b>$1</b>')
.replace(/_(.+?)_/gm, '<u>$1</u>')
.replace(/§(.+?)§/gm, '<kbd>$1</kbd>')
translatePlain: (string, args) => translatePlain: (string, args) =>
@translate(string, args) @translate(string, args)

View file

@ -367,14 +367,6 @@
this.$widget.find('ul').html('') this.$widget.find('ul').html('')
this.log('result', term, result) this.log('result', term, result)
if (!result[0]) {
result = [{id:'', name: '-'}]
}
if (!this.active) {
this.open()
}
var elements = $() var elements = $()
for (var i = 0; i < result.length; i++) { for (var i = 0; i < result.length; i++) {
@ -383,7 +375,7 @@
element.attr('data-id', item.id) element.attr('data-id', item.id)
element.text(App.Utils.htmlEscape(item.name)) element.text(App.Utils.htmlEscape(item.name))
element.addClass('u-clickable u-textTruncate') element.addClass('u-clickable u-textTruncate')
if (i == result.length-1 && item.id != '') { if (i == result.length-1) {
element.addClass('is-active') element.addClass('is-active')
} }
if (item.keywords) { if (item.keywords) {

View file

@ -4,7 +4,7 @@
<%- @Icon('diagonal-cross') %> <%- @Icon('diagonal-cross') %>
</div> </div>
<div class="modal-header"><%- @T(@headline) %></div> <div class="modal-header"><%- @T(@headline) %></div>
<div class="modal-body"><%- @text %></div> <div class="modal-body"><%- @T(@text) %></div>
<div class="modal-controls"> <div class="modal-controls">
<div class="modal-control"> <div class="modal-control">
<div class="<% if @position is 0: %>is-disabled <% end %>btn btn--text js-previous"><%- @T( 'Previous' ) %></div> <div class="<% if @position is 0: %>is-disabled <% end %>btn btn--text js-previous"><%- @T( 'Previous' ) %></div>

View file

@ -18,7 +18,7 @@ class Observer::Ticket::Notification < ActiveRecord::Observer
EventBuffer.reset EventBuffer.reset
via_web = false via_web = false
if ENV['SERVER_NAME'] if ENV['RACK_ENV'] || Rails.configuration.webserver_is_active
via_web = true via_web = true
end end

View file

@ -2,3 +2,6 @@
require ::File.expand_path('../config/environment', __FILE__) require ::File.expand_path('../config/environment', __FILE__)
run Zammad::Application run Zammad::Application
# set config to do no self notification
Rails.configuration.webserver_is_active = true

View file

@ -0,0 +1,2 @@
Rails.configuration.webserver_is_active = false

View file

@ -149,43 +149,50 @@ class String
# replace multiple spaces with one # replace multiple spaces with one
string.gsub!(/ /, ' ') string.gsub!(/ /, ' ')
# strip all &amp; &lt; &gt; &quot; # try HTMLEntities, if it fails on invalid signes, use manual way
string.gsub!( '&amp;', '&' ) begin
string.gsub!( '&lt;', '<' ) coder = HTMLEntities.new
string.gsub!( '&gt;', '>' ) string = coder.decode(string)
string.gsub!( '&quot;', '"' ) rescue
string.gsub!( '&nbsp;', ' ' )
# encode html entities like "&#8211;" # strip all &amp; &lt; &gt; &quot;
string.gsub!( /(&\#(\d+);?)/x ) { string.gsub!( '&amp;', '&' )
$2.chr string.gsub!( '&lt;', '<' )
} string.gsub!( '&gt;', '>' )
string.gsub!( '&quot;', '"' )
string.gsub!( '&nbsp;', ' ' )
# encode html entities like "&#3d;" # encode html entities like "&#8211;"
string.gsub!( /(&\#[xX]([0-9a-fA-F]+);?)/x ) { string.gsub!( /(&\#(\d+);?)/x ) {
chr_orig = $1 $2.chr
hex = $2.hex }
if hex
chr = hex.chr # encode html entities like "&#3d;"
if chr string.gsub!( /(&\#[xX]([0-9a-fA-F]+);?)/x ) {
chr_orig = chr chr_orig = $1
hex = $2.hex
if hex
chr = hex.chr
if chr
chr_orig = chr
else
chr_orig
end
else else
chr_orig chr_orig
end end
else
chr_orig
end
# check valid encoding # check valid encoding
begin begin
if !chr_orig.encode('UTF-8').valid_encoding? if !chr_orig.encode('UTF-8').valid_encoding?
chr_orig = '?'
end
rescue
chr_orig = '?' chr_orig = '?'
end end
rescue chr_orig
chr_orig = '?' }
end end
chr_orig
}
# remove tailing empty spaces # remove tailing empty spaces
string.gsub!(/\s+\n$/, "\n") string.gsub!(/\s+\n$/, "\n")

View file

@ -148,7 +148,7 @@ module Import::Zendesk
initialize_client initialize_client
# retrive statistic # retrive statistic
statistic = { result = {
'Tickets' => 0, 'Tickets' => 0,
'TicketFields' => 0, 'TicketFields' => 0,
'UserFields' => 0, 'UserFields' => 0,
@ -162,20 +162,14 @@ module Import::Zendesk
'Automations' => 0, 'Automations' => 0,
} }
statistic.each { |object, _score| result.each { |object, _score|
result[ object ] = @client.send( object.underscore.to_sym ).count!
counter = 0
@client.send( object.underscore.to_sym ).all do |_resource|
counter += 1
end
statistic[ object ] = counter
} }
if statistic if result
Cache.write('import_zendesk_stats', statistic) Cache.write('import_zendesk_stats', result)
end end
statistic result
end end
=begin =begin
@ -317,12 +311,7 @@ module Import::Zendesk
local_fields = local_object.constantize.column_names local_fields = local_object.constantize.column_names
zendesk_object_fields = [] @client.send("#{local_object.downcase}_fields").all! { |zendesk_object_field|
@client.send("#{local_object.downcase}_fields").all { |zendesk_object_field|
zendesk_object_fields.push(zendesk_object_field)
}
zendesk_object_fields.each { |zendesk_object_field|
if local_object == 'Ticket' if local_object == 'Ticket'
mapped_object_field = method("mapping_#{local_object.downcase}_field").call( zendesk_object_field.type ) mapped_object_field = method("mapping_#{local_object.downcase}_field").call( zendesk_object_field.type )
@ -472,13 +461,7 @@ module Import::Zendesk
def import_groups def import_groups
@zendesk_group_mapping = {} @zendesk_group_mapping = {}
zendesk_groups = [] @client.groups.all! { |zendesk_group|
@client.groups.all { |zendesk_group|
zendesk_groups.push(zendesk_group)
}
zendesk_groups.each { |zendesk_group|
local_group = Group.create_if_not_exists( local_group = Group.create_if_not_exists(
name: zendesk_group.name, name: zendesk_group.name,
active: !zendesk_group.deleted, active: !zendesk_group.deleted,
@ -526,12 +509,7 @@ module Import::Zendesk
role_agent = Role.lookup(name: 'Agent') role_agent = Role.lookup(name: 'Agent')
role_customer = Role.lookup(name: 'Customer') role_customer = Role.lookup(name: 'Customer')
zendesk_users = [] @client.users.all! { |zendesk_user|
@client.users.all { |zendesk_user|
zendesk_users.push(zendesk_user)
}
zendesk_users.each { |zendesk_user|
local_user_fields = { local_user_fields = {
login: zendesk_user.id.to_s, # Zendesk users may have no other identifier than the ID, e.g. twitter users login: zendesk_user.id.to_s, # Zendesk users may have no other identifier than the ID, e.g. twitter users
@ -602,12 +580,7 @@ module Import::Zendesk
@zendesk_user_group_mapping = {} @zendesk_user_group_mapping = {}
zendesk_group_memberships = [] @client.group_memberships.all! { |zendesk_group_membership|
@client.group_memberships.all { |zendesk_group_membership|
zendesk_group_memberships.push(zendesk_group_membership)
}
zendesk_group_memberships.each { |zendesk_group_membership|
@zendesk_user_group_mapping[ zendesk_group_membership.user_id ] ||= [] @zendesk_user_group_mapping[ zendesk_group_membership.user_id ] ||= []
@zendesk_user_group_mapping[ zendesk_group_membership.user_id ].push( zendesk_group_membership.group_id ) @zendesk_user_group_mapping[ zendesk_group_membership.user_id ].push( zendesk_group_membership.group_id )
@ -641,12 +614,7 @@ module Import::Zendesk
article_type_facebook_feed_post = Ticket::Article::Type.lookup(name: 'facebook feed post') article_type_facebook_feed_post = Ticket::Article::Type.lookup(name: 'facebook feed post')
article_type_facebook_feed_comment = Ticket::Article::Type.lookup(name: 'facebook feed comment') article_type_facebook_feed_comment = Ticket::Article::Type.lookup(name: 'facebook feed comment')
zendesk_tickets = [] @client.tickets.all! { |zendesk_ticket|
@client.tickets.all { |zendesk_ticket|
zendesk_tickets.push(zendesk_ticket)
}
zendesk_tickets.each { |zendesk_ticket|
zendesk_ticket_fields = {} zendesk_ticket_fields = {}
zendesk_ticket.custom_fields.each { |zendesk_ticket_field| zendesk_ticket.custom_fields.each { |zendesk_ticket_field|
@ -661,6 +629,7 @@ module Import::Zendesk
} }
local_ticket_fields = { local_ticket_fields = {
id: zendesk_ticket.id,
title: zendesk_ticket.subject, title: zendesk_ticket.subject,
note: zendesk_ticket.description, note: zendesk_ticket.description,
group_id: @zendesk_group_mapping[ zendesk_ticket.group_id ] || 1, group_id: @zendesk_group_mapping[ zendesk_ticket.group_id ] || 1,
@ -708,7 +677,13 @@ module Import::Zendesk
end end
end end
local_ticket = Ticket.create( local_ticket_fields ) local_ticket = Ticket.find_by(id: local_ticket_fields[:id])
if local_ticket
local_ticket.update_attributes(local_ticket_fields)
else
local_ticket = Ticket.create(local_ticket_fields)
_reset_pk('tickets')
end
zendesk_ticket_tags = [] zendesk_ticket_tags = []
zendesk_ticket.tags.each { |tag| zendesk_ticket.tags.each { |tag|
@ -735,6 +710,7 @@ module Import::Zendesk
ticket_id: local_ticket.id, ticket_id: local_ticket.id,
body: zendesk_article.html_body, body: zendesk_article.html_body,
internal: !zendesk_article.public, internal: !zendesk_article.public,
message_id: zendesk_article.id,
updated_by_id: @zendesk_user_mapping[ zendesk_article.author_id ] || 1, updated_by_id: @zendesk_user_mapping[ zendesk_article.author_id ] || 1,
created_by_id: @zendesk_user_mapping[ zendesk_article.author_id ] || 1, created_by_id: @zendesk_user_mapping[ zendesk_article.author_id ] || 1,
} }
@ -750,20 +726,14 @@ module Import::Zendesk
end end
if zendesk_article.via.channel == 'web' if zendesk_article.via.channel == 'web'
local_article_fields[:message_id] = zendesk_article.id
local_article_fields[:type_id] = article_type_web.id local_article_fields[:type_id] = article_type_web.id
elsif zendesk_article.via.channel == 'email' elsif zendesk_article.via.channel == 'email'
local_article_fields[:from] = zendesk_article.via.source.from.address local_article_fields[:from] = zendesk_article.via.source.from.address
local_article_fields[:to] = zendesk_article.via.source.to.address # Notice zendesk_article.via.from.original_recipients=[\"another@gmail.com\", \"support@example.zendesk.com\"] local_article_fields[:to] = zendesk_article.via.source.to.address # Notice zendesk_article.via.from.original_recipients=[\"another@gmail.com\", \"support@example.zendesk.com\"]
local_article_fields[:message_id] = zendesk_article.id
local_article_fields[:type_id] = article_type_email.id local_article_fields[:type_id] = article_type_email.id
elsif zendesk_article.via.channel == 'sample_ticket' elsif zendesk_article.via.channel == 'sample_ticket'
local_article_fields[:message_id] = zendesk_article.id
local_article_fields[:type_id] = article_type_note.id local_article_fields[:type_id] = article_type_note.id
elsif zendesk_article.via.channel == 'twitter' elsif zendesk_article.via.channel == 'twitter'
local_article_fields[:message_id] = zendesk_article.id
# TODO
local_article_fields[:type_id] = if zendesk_article.via.source.rel == 'mention' local_article_fields[:type_id] = if zendesk_article.via.source.rel == 'mention'
article_type_twitter_status.id article_type_twitter_status.id
else else
@ -772,11 +742,9 @@ module Import::Zendesk
elsif zendesk_article.via.channel == 'facebook' elsif zendesk_article.via.channel == 'facebook'
local_article_fields[:from] = zendesk_article.via.source.from.facebook_id local_article_fields[:from] = zendesk_article.via.source.from.facebook_id
local_article_fields[:to] = zendesk_article.via.source.to.facebook_id local_article_fields[:to] = zendesk_article.via.source.to.facebook_id
local_article_fields[:message_id] = zendesk_article.id
# TODO
local_article_fields[:type_id] = if zendesk_article.via.source.rel == 'post' local_article_fields[:type_id] = if zendesk_article.via.source.rel == 'post'
article_type_facebook_feed_post.id article_type_facebook_feed_post.id
else else
@ -785,7 +753,12 @@ module Import::Zendesk
end end
# create article # create article
local_article = Ticket::Article.create( local_article_fields ) local_article = Ticket::Article.find_by(message_id: local_article_fields[:message_id])
if local_article
local_article.update_attributes(local_article_fields)
else
local_article = Ticket::Article.create( local_article_fields )
end
zendesk_attachments = zendesk_article.attachments zendesk_attachments = zendesk_article.attachments
@ -842,12 +815,7 @@ module Import::Zendesk
# https://developer.zendesk.com/rest_api/docs/core/macros # https://developer.zendesk.com/rest_api/docs/core/macros
def import_macros def import_macros
zendesk_macros = [] @client.macros.all! { |zendesk_macro|
@client.macros.all { |zendesk_macro|
zendesk_macros.push(zendesk_macro)
}
zendesk_macros.each { |zendesk_macro|
# TODO # TODO
next if !zendesk_macro.active next if !zendesk_macro.active
@ -899,12 +867,7 @@ module Import::Zendesk
# https://developer.zendesk.com/rest_api/docs/core/views # https://developer.zendesk.com/rest_api/docs/core/views
def import_views def import_views
zendesk_views = [] @client.views.all! { |zendesk_view|
@client.views.all { |zendesk_view|
zendesk_views.push(zendesk_view)
}
zendesk_views.each { |zendesk_view|
# "url" => "https://example.zendesk.com/api/v2/views/59511071.json" # "url" => "https://example.zendesk.com/api/v2/views/59511071.json"
# "id" => 59511071 # "id" => 59511071
@ -1033,12 +996,7 @@ module Import::Zendesk
# https://developer.zendesk.com/rest_api/docs/core/automations # https://developer.zendesk.com/rest_api/docs/core/automations
def import_automations def import_automations
zendesk_automations = [] @client.automations.all! { |zendesk_automation|
@client.automations.all { |zendesk_automation|
zendesk_automations.push(zendesk_automation)
}
zendesk_automations.each { |zendesk_automation|
# "url" => "https://example.zendesk.com/api/v2/automations/60037892.json" # "url" => "https://example.zendesk.com/api/v2/automations/60037892.json"
# "id" => 60037892 # "id" => 60037892
@ -1077,4 +1035,10 @@ module Import::Zendesk
} }
end end
# reset primary key sequences
def self._reset_pk(table)
return if ActiveRecord::Base.connection_config[:adapter] != 'postgresql'
ActiveRecord::Base.connection.reset_pk_sequence!(table)
end
end end

View file

@ -274,6 +274,18 @@ test( "i18n", function() {
translated = App.i18n.translateContent('%s %s test', 123, 'xxx'); translated = App.i18n.translateContent('%s %s test', 123, 'xxx');
equal( translated, '123 xxx test', 'de-de - %s %s' ); equal( translated, '123 xxx test', 'de-de - %s %s' );
translated = App.i18n.translateContent('*%s* %s test', 123, 'xxx');
equal( translated, '<b>123</b> xxx test', 'de-de - *%s* %s' );
translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx');
equal( translated, '<u>123</u> xxx test', 'de-de - _%s_ %s' );
translated = App.i18n.translateContent('§%s§ %s test', 123, 'xxx');
equal( translated, '<kbd>123</kbd> xxx test', 'de-de - §%s§ %s' );
translated = App.i18n.translateContent('\'%s\' %s test', 123, 'xxx');
equal( translated, '&#39;123&#39; xxx test', 'de-de - \'%s\' %s' );
translated = App.i18n.translateContent('<test&now>//*äöüß'); translated = App.i18n.translateContent('<test&now>//*äöüß');
equal( translated, '&lt;test&amp;now&gt;//*äöüß', 'de - <test&now>//*äöüß' ); equal( translated, '&lt;test&amp;now&gt;//*äöüß', 'de - <test&now>//*äöüß' );
@ -299,6 +311,18 @@ test( "i18n", function() {
translated = App.i18n.translateContent('%s %s test', 123, 'xxx'); translated = App.i18n.translateContent('%s %s test', 123, 'xxx');
equal( translated, '123 xxx test', 'en-us - %s %s' ); equal( translated, '123 xxx test', 'en-us - %s %s' );
translated = App.i18n.translateContent('*%s* %s test', 123, 'xxx');
equal( translated, '<b>123</b> xxx test', 'en-us - *%s* %s' );
translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx');
equal( translated, '<u>123</u> xxx test', 'en-us - _%s_ %s' );
translated = App.i18n.translateContent('§%s§ %s test', 123, 'xxx');
equal( translated, '<kbd>123</kbd> xxx test', 'en-us - §%s§ %s' );
translated = App.i18n.translateContent('\'%s\' %s test', 123, 'xxx');
equal( translated, '&#39;123&#39; xxx test', 'en-us - \'%s\' %s' );
translated = App.i18n.translateContent('<test&now>'); translated = App.i18n.translateContent('<test&now>');
equal( translated, '&lt;test&amp;now&gt;', 'en-us - <test&now>' ); equal( translated, '&lt;test&amp;now&gt;', 'en-us - <test&now>' );

View file

@ -156,6 +156,12 @@ class TestCase < Test::Unit::TestCase
fail 'auto wizard login failed' fail 'auto wizard login failed'
end end
assert(true, 'auto wizard login ok') assert(true, 'auto wizard login ok')
clues_close(
browser: instance,
optional: true,
)
return return
end end
screenshot(browser: instance, comment: 'login_failed') screenshot(browser: instance, comment: 'login_failed')
@ -182,6 +188,12 @@ class TestCase < Test::Unit::TestCase
screenshot(browser: instance, comment: 'login_failed') screenshot(browser: instance, comment: 'login_failed')
fail 'login failed' fail 'login failed'
end end
clues_close(
browser: instance,
optional: true,
)
screenshot(browser: instance, comment: 'login_ok') screenshot(browser: instance, comment: 'login_ok')
assert(true, 'login ok') assert(true, 'login ok')
login login
@ -217,6 +229,32 @@ class TestCase < Test::Unit::TestCase
fail 'no login box found, seems logout was not successfully!' fail 'no login box found, seems logout was not successfully!'
end end
=begin
clues_close(
browser: browser1,
optional: false,
)
=end
def clues_close(params = {})
switch_window_focus(params)
log('clues_close', params)
instance = params[:browser] || @browser
clues = instance.find_elements({ css: '.js-modal--clue .js-close' })[0]
if !params[:optional] && !clues
screenshot(browser: instance, comment: 'no_clues')
fail 'Unable to closes clues, no clues found!'
end
return if !clues
instance.execute_script("$('.js-modal--clue .js-close').click()")
assert(true, 'clues closed')
sleep 4
end
=begin =begin
location( location(

70
test/fixtures/mail36.box vendored Normal file
View file

@ -0,0 +1,70 @@
Return-Path: <m.Smith@example.com>
X-Original-To: me@example.com
Delivered-To: martin@arber.example.com
Received-SPF: softfail (example.com: Sender is not authorized by default to use 'm.Smith@example.com' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) receiver=arber.example.com; identity=mailfrom; envelope-from="m.Smith@example.com"; helo=mout.web.de; client-ip=212.227.15.14
Received: from mout.web.de (mout.web.de [2.2.1.1])
by arber.example.com (Postfix) with ESMTPS id CC5CF61391
for <me@example.com>; Wed, 3 Feb 2016 13:23:33 +0100 (CET)
Received: from [79.228.218.253] by 3capp-webde-bs15.server.lan (via HTTP);
Wed, 3 Feb 2016 13:23:33 +0100
MIME-Version: 1.0
Message-ID: <trinity-147fd84a-1e14-4765-bbc0-8c1387385e8f-1454502213303@3capp-webde-bs15>
From: "Martin Smith" <m.Smith@example.com>
To: "Martin Edenhofer" <me@example.com>
Subject: Fw: Zugangsdaten
Content-Type: text/html; charset=UTF-8
Date: Wed, 3 Feb 2016 13:23:33 +0100
Importance: normal
Sensitivity: Normal
References: <70E61C7E-7508-45D9-918E-D890862641E1@example.com>,
<trinity-0f474eb0-4274-4af8-b928-83c21e7881eb-1454499808226@3capp-webde-bs15>
X-UI-Message-Type: mail
X-Priority: 3
X-Provags-ID: V03:K0:/WfykMPf5Mwa0ZvXBNkPO5anKRmg15X0kEGEx6sir6T
Iu1DfMCe1Rqe3ptJJPM6rUy7U0VBf9/N8eAXiGMlekWzR4A1KD
t2D3jKxbBmHQTLoPNpOLpQkO86WZPkGEIRvi4GzGt6y7+AF6Wr
YKe4AHIigSb7TubsOEGhV8vRzB7oObrecn+X9vfQD1vgQextTn
aZrl8Uz4Iq8Qgc9HaDcg2+IG7ZBMKeTgKGlqNqOEpj76pRy3il
HfkGfFxxgbnKg/RK0X0oC1rwgMubWuAxwA97c6AeTLFnPJxtPt ZQu4v0=
X-UI-Out-Filterresults: notjunk:1;V01:K0:Z3b52B2Tvas=:1Ly2mLCISrNqxwJZwsSJvd
ggRZBL9pBdcfKBkFAX6sMmwK+lPYbULi0XgW1MYCDo1JffR9/0dMVKxNGebwN6cBYp9BOZ4PL
c12fINf2qyNQpOUhI5OGSsdltK9XZqPk1MVBK2VoGF2HUo+lBhtzt9ilmD8zdMgXTla9YzQfu
mEm90UGBuITr3Cqln3YOV8nH24PTYE0nvkqLFRENEpR3cUGFxTYWiImuDjr8x+GaUcdqoa7EP
jxQQgSn011n3PozpFcDaw/09WrmkwJ4BlfXbu5jKdQR1X1hzSUrXxniCy1DY2QtX5OqPu+CnA
LrrHBQM4+Arxzd438ajIFoUlswodEY5HGOERMC4SxORgirHKkQz117HjPuPCHoLHqf+zmXgS5
k68l59J5dk2qb1UvcidOMMMYyLEE0Le0K88qs8doKy5RnQZz+butudnLd2NsNZtyWPFbxZu3S
Vb8PRK9Gng==
<html><head></head><body><div style="font-family: Verdana;font-size: 12.0px;"><div><br/>
&nbsp;</div>
<div class="signature">--&nbsp;<br/>
don&#39;t&nbsp;cry&nbsp;-&nbsp;work!&nbsp;(Rainald&nbsp;Goetz)</div>
<div>&nbsp;
<div>&nbsp;
<div name="quote" style="margin:10px 5px 5px 10px; padding: 10px 0 10px 10px; border-left:2px solid #C3D9E5; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">
<div style="margin:0 0 10px 0;"><b>Gesendet:</b>&nbsp;Mittwoch, 03. Februar 2016 um 12:43 Uhr<br/>
<b>Von:</b>&nbsp;&quot;Martin Smith&quot; &lt;m.Smith@example.com&gt;<br/>
<b>An:</b>&nbsp;linuxhotel@zammad.com<br/>
<b>Betreff:</b>&nbsp;Fw: Zugangsdaten</div>
<div name="quoted-content">
<div style="font-family: Verdana;font-size: 12.0px;">
<div><br/>
&nbsp;</div>
<div class="signature">--&nbsp;<br/>
don&#39;t&nbsp;cry&nbsp;-&nbsp;work!&nbsp;(Rainald&nbsp;Goetz)</div>
<div>&nbsp;
<div>&nbsp;
<div style="margin: 10.0px 5.0px 5.0px 10.0px;padding: 10.0px 0 10.0px 10.0px;border-left: 2.0px solid rgb(195,217,229);">
<div style="margin: 0 0 10.0px 0;"><b>Gesendet:</b>&nbsp;Freitag, 22. Januar 2016 um 11:52 Uhr<br/>
<b>Von:</b>&nbsp;&quot;Martin Edenhofer&quot; &lt;me@example.com&gt;<br/>
<b>An:</b>&nbsp;m.Smith@example.com<br/>
<b>Betreff:</b>&nbsp;Zugangsdaten</div>
<div>Um noch vertrauter zu werden, kannst Du mit einen externen E-Mail Account (z. B. <a href="http://web.de" target="_blank">web.de</a>) mal ein wenig selber &ldquo;spielen&rdquo;. :)</div>
</body></html>

View file

@ -29,6 +29,8 @@ class AutoWizardTest < TestCase
timeout: 20, timeout: 20,
) )
clues_close
organization_open_by_search( organization_open_by_search(
value: 'Demo Organization', value: 'Demo Organization',
) )

View file

@ -79,17 +79,32 @@ class ZendeskImportBrowserTest < TestCase
click(css: '.js-migration-start') click(css: '.js-migration-start')
watch_for( watch_for(
css: 'body', css: '.js-group .js-done',
value: 'login', value: '2',
timeout: 60,
)
watch_for(
css: '.js-organization .js-done',
value: '1',
timeout: 60,
)
watch_for(
css: '.js-user .js-done',
value: '141',
timeout: 60,
)
watch_for(
css: '.js-ticket .js-done',
value: '143',
timeout: 300, timeout: 300,
) )
assert_equal( 143, User.count, 'users' ) watch_for(
assert_equal( 3, Group.count, 'groups' ) css: 'body',
assert_equal( 5, Role.count, 'roles' ) value: 'login',
assert_equal( 2, Organization.count, 'organizations' ) )
assert_equal( 144, Ticket.count, 'tickets' )
assert_equal( 151, Ticket::Article.count, 'ticket articles' )
assert_equal( 2, Store.count, 'ticket article attachments' )
end end
end end

View file

@ -48,7 +48,7 @@ class ZendeskImportTest < ActiveSupport::TestCase
assert_equal( 3, Group.count, 'groups' ) assert_equal( 3, Group.count, 'groups' )
assert_equal( 5, Role.count, 'roles' ) assert_equal( 5, Role.count, 'roles' )
assert_equal( 2, Organization.count, 'organizations' ) assert_equal( 2, Organization.count, 'organizations' )
assert_equal( 144, Ticket.count, 'tickets' ) assert_equal( 143, Ticket.count, 'tickets' )
assert_equal( 151, Ticket::Article.count, 'ticket articles' ) assert_equal( 151, Ticket::Article.count, 'ticket articles' )
assert_equal( 2, Store.count, 'ticket article attachments' ) assert_equal( 2, Store.count, 'ticket article attachments' )
@ -275,10 +275,10 @@ class ZendeskImportTest < ActiveSupport::TestCase
checks = [ checks = [
{ {
id: 3, id: 2,
data: { data: {
title: 'test', title: 'test',
note: 'test email', note: 'This is the first comment. Feel free to delete this sample ticket.',
create_article_type_id: 1, create_article_type_id: 1,
create_article_sender_id: 2, create_article_sender_id: 2,
article_count: 2, article_count: 2,
@ -290,6 +290,38 @@ class ZendeskImportTest < ActiveSupport::TestCase
organization_id: 2, organization_id: 2,
}, },
}, },
{
id: 3,
data: {
title: 'Bob Smith, here is the test ticket you requested',
note: 'test email',
create_article_type_id: 10,
create_article_sender_id: 2,
article_count: 4,
state_id: 3,
group_id: 3,
priority_id: 1,
owner_id: 1,
customer_id: 7,
organization_id: nil,
},
},
{
id: 5,
data: {
title: 'Twitter',
note: '@DesafioCaracol sh q acaso sto se vale ver el jueg...',
create_article_type_id: 6,
create_article_sender_id: 2,
article_count: 1,
state_id: 1,
group_id: 3,
priority_id: 2,
owner_id: 1,
customer_id: 91,
organization_id: nil,
},
},
{ {
id: 143, id: 143,
data: { data: {
@ -306,38 +338,6 @@ class ZendeskImportTest < ActiveSupport::TestCase
organization_id: nil, organization_id: nil,
}, },
}, },
{
id: 5,
data: {
title: 'Twitter',
note: '@DesafioCaracol sh q acaso sto se vale ver el jueg...',
create_article_type_id: 6,
create_article_sender_id: 2,
article_count: 1,
state_id: 1,
group_id: 3,
priority_id: 2,
owner_id: 1,
customer_id: 90,
organization_id: nil,
},
},
{
id: 2,
data: {
title: 'This is a sample ticket requested and submitted by you',
note: 'This is the first comment. Feel free to delete this sample ticket.',
create_article_type_id: 10,
create_article_sender_id: 1,
article_count: 4,
state_id: 3,
group_id: 3,
priority_id: 3,
owner_id: 1,
customer_id: 4,
organization_id: 2,
},
},
# { # {
# id: , # id: ,
# data: { # data: {
@ -359,16 +359,16 @@ class ZendeskImportTest < ActiveSupport::TestCase
checks.each { |check| checks.each { |check|
ticket = Ticket.find( check[:id] ) ticket = Ticket.find( check[:id] )
assert_equal( check[:data][:title], ticket.title, 'title' ) assert_equal( check[:data][:title], ticket.title, "title of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:create_article_type_id], ticket.create_article_type_id, 'created_article_type_id' ) assert_equal( check[:data][:create_article_type_id], ticket.create_article_type_id, "created_article_type_id of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:create_article_sender_id], ticket.create_article_sender_id, 'created_article_sender_id' ) assert_equal( check[:data][:create_article_sender_id], ticket.create_article_sender_id, "created_article_sender_id of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:article_count], ticket.article_count, 'article_count' ) assert_equal( check[:data][:article_count], ticket.article_count, "article_count of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:state_id], ticket.state.id, 'state_id' ) assert_equal( check[:data][:state_id], ticket.state.id, "state_id of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:group_id], ticket.group.id, 'group_id' ) assert_equal( check[:data][:group_id], ticket.group.id, "group_id of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:priority_id], ticket.priority.id, 'priority_id' ) assert_equal( check[:data][:priority_id], ticket.priority.id, "priority_id of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:owner_id], ticket.owner.id, 'owner_id' ) assert_equal( check[:data][:owner_id], ticket.owner.id, "owner_id of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:customer_id], ticket.customer.id, 'customer_id' ) assert_equal( check[:data][:customer_id], ticket.customer.id, "customer_id of Ticket.find(#{check[:id]})" )
assert_equal( check[:data][:organization_id], ticket.organization.try(:id), 'organization_id' ) assert_equal( check[:data][:organization_id], ticket.organization.try(:id), "organization_id of Ticket.find(#{check[:id]})" )
} }
end end

View file

@ -132,7 +132,7 @@ class AaaStringTest < ActiveSupport::TestCase
html = ' line&nbsp;1<br> html = ' line&nbsp;1<br>
you<br/> you<br/>
-----&amp;' -----&amp;'
should = 'line 1 should = 'line 1
you you
-----&' -----&'
assert_equal( should, html.html2text) assert_equal( should, html.html2text)

View file

@ -86,7 +86,7 @@ Liebe Grüße!
}, },
{ {
data: IO.read('test/fixtures/mail6.box'), data: IO.read('test/fixtures/mail6.box'),
body_md5: '6229bcc5fc1396445d781daf3c12a285', body_md5: '683ac042e94e99a8bb5e8ced7893b1d7',
params: { params: {
from: '"Hans BÄKOSchönland" <me@bogen.net>', from: '"Hans BÄKOSchönland" <me@bogen.net>',
from_email: 'me@bogen.net', from_email: 'me@bogen.net',
@ -97,9 +97,9 @@ Liebe Grüße!
___ ___
[1] Compare Cable, DSL or Satellite plans: As low as $2.95. [1] Compare Cable, DSL or Satellite plans: As low as $2.95.
Test1:8 Test1:
Test2:& Test2:&
Test3:&ni; Test3:
Test4:& Test4:&
Test5:= Test5:=
@ -328,7 +328,7 @@ Hof
# spam email # spam email
{ {
data: IO.read('test/fixtures/mail16.box'), data: IO.read('test/fixtures/mail16.box'),
body_md5: '5e96cc53e78c0e44523502ee50647808', body_md5: '91e698a1ba3679dff398ba3587b3f3d9',
params: { params: {
from: nil, from: nil,
from_email: 'vipyimin@126.com', from_email: 'vipyimin@126.com',
@ -373,7 +373,7 @@ Hof
}, },
{ {
data: IO.read('test/fixtures/mail20.box'), data: IO.read('test/fixtures/mail20.box'),
body_md5: '646e803f30cddf06db90f426df3672c1', body_md5: 'ddcbbb850491ae9a174c4f1e42309f84',
params: { params: {
from: 'Health and Care-Mall <drugs-cheapest8@sicor.com>', from: 'Health and Care-Mall <drugs-cheapest8@sicor.com>',
from_email: 'drugs-cheapest8@sicor.com', from_email: 'drugs-cheapest8@sicor.com',
@ -382,28 +382,28 @@ Hof
to: 'info2@znuny.com', to: 'info2@znuny.com',
body: "________________________________________________________________________Yeah but even when they. Beth liî ed her neck as well body: "________________________________________________________________________Yeah but even when they. Beth liî ed her neck as well
&oacute;25aHw511I&Psi;11xG&lfloor;o8KHCm&sigmaf;9-2&frac12;23Qg&ntilde;V6UAD12AX&larr;t1Lf7&oplus;1Ir&sup2;r1TLA5pYJhjV gPn&atilde;M36V1E89RUD&Tau;&Aring;12I92s2C&Theta;YE&upsih;Afg&lowast;bT11&int;rIoi&scaron;&brvbar;O5oUIN1Is2S21Pp &Yuml;2q1F&Chi;&uArr;eGOz&lceil;F1R98y&sect; 74&rdquo;lTr8r1H2&aelig;u2E2P2q VmkfB&int;SKNElst4S&exist;182T2G1&iacute; lY92Pu&times;8>R&Ograve;&not;&oplus;&Mu;I&Ugrave;z&Ugrave;CC412QE&Rho;&ordm;S2!Xg&OElig;s. óû5aHw5³½IΨµÁxGo8KHCmς9-Ö½23QgñV6UAD¿ùAXt¨Lf7®Ir²r½TLA5pYJhjV gPnãM36V®E89RUDΤÅ©ÈI9æsàCΘYEϒAfgbT¡1rIoiš¦O5oUIN±IsæSعPp Ÿÿq1FΧeGOzF³R98y§ 74lTr8r§HÐæuØEÛPËq VmkfBSKNElst4SÁ8üTðG°í lY9åPu×8>¬ΜIÙzÙCC4³ÌQEΡºSè!XgŒs.
2&gamma;&dArr;B[1] cwspC&ensp;L8I C K88H E1R?E2e31 !Calm dylan for school today. çγB[1] cwspCLI C KH E R Eëe3¸ !Calm dylan for school today.
Closing the nursery with you down. Here and made the mess. Maybe the from under his mother. Song of course beth touched his pants. Closing the nursery with you down. Here and made the mess. Maybe the from under his mother. Song of course beth touched his pants.
When someone who gave up from here. Feel of god knows what. When someone who gave up from here. Feel of god knows what.
TB&piv;&exist;M5T5&Epsilon;Ef2&ucirc;&ndash;N&para;1v&Zeta;'1&dArr;&prop;5S2225 &Chi;0j&Delta;HbAg&thorn;E&mdash;2i6A2lD&uArr;LGj2nTOy11H2&tau;9&rsquo;:Their mother and tugged it seemed like TBϖM5T5ΕEf2ûNÁvΖ'®5SÐçË5 Χ0jΔHbAgþE2i6A2lDLGjÓnTOy»¦Hëτ9:Their mother and tugged it seemed like
d3RsV&para;H2&Theta;i&macr;B&part;gax1b&icirc;gdH23r2J&yuml;1aIK1&sup2; n1jfaTk1Vs3952 C&tilde;lBl&lsquo;mxGo0&radic;2XwT8Ya 28ksa&int;f1&alefsym;s&rdquo;62Q 2Ad7$p32d1e&prod;2e.0&rdquo;261a2&Kappa;63&alpha;SM2 Nf52CdL&cup;1i&harr;xcaa52R3l6Lc3i2z16s&oacute;9&egrave;U zDE1aE21gs25&Euml;2 hE1cl&sup;&cent;11o21&micro;Bw1zF1 q2k&otilde;aXUius1r0&sube; d&bull;&isin;2$1Z2F1218l.07d56P&Uacute;l25JAO6 d3RsVHÓΘi¯Bgax1bîgdHä3rýJÿ1aIKDz n1jfaTk³Vs395ß C˜lBlmxGo0úXwT8Ya õ8ksaf·s6ÑQ ÍAd7$p32d1eæe.0×61Κ63αSMû Nf5ÉCdL1ixcaa5êR3l6Lc3iãz16só9èU zDE²aEȨgs25ËÞ hE§cl¢¢ÂoÒµBw²zF© qÏkõaXUius1r0 dø$¢Z2F12­8l.07d56PÚl25JAO6
45loV2iv1i2&atilde;&Upsilon;&lfloor;a2&sup;d2g&Atilde;&Upsilon;3&trade;r22u&cedil;aWjO8 n40&ndash;Soy&egrave;2u1&empty;23p1J&Mu;Ne&Igrave;22jr&aacute;2r&Kappa; 1229A2rAkc8nuEtl22ai&Dagger;OB8vSb&eacute;&sigma;e&iota;&otilde;q1+65cw 2s8Ua&ograve;4PrsE1y8 &lang;fMElh&upsih;&sdot;Jo8pmzwj&circ;N1 wv39aW1WtsvuU3 1a&oelig;1$2&Nu;nR2O2&rceil;B.&forall;2c&rarr;5&Ecirc;9&chi;w5p1&frasl;N fHGFVfE&sup3;2i&sigma;jGpa51kgg12cWrUq52akx2h 0F24P&cedil;2L2rn22&Iuml;o2&Yacute;2HfoRb2eU&alpha;w6s2N&oline;ws&para;13&Beta;i2X1&cedil;ofgtHnR&perp;32ase92lF1H5 26B1a&sup;2i&upsih;s&ocirc;12i &Aring;kMyl2J1&Auml;oQ&ndash;0&image;wvm&ugrave;2 2&circ;&mu;\"aQ7jVse62f 1h2p$L2r&pound;3i1t2.323h5qP8g0&hearts;&divide;R2 45loVóiv1i2ãΥd2gÃΥ3rÎÍu¸aWjO8 n40Soyè2u¡Î3p¢JΜNeÌé×jráÒrΚ 1ÌÓ9AúrAkc8nuEtl22aiOB8vSbéσeιõq1+65cw Òs8Uaò4PrsE1y8 fMElhϒJo8pmzwjˆN¥ wv39aW¡WtsvuU3 1³ΝnR2OÏB.þc5Ê9χw5pÃN fHGFVfE³ãiσjGpa5kgg¡ìcWrUq5æakx2h 0Fè4P¸ÕLñrn22ÏoþÝÐHfoRb2eUαw6sñNws§3ΒiòX¸ofgtHnR3âase9álF¿H5 à6BÁa2iϒ¡ói ÅkMylÚJ¾ÄoQ0wvmùþ ˈμ\"aQ7jVse6Ðf «hÜp$Lâr£3i1tÚ.323h5qP8g0♥÷R÷
&middot;i&fnof;PV1&Beta;&ni;&oslash;iF1R1a4v32gL9&cent;wr1722a2&ucirc;0&eta; &thorn;12&szlig;Stu21u7&aacute;&iexcl;lp2ocEe1SLlrV2Xj &perp;U&micro;1F&not;48&eth;ov71Arm242c2Vw2e1&sect;&supe;N 1242aL&thorn;Z2ski&times;5 c&euro;pBl&ucirc;26&part;ol1f&Uacute;wK&szlig;32 4i2la4C12sRE21 &atilde;eI2$2z8t442fG.&cedil;1&le;12F&rsquo;&Atilde;152in&nsub; Tl1&euml;C2v7Ci71X8a225Nl&thorn;U&rang;&iota;icO&sum;&laquo;s&middot;iKN Uu&upsih;jS1j52u2J&uuml;&sect;pn5&deg;1e&yen;&Ucirc;3&weierp;r1W&Dagger;2 J&lsaquo;S7A1j0sc&1pkt1qq2iZ561vn81&lowast;e22Q3+723&Scaron; &sum;RkLaKX2as2s22 &iuml;111lD2z8o278wwU&ndash;&Agrave;C T6U2a&upsih;938s20G&yuml; Ox2&isin;$98&lsquo;R21H25.&Ograve;L6b9&theta;r&delta;292f9j ·iƒPV1ΒøiF¤RÃa4v3âgL9¢wr¨7ø×aÏû0η þ1àßStuÞ³u7á¡lpÑocEe·SLlrVàXj ¢F¬48ðov7¨Arm×4ÍcùVwÞe1§N ÂÛ4äaLþZ2ski×5 cpBlûù6olÃfÚwKß3Ñ 4iíla4C³êsREÕ1 ãeIó$âz8t442fG.¸1¸2FÃ152in Tl©ëC2v7Ci7·X8a×ú5NlþUιicO«s·iKN UuϒjSÃj5Ýu÷§pn5°§e¥Û3rÆWò JS7A1j0sc&ºpkt·qqøiZ56½vn8¨eîØQ3+7Î3Š RkLaKXËasÐsÌ2 ïÇ­lDäz8oã78wwUÀC T6Uûaϒ938sÌ0Gÿ Oxó$98R2ÂHï5.ÒL6b9θrδÜ92f9j
Please matt on his neck. Okay matt huï ed into your mind Since her head to check dylan. Where dylan matt got up there Please matt on his neck. Okay matt huï ed into your mind Since her head to check dylan. Where dylan matt got up there
1&Egrave;&plusmn;&Alpha;AYQ1dN12&upsih;XT00&Agrave;vI&or;&iacute;o8-1b&reg;8A&Epsilon;1V4Lg&Otilde;&uarr;7LKtgcEiw1yR5Y22GRA1&deg;I10C2C2Ti&uuml;/2wc0Ax211S&Uuml;&Acirc;2&OElig;T&Aacute;22&ograve;HpN&acirc;&ugrave;M6&Egrave;10A5Tb1:Simmons and now you really is what. Matt picked up this moment later that. 1ȱΑAYQªdN¬ÚϒXT00ÀvIío8-½b®8AΕºV4LgÕ7LKtgcEiw­yR5YýæGRA1°I¿0CïCàTiü/þwc0Ax211SÜÂùŒTÁ2êòHpNâùM6Ⱦ0A5Tb»:Simmons and now you really is what. Matt picked up this moment later that.
251yV922Yeg1&uarr;DnJ3l4t22b1os&prod;jll&divide;iS2iwB&Icirc;4n021&Ouml; 1f&divide;2a11l2su&Uacute;82 2LCblgvN&frac12;o1oP3wn&spades;90 FZora&M&trade;xs&Kappa;bb1 251&xi;$12&middot;22iG2&nabla;1&supe;&Xi;&not;3.0P0&kappa;53V1203&Yacute;Yz 2X&cent;BAZ4Kwddu2vvuB&uarr;&Beta;a1&rsquo;THi0&mdash;93rZ&epsilon;j0 1r&Mu;1a2111s71&Iota;f 8&dArr;2olW&bdquo;62o6yH&yen;wKZ&and;6 21h2aKJ&ldquo;&real;s48I&Igrave; 21&not;1$Z&Sigma;122&ntilde;26B42YMZ.21V19f10&aring;54&lceil;R8 25¯yV9ÙßYeg·DnJ3l4tÝæb1osjll÷iSÐiwBÎ4n0ú1Ö ªf÷Ña§1løsuÚ8ê 2LCblgvN½o¼oP3wn90 FZora&MxsΚbb ç5Ãξ$Âô·×2iGæ1Ξ¬3.0P0κ53VÁö03ÝYz øX¢BAZ4KwdduÜvvuBΒTHi093rZεj0 §rΜÅa2­·§s7¸Ιf 8þolW6Ýo6yH¥wKZ6 21hÒaKJs48IÌ ÔÀ¬­$ZΣ¹ü2ñÙ6B42YMZ.Ô¹V¼9f·0å54R8
2w\"9N2gB&Agrave;a2S&ecirc;1s&cong;gG&Ocirc;o0Dn4n&crarr;&gamma;7&otimes;eS7e2xf3Jd q&divide;CMa221isNMZp zz0&tilde;l&Kappa;Lw8o229ww1&sect;Qu 1D&lceil;&iacute;a2212sJ811 3o&ugrave;2$&brvbar;1N&real;1>R2t7WPM1.181D92k5D9&lowast;8&asymp;R l131Sj1&Psi;8p&Sigma;2K&ugrave;i6rr2rb&Ucirc;u&not;i2V&lowast;&prod;v5&ordf;10a27B1 &Uacute;&diams;&Xi;sa9j3&chi;sa1i&Omicron; Oi&weierp;ml6&oacute;f2owbz&forall;wA6&ugrave;&rarr; 22b2ai1wbs&diams;&beta;Gs 281i$i&Agrave;&circ;12&sup;2wC82n8o.13NJ9S11&Theta;0P1Sd ÷w\"9N2gBÀaðSê¢s≅gGÔo0Dn4n↵γ7⊗eS7eýxf3Jd q÷CMaÍä³isNMZp zz0˜lΚLw8oë29ww¤§Qu ¥D⌈íaýË¢ésJ8Á¬ 3oùÙ$¦1N1>Rét7WPM¨.¶8¹D92k5D98≈R l©3ªSj·Ψ8pΣïKùi6rrÔrbÛu¬i2V∏v5ª10a27BÁ Ú♦Ξsa9j3χsa¯iΟ Oi℘ml6óféowbz∀wA6ù→ ñ×bàai´wbs♦βGs Ù81i$iÀˆ12⊃2wC82n8o.µ3NJ9S1©Θ0P1Sd
What made no one in each time. Mommy was thinking of course beth. Everything you need the same thing What made no one in each time. Mommy was thinking of course beth. Everything you need the same thing
P2EVG29srEx&lArr;9oN3U1yE2i2OR5k&Ccedil;&yuml;A&Tau;&eta;&nu;ULP&iquest;&and;q R5&iquest;FHt7J6E&raquo;1C&empty;A2&exist;aVLu&lowast;&cent;tT&lang;21&scaron;Hq9N&eacute;: PïEVGÿ9srEx9oN3U®yEÎi2OR5kÇÿAΤηνULP¿q R5¿FHt7J6E»¯CaVLu¢tT2ÚHq9Né:
&perp;&THORN;21T11BrrC712ad&scaron;6lmzb16ai07tdBo&times;Kop&iacute;&Rho;1lj4Hy 2a&Oacute;1a&Ouml;&iacute;&notin;&Oacute;s1a2&rsquo; 4D1kleow2o3&ndash;12wjR&le;&Pi; 1Rh2af27&cong;s26u2 8NLV$&cup;&dArr;1&darr;1Y&para;21.v2&Egrave;232S7202n11 m5VKZy3K2i&ntilde;21Dt&Uacute;2HrhGaMvr5&iuml;R1o11nam&Mu;w22anFu8x7&lceil;sU E4cva11&epsilon;&trade;s7&Alpha;GO dA35ld&ntilde;&Igrave;&egrave;oA&xi;I1wXK2n f1x&frac34;a&prod;7ffs&dagger;222 5msC$72t10z&bdquo;n2.it1T7O8vt5182&middot; J&iuml;12Pk&aacute;O1rn2rAo8s5&empty;z&mdash;4Rha11t&tilde;cq5Y&Chi; &Tau;Q2ra2&rfloor;4&sup1;s&Uuml;51&sect; 2VB&iota;luw2ioL32Bw1111 5&isin;22a1I22s&scaron;&Ucirc;21 G17&rho;$kJM80&sim;&ang;&alefsym;l.J1Km3212&sup;52&eacute;&frac14;&sect; p121A1NU0c&yen;x2fo&lang;22cm14QGpHEj7lnDPVieV21a&Pi;2H7 1j26azBSes&euml;1c9 &acute;2&Ugrave;&not;l0n21o22RVw1X1&Iuml; &alpha;V21a&cong;&sigma;1Zs&sect;jJ&aring; 3pFN$1Kf821Y&Omicron;7.32Y95J&Alpha;q&Yuml;0v91Q ÞÞ¨T¦ªBrrC7³2adš6lmzb¨6ai07tdBo×KopíΡÄlj4Hy ÝaÓ1aÖíÓs1aá 4D­kleowËo31ÍwjRΠ £RhÈafà7sù6u2 8NLV$»1Y2µ.vßÈ23ÖS7û0Ün¬Ä m5VKZy3KÎiñë¹DtÚ2HrhGaMvr5ïR«oÂ1namΜwÐãanFu8x7sU E4cva£Âεs7ΑGO dA35ldñÌèoAξI1wXKïn f¼x¾a7ffsìÖð 5msC$7Ët¦0zn÷.it¡T7O8vt5¼8å· Jï1ÏPkáOrnùrAo8s5z4Rha1®t˜cq5YΧ ΤQÍraÑ4¹sÜ5²§ ûVBιluwóioL3ëBw£±1 5àáa1IÊ2sšÛÛ G´7ρ$kJM80l.J1Km32µÚ5ã鼧 p°ÿ­A¹NU0c¥xçfoØácm14QGpHEj7lnDPVieV2aΠ2H7 ²j26azBSesë1c9 ´2Ù¬l0nò¤oõâRVw¦X´Ï α­aσ¼Zs§jJå 3pFN$¾Kf821YΟ7.3ÍY95JΑqŸ0v9ÄQ
&ntilde;&uarr;yjP&Tau;1u6rFwhNeCO&piv;2d5&Gamma;&ecirc;cne&frac14;a0iTF15sxUS0o88&alefsym;1la&Aring;T&weierp;oOB11n2111e&and;Kpf &upsilon;98&xi;abp&dagger;3sj82& 9&copy;Bol2AWSo7wNgw21mM tteQat0&piv;2s4&equiv;N&Ccedil; &Otilde;&AElig;1&Theta;$2R2q0117&ordf;.mt111&mdash;uwF57H&clubs;f &aelig;&cup;HYSj&psi;3By&scaron;1g1ndX15t1126hZ&rArr;y2r82mdowy2di&psi;8Y&Eta;d0r&scaron;&Scaron; N029a13I&brvbar;sQa&yacute;2 20Y7lZ118o&int;50&Ccedil;w1\"1&Zeta; n6&Uuml;&ge;a&nabla;l&szlig;nsF&rsaquo;J9 1D&Omicron;K$142L0S7z2.Ta2X31R9953911 ñyjPΤ1u6rFwhNeCOϖúd5Γêcne¼a0iTF¹5sxUS0o88ℵªlaÅToOBÀ¹·­1eKpf υ98ξabp3sj8â& 9©BolÎAWSo7wNgwø¦mM tteQat0ϖ2s4 ÕƦΘ$ùRÓq0·Ã7ª.mt¾³1uwF57Hf æHYSjψ3Byš²g¤ndXÀ5tµ¯ò6hZyÿr8ÿmdowyðdiψ8YΗd0ršŠ N0Ý9aÃ3I¦sQaýê Õ0Y7lZ¯18o50Ç\"©Ζ n6Ü≥a∇lßnsFJ9 ºDΟK$Á4ÉL0S7zÖ.Ta2X3²R995391¡
Turning to mess up with. Well that to give her face Another for what she found it then. Since the best to hear Turning to mess up with. Well that to give her face Another for what she found it then. Since the best to hear
GX1&diams;Ca2isA18&iexcl;bN2&icirc;81A22z&Theta;D&nabla;tNXIfWi&ndash;Ap2WYNYF1b &ne;7y&phi;Dpj6&copy;R04E1U1&ntilde;n7G1o2jS111&ni;TC&perp;&pi;&Euml;O1&lowast;21RtS2wE6621 &nu;222ASi21DP&ldquo;8&lambda;V&and;W&sdot;OA2g6qNtNp1T269XA7&yen;11GGI6SEwU22S3&Chi;12!Okay let matt climbed in front door. Well then dropped the best she kissed GX°Ca2isA¾8¡bNÉî8ÂAöÜzΘDtNXIfWiAp2WYNYF®b 7yφDpj6©R04EÂU´ñn7GÆoÌjS³ÁTCπËO1÷©RtS2wE66è­ νÑêéASi21DP8λVWOAÖg6qNtNp1T269XA7¥À²GGI6SEwU2íS3Χ!Okay let matt climbed in front door. Well then dropped the best she kissed
122C>&Phi;221 flQkWM&Scaron;tvo2dV1rT1ZtlN6R9dZ12LwuD19i3B5Fdc&AElig;l2eSwJd K1tDDfoX&plusmn;evr&yacute;wlK7P&divide;i1e13v2z&egrave;Ce&not;&Mu;&clubs;&Nu;rGhs2y172Y!gZp&aacute; R6O4O112&ni;r92Z1dB6i1e2&sigma;&sim;&Oacute;rCZ1s 122I31e2&curren;+&rceil;C&ecirc;U 1k6wG1c&sbquo;1o60AJoR72sd3i11s22pt &Oslash;277a2&forall;f5np&curren;n2duE8&rArr; 21SHGJVAtew&nabla;L&euml;t&sigmaf;2D2 6k28FgQQ&sub;R81L2EI2&notin;iEH&Iacute;&Eacute;3 H2r5Af1qxim&sigmaf;&rho;&Dagger;r6&copy;2jmWv92aW21giAC21lM&rfloor;1k 2V2&cedil;S2&ugrave;&theta;2h15B&Iota;i&lowast;ttEp8&cent;EPpSzWJi32U2n5&igrave;Ihgx8n&rceil;!j&prod;e5 ¤ÊüC>ΦÉí© flQkWMŠtvoÐdV¯rT´ZtlN6R9dZ¾ïLwuD¢9i3B5FdcÆlÝeSwJd KªtDDfoX±evrýwlK7P÷i§e³3vÎzèCe¬ΜΝrGhsáy°72Y!gZpá R6O4O»£ðr9ÊZÀdB6iÀeîσÓrCZ1s ²ú÷I3ÁeÒ¤+CêU »k6wG´c¾o60AJoR7Ösd3i¿Ásððpt Øè77f5np¤nþduE8 ȹSHGJVAtewLëtςëDæ 6kÌ8FgQQR8ÇL2EI2iEHÍÉ3 Hÿr5Af1qximςρr6©2jmWv9ÛaWð¸giACÜ¢lM¿k ʸSÓùθçhµ5BΙittEp8¢EPpSzWJi32UÎn5ìIhgx8n!je5
x1qJ>mC7f 512y1GA420lCQe09s9u%uks&atilde; &psi;2X5A4g3nu&larr;&Tau;yst72pMh&scaron;g12e&rang;p&Uacute;1n1Y&fnof;&Scaron;t&Eacute;2LGizqQ&darr;c3t&Ugrave;I &oelig;&iuml;bXMK&Ucirc;RSertj2d\"Ot2ss581!oo2i F&Acirc;W2EW2DDx7hI2p&Phi;S2Bi2drUr&hArr;J<2a1&Alpha;zwt01p2i28R2oH21&Auml;n172r 1122DYvO7ak21ht204&Pi;e&part;&lambda;11 12dUo&omicron;1X3fc631 e&&cup;GOxT3CvXcO1e3K2&nu;r31y2 262z31&infin;I1 P&igrave;&exist;zYt6F4e6&egrave;&dArr;va5229rk&Theta;32sKP5R!&iota;&micro;mz x¯qJ>mC7f 5ºñy1GA4Ý0lCQe09s9u%uksã ψìX5A4g3nuΤyst7ÍpMhšgÀÖe£n¼YƒŠtÉÚLGizqQc3tÙI œïbXMKÛRSertj×d\"OtÊss58®!oo2i FÂWáEWøDDx7hIÕpΦSôBiÒdrUr⇔J<Õa1Αzwt0°p×ià8RÌoHÛ1Än¥7ÿr ¯¥õàDYvO7aká»htì04Πe∂λÇ1 1ÈdUoο°X3fc63¶ e&GOxT3CvXcO·e3KËνr3¸y2 26Ëz3Ã∞I± Pì∃zYt6F4e6è⇓va5÷þ9rkΘ3äsKP5R!ιµmz
3212>22&prime;L 2&oacute;B&perp;S&cap;OQMe&yacute;&notin;2&Phi;c229Tu2a&int;dr25&ucirc;MeLk92 121OO&oslash;9oKn&yuml;&psi;&Agrave;Wl7H2&empty;i9&rho;&Egrave;2ni2&bull;2eXPx&iacute; 1251SUqtBh72a5otSZ9p222Dpf1&Yacute;2i2&omega;bjn11&Yuml;2gs2h&minus; b&aring;2swx2oSiq8hvt2262h&lceil;b&sup2;S 26&thorn;SVBEFCi2U&agrave;ds9&Ntilde;1&Epsilon;a11&xi;2,1&bdquo;wv jw7AMK2&harr;la2G91s23&laquo;etuB2keD&atilde;2&igrave;r1&uml;IeC&frac34;Ea&Auml;ao&divide;&Prime;&and;r>6e1d9D21,mtS2 I&lowast;44A1R&circ;2M98zME&cong;Q&Yuml;&ETH;X&sup1;4j6 20n3a1&apos;22nxpl6d832J 06&ETH;9E22&yacute;2-2829c42r2h72&yen;med&frac12;&spades;kc23sPk12&bull;r!&rang;QCa 3í1ë>ð2L 2óBSOQMeýÑΦcöè9Tuãadrâ5ûMeLk9Ô £æ1OOø9oKnÿψÀWl7HÏi9ρÈÊniâÛeXPxí ´Í5¡SUqtBh7æa5otSZ9pØËÛDpf®ÝÊiÛωbjn¯½Ÿ2gsçh båÌswxðoSiq8hvtèé6Òhb²S ×6þSVBEFCiøUàds9Ñ¤Ε§ξÜ,1wv jw7AMKÈlaæG9¦së3«etuB2keDãæìr°¨IeC¾EaÄao÷r>6e¸d9DùÇ,mtSö I44A¹RˆêM98zMEQŸÐX¹4j6 î0n3a1'Êânxpl6d83þJ 06Ð9Eïãýã-28Ú9c4ßrØh7è¥med½kcñ3sPk2r!QCa
&Scaron;e21>1&sigma;12 bp&oslash;NERN8eaD61ns7Abhy&plusmn;12&cap; D7sVR8&apos;1Ee22DVfc&tilde;32u72&AElig;qnc23qd2&sim;4&nabla;s&rho;mi5 6212a21&prop;TnQb9sd1M&ugrave;&image; &sum;gM22bN2&para;4c&auml;&frac12;&sube;/4X1&kappa;71f1z &piv;12ECzf&bull;1uMbycs1&bull;9&frac34;ts0T2o3h2DmSs31e7B2&Eacute;r2&sdot;22 &phi;81&Prime;SSX&eth;1u&uacute;I15p58uHp2c2&plusmn;o&part;T1Rrd6sMt&cup;1&micro;&xi;!24Xb ŠeÏÀ>Ãσ½å bpøNERN8eaD6Åns7Abhy±Æü D7sVR8'ºEeÿáDVfc˜3ëu7ÏÆqncË3qdÊ4sρmi5 6æ¾Ê°TnQb9sdÀMù gMÿ2bNð4½/4X1κ7¥f1z ϖ1úECzf1uMbycs19¾ts0Tào3hêDmSs3Áe7BíÉrôãÔ φ8ÄSSXð¤uúI¸5p58uHp2cß±oT©Rrd6sMtµµξ!é4Xb
Both hands through the fear in front. Both hands through the fear in front.
Wade to give it seemed like this. Yeah but one for any longer. Everything you going inside the kids. Wade to give it seemed like this. Yeah but one for any longer. Everything you going inside the kids.
@ -414,7 +414,7 @@ Wade to give it seemed like this. Yeah but one for any longer. Everything you go
}, },
{ {
data: IO.read('test/fixtures/mail21.box'), data: IO.read('test/fixtures/mail21.box'),
body_md5: '617017ee0b2d1842f410fceaac696230', body_md5: 'c9fb828072385643e528ab3a9ce7f10c',
params: { params: {
from: 'Viagra Super Force Online <pharmacy_affordable1@ertelecom.ru>', from: 'Viagra Super Force Online <pharmacy_affordable1@ertelecom.ru>',
from_email: 'pharmacy_affordable1@ertelecom.ru', from_email: 'pharmacy_affordable1@ertelecom.ru',
@ -684,6 +684,42 @@ Weil wir die Echtheit oder Vollständigkeit der in dieser Nachricht enthaltenen
body: 'some html text', body: 'some html text',
}, },
}, },
{
data: IO.read('test/fixtures/mail36.box'),
body_md5: '428327fb533b387b3efca181ae0c25d0',
params: {
from: 'Martin Smith <m.Smith@example.com>',
from_email: 'm.Smith@example.com',
from_display_name: 'Martin Smith',
subject: 'Fw: Zugangsdaten',
to: 'Martin Edenhofer <me@example.com>',
body: ' 
-- 
don\'t cry - work! (Rainald Goetz)
 
 
Gesendet: Mittwoch, 03. Februar 2016 um 12:43 Uhr
Von: "Martin Smith" <m.Smith@example.com>
An: linuxhotel@zammad.com
Betreff: Fw: Zugangsdaten
 
-- 
don\'t cry - work! (Rainald Goetz)
 
 
Gesendet: Freitag, 22. Januar 2016 um 11:52 Uhr
Von: "Martin Edenhofer" <me@example.com>
An: m.Smith@example.com
Betreff: Zugangsdaten
Um noch vertrauter zu werden, kannst Du mit einen externen E-Mail Account (z. B. [1] web.de) mal ein wenig selber spielen. :)
[1] http://web.de',
},
},
] ]
count = 0 count = 0

View file

@ -141,28 +141,28 @@ Some Text",
1 => { 1 => {
body: "_________________________________________________________________________________Please beth saw his head body: "_________________________________________________________________________________Please beth saw his head
92hH3&yuml;oI221G1&iquest;iH16u-2&loz;NQ422U1awAq&sup1;JLZ&mu;2IicgT1&zeta;2Y7&sube;t 63&lsquo;M236E2&Yacute;&rarr;DA2&dagger;I048CvJ9A&uarr;3iTc4&Eacute;I&Upsilon;vXO502N1FJS&eth;1r 154F1HPO11CRxZp tL&icirc;T9&ouml;XH1b3Es1W mN2Bg3&otilde;EbP&OElig;S2f&tau;T&oacute;Y4 sU2P2&zeta;&Delta;RFkcI21&trade;C&Oacute;Z3E&Lambda;Rq!Cass is good to ask what that 9õhH3ÿoIÚõ´¿iH±6u-ûNQ4ùäU¹awAq¹JLZμÒIicgT1ζ2Y7t 63Mñ36EßÝDAåI048CvJ9A3iTc4ÉIΥvXO50ñNÁFJSð­r 154F1HPOÀ£CRxZp tLîT9öXH1b3Es±W mNàBg3õEbPŒSúfτTóY4 sUÖPÒζΔRFkcIÕ1CÓZ3EΛRq!Cass is good to ask what that
86&Euml;[1] 2u2C L I C1K H E R E28MLuke had been thinking about that. 86Ë[1] ÏuÕC L I C K   H E R E28MLuke had been thinking about that.
Shannon said nothing in fact they. Matt placed the sofa with amy smiled. Since the past him with more. Maybe he checked the phone. Neither did her name only. Ryan then went inside matt. Shannon said nothing in fact they. Matt placed the sofa with amy smiled. Since the past him with more. Maybe he checked the phone. Neither did her name only. Ryan then went inside matt.
Maybe we can have anything you sure. Maybe we can have anything you sure.
&aacute;&bull;XMY2&Aring;EE12N&deg;kP'd&Auml;1S4&rceil;d &radic;p&uml;H&Sigma;>jE4y4AC22L2&ldquo;vT&and;4tHX1X: áXMYÍÅEE£ÓN°kP'dÄÅS4d p¨>jE4y4ACüûLìvT4tHXÆX:
x5VV\"1ti21aa&Phi;3fg&brvbar;z2r1&deg;haeJw n1Va879s&AElig;3j f1&iuml;l29lo5F1w&nu;11 &kappa;&psi;&rsaquo;a9f4sLsL 2Vo$v3x1&cedil;nz.u2&brvbar;1H4s3527 yoQC1FMiMzda1Z&epsilon;l&Yacute;HNi1c2s2&ndash;&piv; DYha&atilde;7Ns421 n3dl1X1o11&para;wpN&uarr; YQ7a239s1q2 QyL$fc21&Nu;S5.5Wy621d5&Auml;1H x5VV\"¹tiçÂaaΦ3fg¦zèr«°haeJw n§Va879sÆ3j f¶ïlÞ9lo5F¾wν¶1 κψa9f4sLsL ùVo$v3x1¸nz.uȦ1H4s35Ô7 yoQCÄFMiMzda¯ZεlÝHNi¬cÚsùϖ DYhaã7Ns4Ö· n3dl1XÆo¯µ¶wpN↑ YQ7aé39s1qÓ QyL$fcÕ1ΝS5.5Wy62­d5ĶH
17<V401i421a&theta;1Tg21Gr9E2a&Rho;Bw &rarr;2&Ouml;SRSLu72lpL6Ve191r1HL FEpA229cP&not;lt&Ograve;cDib2XvTtFel3&reg;+bVM 252aXWas4&ordm;2 &mu;2Kl&prod;7mo&radic;23wSg1 &iota;&pound;Ca11Xso18 1L2$&hellip;412Jo&uarr;.0&Lambda;a53i&egrave;55W2 23IV4&loz;9iF2Va2&Otilde;&oacute;g8&sup3;9r&weierp;buaf12 fc7Pg3&sube;rz&ccedil;8o2&minus;&sdot;f&yuml;&ge;ZeaP&Ntilde;s5&lArr;Tsi&Psi;&ni;i92uoU8Rn&Psi;&rceil;&bull;aw1flf22 TQNaU&rsaquo;&eacute;svDu B1Il6&Theta;lo&ang;HfwNX8 36Xa&sim;&alpha;1sT1d &Scaron;HG$2&otilde;13QW1.&permil;&rsaquo;Y52g80&brvbar;ao ³7<V401i4æÂaθÀTg÷ÄGr9EûaΡBw ÌÖSRSLu72lpL6Veº9Ær¾HL FEpAÕø9cP¬ltÒcDibäXvTtFel3®+bVM ø5ôaXWas4ºä μÕKl7moþ3wSg1 ι£Ca´´Xso18 ÅL2$4¾2Jo.0Λa53iè55WÕ î3IV49iFÊVaßÕóg8³9rbuaf®2 fc7Pg3rzç8oÜfÿZeaPÑs5TsiΨi9ÌuoU8RnΨaw1flfùë TQNaUésvDu BÇIl6ΘloHfwNX8 36Xaα»sT½d ŠHG$Îõ¬3QWÀ.Y5Ôg80¦ao
LKNV0&Auml;wiM4xafsJgFJ2r27&rdquo;a&lArr;M2 &ang;O5SQ2Mut21p2&Aring;&Atilde;e&uml;2HrZ41 1U&Lambda;F&uml;Tso2wXr24Icky2e1qY 074a2l&lfloor;s2H1 42pl24Xob0aw4F&Ocirc; 28&there4;a70lsA30 &szlig;WF$Z&cedil;v4AEG.2612t9p5&para;1Q M91C&epsilon;92i0qPa1A2lW5Pi5Vusi8&euml; 2O0SE2Eu2&isin;2p2Y3eTs6r622 l12Ay2jcQpet13&otilde;iiqXvPVOe81V+1&ldquo;G 126a1&Pi;7sJ2g 1J2l&hearts;&Scaron;1o2olwBV2 &rarr;Ama&eta;2&macr;sa22 H22$2Ef2&isin;n5.&OElig;8H95119&sup;&fnof;2 LKNV0ÄwiM4xafsJgFJär27a O5SQØMuté«p÷ÅÃe¨ûHrZ4Ä 1UΛF¨TsoûwXrú4Ickyçe½qY 074aÙlsÐH1 4Ùplø4Xob0aw4FÔ 28a70lsA30 ßWF$Z¸v4AEG.Î6¨2t9p5¼Q M9¯Cε92i0qPa¹AölW5Pi5Vusi8ë ðO0SE2EuùèpòY3eTs6r6ý2 lªÌAyîjcQpet½3õiiqXvPVOe8­V+«G ¤ó6a®Π7sJÕg ¡JÈlŠ¾oÐolwBVà AmaηÒ¯saÑÚ Häð$2Ef2n5.Œ8H95¨19ƒõ
Up dylan in love and found herself. Sorry for beth smiled at some time Whatever you on one who looked. Except for another man and ready. Up dylan in love and found herself. Sorry for beth smiled at some time Whatever you on one who looked. Except for another man and ready.
&Uacute;2eAC2&oslash;N&Euml;1UT3L&spades;IC&euml;9-B&OElig;fAo&Oacute;CL5&Beta;2LH&omicron;NE5&part;7RScdGX11Ip&Sigma;uCCw&or;/D16A1v2S0d&sub;T1&apos;BHf2&Delta;M227A63B: ÚúeACíøN˵UT3LICë9-BŒfAoÓCL5ΒÉLHοNE57RScdGX­ªIpΣuCCw/D¤6A´vâS0d'BHfóΔMåß7A63B:
2U2V51Ue212nRm2t22Oo&gamma;12ly&frac14;Wi6pxn&Agrave;Z1 c2Sa8&iuml;1sG2&sub; &Mu;Jll1&pound;&bdquo;onb2w&rceil;&ouml;1 vY8a&Theta;mgs024 &aring;&yen;G$1592KkU11b0.&frac12;&Acirc;&real;54&Egrave;h0&ordm;1h Zf1A0j&cedil;dc1&xi;v&trade;Xpagl2ib8YrSf0 1Wia141s1&times;7 TAwll1dom1Gw2&iquest;z &Beta;21a&circ;y2sN8&eta; 3oo$D012&Lambda;p14c2z.PA&empty;9&upsih;7354&uacute;9 2UýV5¦Ueý¿×nRm2tæÓOoγ1øly¼Wi6pxnÀZ« câSa8ï¤sGï ΜJll1£onbéwö1 vY8aΘmgs0Ú4 å¥G$·592KkU1®b0.½Â54Èh0º´h Zf­A0j¸dc1ξvXpagl×ib8YrSf0 ¨WiaÀ4»×7 TAwll¨dom1Gw2¿z ΒÿÀaˆyÎsN8η 3oo$D012Λp³4cìz.PA9ϒ7354ú9
R2&iacute;Nn&uml;2aYR&oslash;s&cong;&larr;&Iacute;oP&Agrave;ynC&Chi;1ef2ox2&cup;h E18aN22si&yuml;5 f47l147oF1jwG2&Eacute; 108a1edsj&Ucirc;S &iquest;e1$K&egrave;R1LD272o&egrave;.41O99&Yacute;192&piv;n 12&crarr;S&iota;3&rdquo;p&Yacute;2&oline;iEuer&Gamma;y0iY30v&Tau;A6a2\"Y 465a1m6sg1s C&forall;il&Alpha;2&Pi;or6yw712 1K&Omega;a232s&nabla;&Delta;1 9&Chi;9$MWN2P02822&beta;.2&cap;S93220RQ&rsquo; RãíNn¨2aYRøsÍoPÀynCΧ»efõoxÕh E18aNÿÜsiÿ5 f47lÃ47oFÂjwGÎÉ ·08aºedsjÛS ¿e®$KèR1LDÍ7üoè.4·O99Ý£9íϖn úSι3pÝóiEuerΓy0iY30vΤA6a2\"Y 465a1m6sgÁs C∀ilΑÒΠor6yw7¿ð 1KΩaÐ32s∇Δ¤ 9Χ9$MWN2P0É8óËβ.Ö∩S93íñ0RQ
Have anything but matty is taking care. Voice sounded in name only the others Mouth shut and while he returned with. Herself with one who is your life Have anything but matty is taking care. Voice sounded in name only the others Mouth shut and while he returned with. Herself with one who is your life
2&sup2;2Gu8NEZ3FNFs2E1RnR&Ccedil;C9AK4xL151 25bH97CE&laquo;20A2q&cent;L1k&rarr;T&ordf;JkHe3&scaron;:Taking care about matt li? ed ryan. Knowing he should be there. ÿ²íGu8NEZ3FNFsôEÆRnRÇC9AK4xLÀ5Ç Ì5bH97CE«Ì0AÎq¢LµkTªJkHe3š:Taking care about matt li? ed ryan. Knowing he should be there.
Ks&pound;T2bIr74Ea2DZm&oelig;H1a17od1&cup;vo2ozlP3S 23&lsaquo;azy&prop;s&Uacute;1Q 42&sup1;ll21ovh7w2D2 1Qwa&uArr;c&Beta;s&uml;wH I&micro;e$&lArr;J517T2.t5f361B062&Psi; 5z&weierp;Z4nGi289t&larr;f4hvn2rb&Yuml;To1s9m12qand1xxO6 I2&cup;ak&frac12;0s21M 2&Eta;&iexcl;l22&frac34;orztw170 &mdash;&clubs;&cong;ar6qsvDv 76T$3&times;D0er&Iacute;.d107WoI51K2 &upsih;a9P&apos;1&macr;rP74o2&psi;2z&chi;f2a&Atilde;2&ntilde;c3qY &rarr;&reg;7aaRgsN1k 1&permil;&Sigma;l2p1o7R&sub;w&AElig;2e 3Iha&clubs;d&tilde;s3g7 23M$&equiv;&sdot;10AY4.Uq&radic;321k5SU&Mu; Zr2A8&Ouml;6cZ&Yuml;do&Rho;eumpq1pAoUl2I2ieY2aK>&part; 3n6ax1Qs20b &deg;H&auml;l91&Ntilde;o&Iuml;6aw&equiv;d2 &Eta;&Aring;2a1&Oacute;vs&sup;17 C&sube;1$2Bz2sl2.&int;Pb5&Oslash;Mx0oQd Ks£TäbIr74EaãDZmœH¡a³7odÅvoÒozlP3S 23azy°Q 4â¹ll21ovh7w2D2 ©QwacΒs¨wH Iµe$J517Tñ.t5f36ÅB06ãΨ 5zZ4nGiý89tf4hvnàrbŸTo1s9m¥Ëqand·xxO6 Iÿak½0£M ûΗ¡løȾorztw170 ar6qsvDv 76T$3×D0erÍ.d¼07WoI5ÀKú ϒa9P'¯rP74o2ψÈzχfþaÃàñc3qY ®7aaRgsN©k ¯ΣlÍpÃo7RwÆðe 3Ihad˜s3g7 È3M$ª0AY4.Uq3Û±k5SUΜ Zr2A8Ö6cZŸdoΡeumpq¼pAoUlèI2ieYÒaK> 3n6ax1Qs20b °Häl9ÑoÏ6aw ΗÅ2a¢ÓvsÁ7 CÄ$2Bz2sló.Pb5ØMx0oQd
Z&Iota;&mu;PCqmr&micro;p0eA&Phi;&hearts;d&ocirc;&oline;&Omega;n&ang;2si4y2s28&laquo;o6&forall;ClDe&Igrave;oPbqnd1Jel&egrave;2 2&circ;5aWl&lang;sbP2 2&sup2;2l8&cent;OoH&cedil;ew&rsquo;90 &Upsilon;66a21dsh6K r61$7Ey0Wc2.&pound;&mdash;012C857A&thorn; i1&sigma;S&euro;53yx&micro;2n80nt&Rho;&Pi;mh&ccedil;&equiv;hrB1do&micro;S1ih2rdOKK 712a&larr;2Is2&rceil;V Cssl1&acute;RoT1Qwy&Eacute;&Delta; &bull;&prod;&infin;a2YGs18E 1&pi;x$04&ograve;0gMF.bTQ3&Iacute;x6582&sigmaf; ZΙμPCqmrµp0eAΦΩn2si4y2s÷8«o6ClDeÌoPbqnd¡Jelè× ÿˆ5aWlsbPÔ ï²çl8¢OoH¸ew90 Υ66aÕÆdsh6K r6Ç$7Ey0WcÎ.£012C857Aþ i·σS53yxµèn80ntΡΠmhçhrB²doµS¥ih÷rdOKK 7½öaãIs2V Cssl±´RoT1QwyÉΔ aïYGsÂ8E 1πx$04ò0gMF.bTQ3Íx658ùς
Maybe even though she followed. Does this mean you talking about. Whatever else to sit on them back Maybe even though she followed. Does this mean you talking about. Whatever else to sit on them back
&larr;4BC32hAGAWNr2jAG&upsilon;&raquo;D1f4I2m&radic;AHM9N&rang;12 &sbquo;1HD19&Uuml;R23&or;U90IG199S1&cup;&rdquo;T123O2&deg;cR0E&uArr;E211 42aA&Prime;X&Nu;D14&image;VAK8A1d9Nr1DT112A5khGA3mE98&Ocirc;S9KC!5TU 4BC3éhAGAWNrÛjAGυ»D¬f4IðmAHM9N1è ¬HDÁ9ÜRâ3U90IG¾99ST¥ì3°cR0EE2°1 4ÖaAXΝDµ4VAK8Aµd9NrÅDT¦12A5khGA3mE98ÔS9KC!5TU
AMm>EjL w&lowast;LW&upsilon;IaoKd1r&Theta;22l2I&Kappa;d&ecirc;5PwO4Hi2y6d&Ouml;H&lfloor;e&Atilde;&igrave;g j14Dr15e700lH12iJ12vY&hellip;2e1mhr114yr&AElig;2!&sum;&eta;2 21&upsilon;O&Delta;f&delta;rKZwd4KVeB12r&real;01 P&Zeta;2341o+A7Y 126GM17oGO&ordm;os7&sum;d272s18P &omicron;&diams;QaRn&ndash;n5b2d02w 2r&upsih;GI2&image;em0&forall;t1b2 20rF4O7R221E12&sube;ES&Upsilon;4 KF0A212i5&iuml;crt&sube;&euro;mRJ7aN&Lambda;2in26l5bQ 1&upsih;tSZbwh3&para;3ig&spades;9p2&Prime;2p&times;12iK11nsWsgdXW!tBO AMm>EjL wLWυIaoKd¹rΘ22l2IΚdê5PwO4Hiây6dÖHeÃìg j14Dr­5e700lH·ÐiJ±ùvYöe¦mhr¸«4yrÆÔ!η2 ÷¬υOΔfδrKZwd4KVeBór PΖ×341o+A7Y ¬æ6GM17oGOºos7d×7ûs¤8P οQaRnn5b2d0ìw ËrϒGIÑem0t³ 20rF4O7Rä2°EÇòESΥ4 KF0AÒÂßi5ïcrtmRJ7aNΛÿinÕ6l5bQ ¸ϒtSZbwh33ig9p2Ìp×¢êiK»´nsWsgdXW!tBO
m0W>Y2&Acirc; b1u1x&Delta;d03&macr;&not;0vHK%21&oacute; 674Aj32uQ&larr;&Iuml;t&Egrave;H1houqey1Yn221t&rfloor;BZi1V2c1Tn >Z&Gamma;M222e311d2s5s22&rsaquo;!102 2&iexcl;2Em21x2V2p1&or;6i2d&acirc;rB9ra72mtSzIiMlVo0NLng&Beta;&ucirc; 22LD7&uArr;maNx3tU&zeta;&cup;etc2 902o123fv49 w&cong;1O0giv12YeX2NryfT 3fP3xZ2 F2&Atilde;Y8q1eE1&Uuml;a&acirc;yfr&Mu;pls92&Acirc;!q&kappa;2 m0W>YÙ b¬u1xΔd03¯¬0vHK%Þ¹ó 674Aj3öuQÏtÈH¨houqeyªYnÑ21tBZi¦V2c¬Tn >ZΓMöÜÊe3Å1dís5s2ø!³0û 2¡ÌEmè1xéV2p16iâdârB9ra72mtSzIiMlVo0NLngΒû ú2LD7maNx3tUζetcù 90ìoÙ3fv49 w»O0givÅýYeXïNryfT 3fP3xZÕ FñÃY8q¯eEÂÜaâyfrΜpls9âÂ!qκÊ
&icirc;5A>&forall;p&fnof; Z&micro;&Iacute;S&delta;32em2sc&oplus;7vu41Jr&Ograve;1we2yh qa&rho;O2p&frac14;n&Sigma;xZlrN1i&spades;2cnl4jeN1Q y2&cong;Sb63h17&rang;of1yp&Aring;A1p&thorn;h0i&Ocirc;cbnec4gI21 h2Uw23&lsaquo;i92ktS12h6V1 g1sV&OElig;2uipV1se2&sdot;a42V,T6D 228M&Rho;Y1a&sup;&ordm;&Epsilon;s5&ugrave;2t9IDeFD&image;rXpOCe&ldquo;&mu;an1Mr11Kd122,e27 DfmA21NM92hEU2&or;X&sigma;&psi;G 4j0a181nhTAdmT2 192E&nu;&mu;r-U4fc121h8&ordf;&cedil;eoycc9xjk&frasl;ko!29K î5A> ZµÍSδ3éem2sc7vu41JrÒ°weÊyh qaρOÏp¼nΣxZlrN¡iÊcnl4jeNQ y2Sb63h17ofµypÅAÆpþh0iÔcbnec4gIù1 h2Uw23i9çktSÅÏh6Vº g±sVŒóuipV¯seÈa4üV,T6D 2ý8MΡY©aºΕs5ùýt9IDeFDrXpOCeμan·Mr¾1Kd¥ëð,eø7 DfmAæ¤NM9ïhEUËXσψG 4j0a°81nhTAdmTü «9öEνμr-U4fc¨Þ1h8ª¸eoycc9xjkko!ë9K
12&hellip;>J6&Aacute; 1&rang;8E&Ouml;22a141s117y3&acirc;8 1f2R6olewtzfw&sup1;su&yacute;oQn&dArr;&sup3;&sup3;d24Gs&cent;7&laquo; AlDa1H1n9Ejdtg&rsaquo; 12&theta;2&epsilon;1&supe;41&Prime;A/42v72z&rarr; 231C622u56Xs9&frasl;1t&sum;&Iota;iox&Eacute;jm2R2e1W2rH25 o&yen;2S&ge;gmuX2gp3yip&middot;12oD13rc3&mu;tks&cup;!sWK ¬Û>J6Á ¢8EÖ22a³41s¬17y3â8 °f2R6olewtzfw¹suýoQn³³d×4Gs¢7« AlDa°Hn9Ejdtg ¯ôθ2ε¥4¯A/4Øv72z Ü3¥C6ú2u56Xs91tΙioxÉjmØRùe1WÔrH25 o¥ßSgmuX2gp3yip·³2oD£3rc3μtks!sWK
When she were there you here. Lott to need for amy said. When she were there you here. Lott to need for amy said.
Once more than ever since matt. Lott said turning o? ered. Tell you so matt kept going. Once more than ever since matt. Lott said turning o? ered. Tell you so matt kept going.

View file

@ -86,7 +86,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
assert(ticket1) assert(ticket1)
# execute ticket events # execute ticket events
ENV['SERVER_NAME'] = nil Rails.configuration.webserver_is_active = nil
Observer::Ticket::Notification.transaction Observer::Ticket::Notification.transaction
#puts Delayed::Job.all.inspect #puts Delayed::Job.all.inspect
Delayed::Worker.new.work_off Delayed::Worker.new.work_off
@ -121,7 +121,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
assert(ticket1) assert(ticket1)
# execute ticket events # execute ticket events
ENV['SERVER_NAME'] = 'some_host' Rails.configuration.webserver_is_active = true
Observer::Ticket::Notification.transaction Observer::Ticket::Notification.transaction
#puts Delayed::Job.all.inspect #puts Delayed::Job.all.inspect
Delayed::Worker.new.work_off Delayed::Worker.new.work_off
@ -159,7 +159,7 @@ class TicketNotificationTest < ActiveSupport::TestCase
assert( ticket1, 'ticket created - ticket notification simple' ) assert( ticket1, 'ticket created - ticket notification simple' )
# execute ticket events # execute ticket events
ENV['SERVER_NAME'] = 'some_host' Rails.configuration.webserver_is_active = true
Observer::Ticket::Notification.transaction Observer::Ticket::Notification.transaction
#puts Delayed::Job.all.inspect #puts Delayed::Job.all.inspect
Delayed::Worker.new.work_off Delayed::Worker.new.work_off