Improved unit tests, merged html2ascii to html2text.

This commit is contained in:
Martin Edenhofer 2015-01-08 15:27:44 +01:00
parent 62fedc8fbd
commit a9836b5586
8 changed files with 406 additions and 339 deletions

View file

@ -133,7 +133,7 @@ class Channel::EmailParser
filename = 'message.html'
data[:body] = mail.html_part.body.to_s
data[:body] = Encode.conv( mail.html_part.charset.to_s, data[:body] )
data[:body] = html2ascii( data[:body] ).to_s.force_encoding('utf-8')
data[:body] = data[:body].html2text.to_s.force_encoding('utf-8')
if !data[:body].valid_encoding?
data[:body] = data[:body].encode('utf-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '?')
@ -199,7 +199,7 @@ class Channel::EmailParser
filename = 'message.html'
data[:body] = mail.body.decoded
data[:body] = Encode.conv( mail.charset, data[:body] )
data[:body] = html2ascii( data[:body] ).to_s.force_encoding('utf-8')
data[:body] = data[:body].html2text.to_s.force_encoding('utf-8')
if !data[:body].valid_encoding?
data[:body] = data[:body].encode('utf-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '?')
@ -349,7 +349,7 @@ class Channel::EmailParser
# reset current_user
UserInfo.current_user_id = 1
# create sender
if mail[ 'x-zammad-customer-login'.to_sym ]
user = User.where( :login => mail[ 'x-zammad-customer-login'.to_sym ] ).first
end
@ -358,20 +358,28 @@ class Channel::EmailParser
end
if !user
puts 'create user...'
roles = Role.where( :name => 'Customer' )
user = User.create(
user = user_create(
:login => mail[ 'x-zammad-customer-login'.to_sym ] || mail[ 'x-zammad-customer-email'.to_sym ] || mail[:from_email],
:firstname => mail[ 'x-zammad-customer-firstname'.to_sym ] || mail[:from_display_name],
:lastname => mail[ 'x-zammad-customer-lastname'.to_sym ],
:email => mail[ 'x-zammad-customer-email'.to_sym ] || mail[:from_email],
:password => '',
:active => true,
:roles => roles,
:updated_by_id => 1,
:created_by_id => 1,
)
end
# create to and cc user
['to', 'cc'].each { |item|
if mail[item.to_sym]
items = Mail::AddressList.new( mail[item.to_sym] )
items.addresses.each {|item|
user_create(
:firstname => item.display_name,
:lastname => '',
:email => item.address,
)
}
end
}
# set current user
UserInfo.current_user_id = user.id
@ -479,6 +487,35 @@ class Channel::EmailParser
return ticket, article, user
end
def user_create(data)
# return existing
user = User.where( :login => data[:email].downcase ).first
return user if user
# create new user
roles = Role.where( :name => 'Customer' )
# fillup
['firstname', 'lastname'].each { |item|
if data[item.to_sym] == nil
data[item.to_sym] = ''
end
}
data[:password] = ''
data[:active] = true
data[:roles] = roles
data[:updated_by_id] = 1
data[:created_by_id] = 1
user = User.create(data)
user.update_attributes(
:updated_by_id => user.id,
:created_by_id => user.id,
)
user
end
def set_attributes_by_x_headers( item_object, header_name, mail )
# loop all x-zammad-hedaer-* headers
@ -525,85 +562,6 @@ class Channel::EmailParser
}
end
def html2ascii(string)
# in case of invalid encodeing, strip invalid chars
# see also test/fixtures/mail21.box
# note: string.encode!('UTF-8', 'UTF-8', :invalid => :replace, :replace => '?') was not detecting invalid chars
if !string.valid_encoding?
string = string.chars.select { |c| c.valid_encoding? }.join
end
# find <a href=....> and replace it with [x]
link_list = ''
counter = 0
string.gsub!( /<a\s.*?href=("|')(.+?)("|').*?>/ix ) { |item|
link = $2
counter = counter + 1
link_list += "[#{counter}] #{link}\n"
"[#{counter}]"
}
# remove empty lines
string.gsub!( /^\s*/m, '' )
# fix some bad stuff from opera and others
string.gsub!( /(\n\r|\r\r\n|\r\n)/, "\n" )
# strip all other tags
string.gsub!( /\<(br|br\/|br\s\/)\>/, "\n" )
# strip all other tags
string.gsub!( /\<.+?\>/, '' )
# strip all &amp; &lt; &gt; &quot;
string.gsub!( '&amp;', '&' )
string.gsub!( '&lt;', '<' )
string.gsub!( '&gt;', '>' )
string.gsub!( '&quot;', '"' )
# encode html entities like "&#8211;"
string.gsub!( /(&\#(\d+);?)/x ) { |item|
$2.chr
}
# encode html entities like "&#3d;"
string.gsub!( /(&\#[xX]([0-9a-fA-F]+);?)/x ) { |item|
chr_orig = $1
hex = $2.hex
if hex
chr = hex.chr
if chr
chr_orig = chr
else
chr_orig
end
else
chr_orig
end
# check valid encoding
begin
if !chr_orig.encode('UTF-8').valid_encoding?
chr_orig = '?'
end
rescue
chr_orig = '?'
end
chr_orig
}
# remove empty lines
string.gsub!( /^\s*\n\s*\n/m, "\n" )
# add extracted links
if link_list
string += "\n\n" + link_list
end
return string
end
end
# workaround to parse subjects with 2 different encodings correctly (e. g. quoted-printable see test/fixtures/mail9.box)

View file

@ -86,10 +86,10 @@ returns
def fullname
fullname = ''
if self.firstname
if self.firstname && !self.firstname.empty?
fullname = fullname + self.firstname
end
if self.lastname
if self.lastname && !self.lastname.empty?
if fullname != ''
fullname = fullname + ' '
end
@ -414,26 +414,38 @@ returns
scan = self.firstname.scan(/, /)
if scan[0]
name = self.firstname.split(', ', 2)
if name[0] != nil
self.lastname = name[0]
end
if name[1] != nil
self.firstname = name[1]
end
return
end
# Firstname Lastname
name = self.firstname.split(' ', 2)
if name[0] != nil
self.firstname = name[0]
end
if name[1] != nil
self.lastname = name[1]
end
return
# -no name- firstname.lastname@example.com
elsif ( !self.firstname || self.firstname.empty? ) && ( !self.lastname || self.lastname.empty? ) && ( self.email && !self.email.empty? )
scan = self.email.scan(/^(.+?)\.(.+?)\@.+?$/)
if scan[0]
if scan[0][0] != nil
self.firstname = scan[0][0].capitalize
end
if scan[0][1] != nil
self.lastname = scan[0][1].capitalize
end
end
end
end
def check_email
if self.email

View file

@ -12,24 +12,24 @@ class CreateBase < ActiveRecord::Migration
create_table :users do |t|
t.references :organization, :null => true
t.column :login, :string, :limit => 100, :null => false
t.column :firstname, :string, :limit => 100, :null => true
t.column :lastname, :string, :limit => 100, :null => true
t.column :email, :string, :limit => 140, :null => true
t.column :firstname, :string, :limit => 100, :null => true, :default => ''
t.column :lastname, :string, :limit => 100, :null => true, :default => ''
t.column :email, :string, :limit => 140, :null => true, :default => ''
t.column :image, :string, :limit => 100, :null => true
t.column :image_source, :string, :limit => 200, :null => true
t.column :web, :string, :limit => 100, :null => true
t.column :web, :string, :limit => 100, :null => true, :default => ''
t.column :password, :string, :limit => 100, :null => true
t.column :phone, :string, :limit => 100, :null => true
t.column :fax, :string, :limit => 100, :null => true
t.column :mobile, :string, :limit => 100, :null => true
t.column :department, :string, :limit => 200, :null => true
t.column :street, :string, :limit => 120, :null => true
t.column :zip, :string, :limit => 100, :null => true
t.column :city, :string, :limit => 100, :null => true
t.column :country, :string, :limit => 100, :null => true
t.column :phone, :string, :limit => 100, :null => true, :default => ''
t.column :fax, :string, :limit => 100, :null => true, :default => ''
t.column :mobile, :string, :limit => 100, :null => true, :default => ''
t.column :department, :string, :limit => 200, :null => true, :default => ''
t.column :street, :string, :limit => 120, :null => true, :default => ''
t.column :zip, :string, :limit => 100, :null => true, :default => ''
t.column :city, :string, :limit => 100, :null => true, :default => ''
t.column :country, :string, :limit => 100, :null => true, :default => ''
t.column :verified, :boolean, :null => false, :default => false
t.column :active, :boolean, :null => false, :default => true
t.column :note, :string, :limit => 250, :null => true
t.column :note, :string, :limit => 250, :null => true, :default => ''
t.column :last_login, :timestamp, :null => true
t.column :source, :string, :limit => 200, :null => true
t.column :login_failed, :integer, :null => false, :default => 0
@ -104,7 +104,7 @@ class CreateBase < ActiveRecord::Migration
t.column :name, :string, :limit => 100, :null => false
t.column :shared, :boolean, :null => false, :default => true
t.column :active, :boolean, :null => false, :default => true
t.column :note, :string, :limit => 250, :null => true
t.column :note, :string, :limit => 250, :null => true, :default => ''
t.column :updated_by_id, :integer, :null => false
t.column :created_by_id, :integer, :null => false
t.timestamps

View file

@ -45,37 +45,111 @@ class String
=end
# base from https://gist.github.com/petrblaho/657856
def html2text
text = self.
gsub(/(&nbsp;|\n|\s)+/im, ' ').squeeze(' ').strip.
gsub(/<([^\s]+)[^>]*(src|href)=\s*(.?)([^>\s]*)\3[^>]*>\4<\/\1>/i, '\4')
string = self
links = []
linkregex = /<[^>]*(src|href)=\s*(.?)([^>\s]*)\2[^>]*>\s*/i
while linkregex.match(text)
links << $~[3]
text.sub!(linkregex, "[#{links.size}]")
# in case of invalid encodeing, strip invalid chars
# see also test/fixtures/mail21.box
# note: string.encode!('UTF-8', 'UTF-8', :invalid => :replace, :replace => '?') was not detecting invalid chars
if !string.valid_encoding?
string = string.chars.select { |c| c.valid_encoding? }.join
end
text = CGI.unescapeHTML(
text.
gsub(/<(script|style)[^>]*>.*<\/\1>/im, '').
gsub(/<!--.*-->/m, '').
gsub(/<hr(| [^>]*)>/i, "___\n").
gsub(/<li(| [^>]*)>/i, "\n* ").
gsub(/<blockquote(| [^>]*)>/i, '> ').
gsub(/<(br)(|\/| [^>]*)>/i, "\n").
gsub(/<\/div(| [^>]*)>/i, "\n").
gsub(/<(\/h[\d]+|p)(| [^>]*)>/i, "\n\n").
gsub(/<[^>]*>/, '')
).lstrip.gsub(/\n[ ]+/, "\n") + "\n"
# find <a href=....> and replace it with [x]
link_list = ''
counter = 0
string.gsub!( /<a\s.*?href=("|')(.+?)("|').*?>/ix ) { |item|
link = $2
counter = counter + 1
link_list += "[#{counter}] #{link}\n"
"[#{counter}] "
}
for i in (0...links.size).to_a
text = text + "\n [#{i+1}] <#{CGI.unescapeHTML(links[i])}>" unless links[i].nil?
# remove empty lines
string.gsub!( /^\s*/m, '' )
# pre/code handling 1/2
string.gsub!( /<pre>(.+?)<\/pre>/m ) { |placeholder|
placeholder = placeholder.gsub(/\n/, "###BR###")
}
string.gsub!( /<code>(.+?)<\/code>/m ) { |placeholder|
placeholder = placeholder.gsub(/\n/, "###BR###")
}
# remove all new lines
string.gsub!( /(\n\r|\r\r\n|\r\n|\n)/, '' )
# pre/code handling 2/2
string.gsub!( /###BR###/, "\n" )
# add counting
string.gsub!(/<li(| [^>]*)>/i, "\n* ")
# add quoting
string.gsub!(/<blockquote(| [^>]*)>/i, '> ')
# add hr
string.gsub!(/<hr(|\/| [^>]*)>/i, "___\n")
# add new lines
string.gsub!( /\<(br|table)(|\/| [^>]*)\>/i, "\n" )
string.gsub!( /\<\/(div|p|pre|blockquote|table|tr)(|\s.+?)\>/i, "\n" )
string.gsub!( /\<\/td\>/i, ' ' )
# strip all other tags
string.gsub!( /\<.+?\>/, '' )
# strip all &amp; &lt; &gt; &quot;
string.gsub!( '&amp;', '&' )
string.gsub!( '&lt;', '<' )
string.gsub!( '&gt;', '>' )
string.gsub!( '&quot;', '"' )
string.gsub!( '&nbsp;', ' ' )
# encode html entities like "&#8211;"
string.gsub!( /(&\#(\d+);?)/x ) { |item|
$2.chr
}
# encode html entities like "&#3d;"
string.gsub!( /(&\#[xX]([0-9a-fA-F]+);?)/x ) { |item|
chr_orig = $1
hex = $2.hex
if hex
chr = hex.chr
if chr
chr_orig = chr
else
chr_orig
end
links = nil
text.chomp
else
chr_orig
end
# check valid encoding
begin
if !chr_orig.encode('UTF-8').valid_encoding?
chr_orig = '?'
end
rescue
chr_orig = '?'
end
chr_orig
}
# remove tailing empty spaces
string.gsub!(/\s+\n$/, "\n")
# remove multible empty lines
string.gsub!(/\n\n\n/, "\n\n")
# add extracted links
if link_list != ''
string += "\n\n" + link_list
end
string.strip
end
=begin

View file

@ -52,8 +52,7 @@ class EmailBuildTest < ActiveSupport::TestCase
should = '> Welcome!
>
> Thank you for installing Zammad. äöüß
>
'
>'
assert_equal( should, mail.text_part.body.to_s )
assert_equal( html, mail.html_part.body.to_s )
@ -90,8 +89,7 @@ class EmailBuildTest < ActiveSupport::TestCase
text = '> Welcome!
>
> Thank you for installing Zammad. äöüß
>
'
>'
mail = Channel::EmailBuild.build(
:from => 'sender@example.com',
:to => 'recipient@example.com',
@ -108,8 +106,7 @@ class EmailBuildTest < ActiveSupport::TestCase
should = '> Welcome!
>
> Thank you for installing Zammad. äöüß
>
'
>'
assert_equal( should, mail.text_part.body.to_s )
assert_equal( nil, mail.html_part )
@ -141,8 +138,7 @@ class EmailBuildTest < ActiveSupport::TestCase
text = '> Welcome!
>
> Thank you for installing Zammad. äöüß
>
'
>'
mail = Channel::EmailBuild.build(
:from => 'sender@example.com',
:to => 'recipient@example.com',
@ -152,8 +148,7 @@ class EmailBuildTest < ActiveSupport::TestCase
should = '> Welcome!
>
> Thank you for installing Zammad. äöüß
>
'
>'
assert_equal( should, mail.body.to_s )
assert_equal( nil, mail.html_part )
@ -169,22 +164,63 @@ class EmailBuildTest < ActiveSupport::TestCase
end
test 'html2text' do
html = '<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">
<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad.</div><div>&gt;</div>
</body>
</html>'
should = '> Welcome!
>
> Thank you for installing Zammad.
>
'
assert_equal( should, html.html2text )
html = 'test'
result = 'test'
assert_equal( result, html.html2text )
html = ' test '
result = 'test'
assert_equal( result, html.html2text )
html = "\n\n test \n\n\n"
result = 'test'
assert_equal( result, html.html2text )
html = '<div>test</div>'
result = 'test'
assert_equal( result, html.html2text )
html = '<div>test<br></div>'
result = 'test'
assert_equal( result, html.html2text )
html = "<div>test<br><br><br>\n<br>\n<br>\n</div>"
result = 'test'
assert_equal( result, html.html2text )
html = "<pre>test\n\ntest</pre>"
result = "test\ntest"
assert_equal( result, html.html2text )
html = "<code>test\n\ntest</code>"
result = "test\ntest"
assert_equal( result, html.html2text )
html = "<table><tr><td>test</td><td>col</td></td></tr><tr><td>test</td><td>4711</td></tr></table>"
result = "test col \ntest 4711"
assert_equal( result, html.html2text )
html = "<!-- some comment -->
<div>
test<br><br><br>\n<br>\n<br>\n
</div>"
result = 'test'
assert_equal( result, html.html2text )
html = "\n<div><a href=\"http://zammad.org\">Best Tool of the World</a>
some other text</div>
<div>"
result = "[1] Best Tool of the Worldsome other text\n\n\n[1] http://zammad.org"
assert_equal( result, html.html2text )
html = "<!-- some comment -->
<div>
test<br><br><br>\n<hr/>\n<br>\n
</div>"
result = "test\n\n___"
assert_equal( result, html.html2text )
html = ' line&nbsp;1<br>
you<br/>
@ -200,5 +236,20 @@ you
* #2'
assert_equal( should, html.html2text )
html = '<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">
<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad.</div><div>&gt;</div>
</body>
</html>'
should = '> Welcome!
>
> Thank you for installing Zammad.
>'
assert_equal( should, html.html2text )
end
end

View file

@ -85,46 +85,49 @@ Liebe Grüße!
},
{
:data => IO.read('test/fixtures/mail6.box'),
:body_md5 => '88c0c9e004021a4ed2a0c1e5f6b3455d',
:body_md5 => 'cc60217317756f45a6e02829c0a8c49c',
:params => {
:from => '"Hans BÄKOSchönland" <me@bogen.net>',
:from_email => 'me@bogen.net',
:from_display_name => 'Hans BÄKOSchönland',
:subject => 'utf8: 使って / ISO-8859-1: Priorität" / cp-1251: Сергей Углицких',
:body => "this is a test [1]Compare Cable, DSL or Satellite plans: As low as $2.95.
:body => "this is a test
___
[1] Compare Cable, DSL or Satellite plans: As low as $2.95.
Test1:8
Test2:&
Test3:&ni;
Test4:&
Test5:=
[1] http://localhost/8HMZENUS/2737??PS=
"
[1] http://localhost/8HMZENUS/2737??PS="
},
},
{
:data => IO.read('test/fixtures/mail7.box'),
:body_md5 => '6029e6b6106a6dd11ed887ec31f118ac',
:body_md5 => 'c78f6a91905538ee32bc0bf71f70fcf2',
:params => {
:from => 'Eike.Ehringer@example.com',
:from_email => 'Eike.Ehringer@example.com',
:from_display_name => '',
:subject => 'AW:Installation [Ticket#11392]',
:body_md5 => "Hallo.
:body => "Hallo.
Jetzt muss ich dir noch kurzfristig absagen für morgen.
Lass uns evtl morgen Tel.
Mfg eike
Martin Edenhofer via Znuny Team --- Installation [Ticket#11392] ---
Von:\"Martin Edenhofer via Znuny Team\" <support@example.com>Aneike.xx@xx-corpxx.comDatum:Mi., 13.06.2012 14:30BetreffInstallation [Ticket#11392]
Von: \"Martin Edenhofer via Znuny Team\" <support@example.com>
An eike.xx@xx-corpxx.com
Datum: Mi., 13.06.2012 14:30
Betreff Installation [Ticket#11392]
___
Hi Eike,
anbei wie gestern telefonisch besprochen Informationen zur Vorbereitung.
a) Installation von http://ftp.gwdg.de/pub/misc/zammad/RPMS/fedora/4/zammad-3.0.13-01.noarch.rpm (dieses RPM ist RHEL kompatible) und dessen Abhängigkeiten.
@ -139,10 +142,7 @@ P: +49 (0) 30 60 98 54 18-0
F: +49 (0) 30 60 98 54 18-8
W: http://example.com
Location: Berlin - HRB 139852 B Amtsgericht Berlin-Charlottenburg
Managing Director: Martin Edenhofer
",
Managing Director: Martin Edenhofer",
},
},
{
@ -326,7 +326,7 @@ Hof
# spam email
{
:data => IO.read('test/fixtures/mail16.box'),
:body_md5 => 'b255fb5620db3b63131924513061d974',
:body_md5 => 'a2367adfa77857a078dad83826d659e8',
:params => {
:from => nil,
:from_email => 'vipyimin@126.com',
@ -360,7 +360,7 @@ Hof
},
{
:data => IO.read('test/fixtures/mail19.box'),
:body_md5 => '2fa47e9122f4c1b9c5057400529c7567',
:body_md5 => '3e42be74f967379a3053f21f4125ca66',
:params => {
:from => '"我" <>',
:from_email => '"=?GB2312?B?ztI=?=" <>',
@ -371,7 +371,7 @@ Hof
},
{
:data => IO.read('test/fixtures/mail20.box'),
:body_md5 => 'd2b65203aaf2bbbd50fc73cb14d781bc',
:body_md5 => '65ca1367dfc26abcf49d30f68098f122',
:params => {
:from => 'Health and Care-Mall <drugs-cheapest8@sicor.com>',
:from_email => 'drugs-cheapest8@sicor.com',
@ -381,71 +381,37 @@ Hof
: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.
2&gamma;&dArr;B[1]cwspC&ensp;L8I&nbsp;C&nbsp;K88H E1R?E2e31 !Calm dylan for school today.
2&gamma;&dArr;B[1] cwspC&ensp;L8I C K88H E1R?E2e31 !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.
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
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
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
&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
Please matt on his neck. Okay matt huï ed into your mind
Since her head to check dylan. Where dylan matt got up there
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
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
&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
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.
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
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
What made no one in each time.
Mommy was thinking of course beth. Everything you need the same thing
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
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
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;:
&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
&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
Turning to mess up with. Well that to give her face
Another for what she found it then. Since the best to hear
&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
&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
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
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
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
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
&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
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.
[1] http://pxmzcgy.storeprescription.ru?zz=fkxffti
"
[1] http://pxmzcgy.storeprescription.ru?zz=fkxffti"
},
},
{
:data => IO.read('test/fixtures/mail21.box'),
:body_md5 => 'a232a7b7b29d20950b9f7b748137ba9d',
:body_md5 => 'f909a17fde261099903f3236f8755249',
:params => {
:from => 'Viagra Super Force Online <pharmacy_affordable1@ertelecom.ru>',
:from_email => 'pharmacy_affordable1@ertelecom.ru',
@ -456,7 +422,7 @@ Wade to give it seemed like this. Yeah but one for any longer. Everything you go
},
{
:data => IO.read('test/fixtures/mail22.box'),
:body_md5 => '57cf207fb52f01f107ae008eb2f8d6cc',
:body_md5 => '9e79cb133d52afe9e18e8438df539305',
:params => {
:from => 'Gilbertina Suthar <ireoniqla@lipetsk.ru>',
:from_email => 'ireoniqla@lipetsk.ru',
@ -470,16 +436,15 @@ Thinking of bed and whenever adam.
Mike was too tired man to hear.I10PQSHEJl2Nwf&tilde;2113S173 &Icirc;1mEbb5N371L&piv;C7AlFnR1&diams;HG64B242&brvbar;M2242zk&Iota;N&rceil;7&rceil;TBN&ETH; T2xPI&ograve;gI2&Atilde;lL2&Otilde;ML&perp;22Sa&Psi;RBreathed adam gave the master bedroom door.
Better get charlie took the wall.
Charlotte clark smile he saw charlie.
Dave and leaned her tears adam.Maybe we want any help me that.
Dave and leaned her tears adam.
Maybe we want any help me that.
Next morning charlie gazed at their father.
Well as though adam took out here. Melvin will be more money. Called him into this one last night.
Men joined the pickup truck pulled away. Chuck could make sure that.[1] &dagger;p1C?L&thinsp;I?C&ensp;K?88&ensp;5 E R?EEOD !Chuckled adam leaned forward and le? charlie.
Just then returned to believe it here.
Freemont and pulling out several minutes.
[1] &#104;&#116;&#116;&#112;&#58;&#47;&#47;&#1072;&#1086;&#1089;&#1082;&#46;&#1088;&#1092;?jmlfwnwe&ucwkiyyc
",
[1] &#104;&#116;&#116;&#112;&#58;&#47;&#47;&#1072;&#1086;&#1089;&#1082;&#46;&#1088;&#1092;?jmlfwnwe&ucwkiyyc",
},
},
@ -565,14 +530,14 @@ gate GmbH * Gladbacher Str. 74 * 40219 Düsseldorf
},
{
:data => IO.read('test/fixtures/mail27.box'),
:body_md5 => 'e1c06d85ae7b8b032bef47e42e4c08f9',
:body_md5 => 'd41d8cd98f00b204e9800998ecf8427e',
:params => {
:from => 'caoyaoewfzfw@21cn.com',
:from_email => 'caoyaoewfzfw@21cn.com',
:from_display_name => "",
:subject => "\r\n蠭龕中層管理者如何避免角色行为誤区",
:to => 'duan@seat.com.cn, info@znuny.com, jinzh@kingdream.com',
:body => "\n\n",
:body => "",
},
:attachments => [
{
@ -609,8 +574,10 @@ gate GmbH * Gladbacher Str. 74 * 40219 Düsseldorf
parser = Channel::EmailParser.new
data = parser.parse( file[:data] )
#puts '++' + data[:body].to_s + '++'
# check body
md5 = Digest::MD5.hexdigest( data[:body] )
#puts "IS #{md5} / should #{file[:body_md5]}"
assert_equal( file[:body_md5], md5 )
# check params

View file

@ -138,77 +138,43 @@ Some Text",
:title => 'World Best DRUGS Mall For a Reasonable Price.',
},
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
86&Euml;[1]2u2C&nbsp;L&nbsp;I C1K&nbsp;&nbsp;&nbsp;H E&nbsp;R E28MLuke had been thinking about that.
86&Euml;[1] 2u2C L I C1K 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.
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:
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
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
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
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.
&aacute;&bull;XMY2&Aring;EE12N&deg;kP'd&Auml;1S4&rceil;d &radic;p&uml;H&Sigma;>jE4y4AC22L2&ldquo;vT&and;4tHX1X:
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
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
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
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:
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
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;
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
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
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;
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.
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
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;
Maybe even though she followed.
Does this mean you talking about. Whatever else to sit on them back
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
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;
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
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
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
&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
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
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.
Homegrown dandelions by herself into her lips. Such an excuse to stop thinking about. Leave us and be right.
[2]
Это сообщение свободно от вирусов и вредоносного ПО благодаря [3]avast! Antivirus защита активна.
___
[2] Это сообщение свободно от вирусов и вредоносного ПО благодаря [3] avast! Antivirus защита активна.
[1] http://piufup.medicatingsafemart.ru
[2] http://www.avast.com/
[3] http://www.avast.com/
',
[3] http://www.avast.com/",
:sender => 'Customer',
:type => 'email',
:internal => false,
@ -231,16 +197,15 @@ Thinking of bed and whenever adam.
Mike was too tired man to hear.I10PQSHEJl2Nwf&tilde;2113S173 &Icirc;1mEbb5N371L&piv;C7AlFnR1&diams;HG64B242&brvbar;M2242zk&Iota;N&rceil;7&rceil;TBN&ETH; T2xPI&ograve;gI2&Atilde;lL2&Otilde;ML&perp;22Sa&Psi;RBreathed adam gave the master bedroom door.
Better get charlie took the wall.
Charlotte clark smile he saw charlie.
Dave and leaned her tears adam.Maybe we want any help me that.
Dave and leaned her tears adam.
Maybe we want any help me that.
Next morning charlie gazed at their father.
Well as though adam took out here. Melvin will be more money. Called him into this one last night.
Men joined the pickup truck pulled away. Chuck could make sure that.[1] &dagger;p1C?L&thinsp;I?C&ensp;K?88&ensp;5 E R?EEOD !Chuckled adam leaned forward and le? charlie.
Just then returned to believe it here.
Freemont and pulling out several minutes.
[1] &#104;&#116;&#116;&#112;&#58;&#47;&#47;&#1072;&#1086;&#1089;&#1082;&#46;&#1088;&#1092;?jmlfwnwe&ucwkiyyc
",
[1] &#104;&#116;&#116;&#112;&#58;&#47;&#47;&#1072;&#1086;&#1089;&#1082;&#46;&#1088;&#1092;?jmlfwnwe&ucwkiyyc",
:sender => 'Customer',
:type => 'email',
:internal => false,
@ -2007,8 +1972,8 @@ Some Text',
},
},
{
:data => 'From: somebody@example.com
To: bod@example.com
:data => 'From: Some Body <somebody@example.com>
To: Bob <bod@example.com>
Cc: any@example.com
Subject: some subject
@ -2027,6 +1992,27 @@ Some Text',
:internal => true,
},
},
:verify => {
:users => [
{
:firstname => 'Some',
:lastname => 'Body',
:email => 'somebody@example.com',
},
{
:firstname => 'Bob',
:lastname => '',
:fullname => 'Bob',
:email => 'bod@example.com',
},
{
:firstname => '',
:lastname => '',
:email => 'any@example.com',
:fullname => 'any@example.com',
},
],
}
},
]
process(files)
@ -2053,6 +2039,25 @@ Some Text',
end
}
end
if file[:verify]
# verify if users are created
if file[:verify][:users]
file[:verify][:users].each { |user_result|
user = User.where(:email => user_result[:email]).first
if !user
assert( false, "No user '#{user_result[:email]}' found!" )
return
end
user_result.each { |key,value|
if user.respond_to?( key )
assert_equal( value, user.send(key), "user check #{ key }" )
else
assert_equal( value, user[key], "user check #{ key }" )
end
}
}
end
end
else
assert( false, 'ticket not created', file )
end

View file

@ -45,7 +45,7 @@ class UserTest < ActiveSupport::TestCase
:name => '#3 - simple create - nil as lastname',
:create => {
:firstname => 'Firstname Lastname',
:lastname => nil,
:lastname => '',
:email => 'some@example.com',
:login => 'some@example.com',
:updated_by_id => 1,
@ -114,8 +114,8 @@ class UserTest < ActiveSupport::TestCase
{
:name => '#7 - simple create - nill as fristname and lastname',
:create => {
:firstname => nil,
:lastname => nil,
:firstname => '',
:lastname => '',
:email => 'FIRSTNAME.lastname@example.com',
:login => 'login-3',
:updated_by_id => 1,