Browse Source

Improved unit tests, merged html2ascii to html2text.

Martin Edenhofer 10 years ago
parent
commit
a9836b5586

+ 66 - 108
app/models/channel/email_parser.rb

@@ -12,17 +12,17 @@ class Channel::EmailParser
   mail = parse( msg_as_string )
 
   mail = {
-    :from               => 'Some Name <some@example.com>',
-    :from_email         => 'some@example.com',
-    :from_local         => 'some',
-    :from_domain        => 'example.com',
-    :from_display_name  => 'Some Name',
-    :message_id         => 'some_message_id@example.com',
-    :to                 => 'Some System <system@example.com>',
-    :cc                 => 'Somebody <somebody@example.com>',
-    :subject            => 'some message subject',
-    :body               => 'some message body',
-    :attachments        => [
+    :from              => 'Some Name <some@example.com>',
+    :from_email        => 'some@example.com',
+    :from_local        => 'some',
+    :from_domain       => 'example.com',
+    :from_display_name => 'Some Name',
+    :message_id        => 'some_message_id@example.com',
+    :to                => 'Some System <system@example.com>',
+    :cc                => 'Somebody <somebody@example.com>',
+    :subject           => 'some message subject',
+    :body              => 'some message body',
+    :attachments       => [
       {
         :data        => 'binary of attachment',
         :filename    => 'file_name_of_attachment.txt',
@@ -50,9 +50,9 @@ class Channel::EmailParser
     :x-zammad-ticket-owner    => 'some_owner_login',
 
     # article headers
-    :x-zammad-article-internal   => false,
-    :x-zammad-article-type       => 'agent',
-    :x-zammad-article-sender     => 'customer',
+    :x-zammad-article-internal => false,
+    :x-zammad-article-type     => 'agent',
+    :x-zammad-article-sender   => 'customer',
 
     # all other email headers
     :some-header => 'some_value',
@@ -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(
-          :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,
+        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],
         )
       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)
@@ -642,4 +600,4 @@ module Mail
       end.join("")
     end
   end
-end
+end

+ 25 - 13
app/models/user.rb

@@ -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
@@ -132,16 +132,16 @@ returns
 
   result = [
     {
-      :id            =>2,
-      :o_id          =>2,
+      :id            => 2,
+      :o_id          => 2,
       :created_by_id => 3,
       :created_at    => '2013-09-28 00:57:21',
       :object        => "User",
       :type          => "created",
     },
     {
-      :id            =>2,
-      :o_id          =>2,
+      :id            => 2,
+      :o_id          => 2,
       :created_by_id => 3,
       :created_at    => '2013-09-28 00:59:21',
       :object        => "User",
@@ -414,23 +414,35 @@ returns
       scan = self.firstname.scan(/, /)
       if scan[0]
         name = self.firstname.split(', ', 2)
-        self.lastname  = name[0]
-        self.firstname = name[1]
+        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)
-      self.firstname = name[0]
-      self.lastname  = name[1]
+      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
+    # -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]
-        self.firstname = scan[0][0].capitalize
-        self.lastname  = scan[0][1].capitalize
+        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

+ 14 - 14
db/migrate/20120101000001_create_base.rb

@@ -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

+ 101 - 27
lib/core_ext/string.rb

@@ -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')
-
-    links = []
-    linkregex = /<[^>]*(src|href)=\s*(.?)([^>\s]*)\2[^>]*>\s*/i
-    while linkregex.match(text)
-      links << $~[3]
-      text.sub!(linkregex, "[#{links.size}]")
+    string = self
+
+    # 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"
-
-    for i in (0...links.size).to_a
-      text = text + "\n  [#{i+1}] <#{CGI.unescapeHTML(links[i])}>" unless links[i].nil?
+    # 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, '' )
+
+    # 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
+      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
-    links = nil
-    text.chomp
+
+    string.strip
   end
 
 =begin

+ 76 - 25
test/unit/email_build_test.rb

@@ -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

+ 53 - 86
test/unit/email_parser_test.rb

@@ -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
 
-Test1:8
+___
+ [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 
+Mfg eike
+
+Martin Edenhofer via Znuny Team --- Installation [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]
+
+___
 
-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]
 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',
@@ -380,72 +380,38 @@ Hof
           :to                => 'info2@znuny.com',
           :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.
+&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 C K88H E1R?E2e31 !Calm dylan for school today.
 Closing the nursery with you down. Here and made the mess. Maybe the oï 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
-
-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
-
-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
-
-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
-
+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 
+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 
+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 
+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.
+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

+ 70 - 65
test/unit/email_process_test.rb

@@ -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.
+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 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.
-
-&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
-
-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
-
-&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
-
+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. 
+&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 
+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 
+&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.
+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

+ 3 - 3
test/unit/user_test.rb

@@ -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,