Browse Source

Improved error handling of email parsing.

Martin Edenhofer 12 years ago
parent
commit
a63752c134
3 changed files with 254 additions and 6 deletions
  1. 16 4
      app/models/channel/email_parser.rb
  2. 216 0
      test/fixtures/mail10.box
  3. 22 2
      test/unit/email_parser_test.rb

+ 16 - 4
app/models/channel/email_parser.rb

@@ -146,14 +146,25 @@ class Channel::EmailParser
           file.header.fields.each { |field|
             headers_store[field.name.to_s] = field.value.to_s
           }
+
+          # get filename from content-disposition
           filename = nil
-          if file.header[:content_disposition].filename
+          if file.header[:content_disposition] && file.header[:content_disposition].filename
             filename = file.header[:content_disposition].filename
           end
-          if file.header[:content_type].string
+
+          # for some broken sm mail clients (X-MimeOLE: Produced By Microsoft Exchange V6.5)
+          if !filename
+            filename = file.header[:content_location].to_s
+          end
+
+          # get mime type
+          if file.header[:content_type] && file.header[:content_type].string
             headers_store['Mime-Type'] = file.header[:content_type].string
           end
-          if file.header.charset
+
+          # get charset
+          if file.header && file.header.charset
             headers_store['Charset'] = file.header.charset
           end
 
@@ -166,6 +177,7 @@ class Channel::EmailParser
             :filename    => filename,
             :preferences => headers_store,
           }
+
           data[:attachments].push attach
         }
       end
@@ -205,7 +217,7 @@ class Channel::EmailParser
         attachment = {
           :data        => mail.body.decoded,
           :filename    => mail.filename || filename,
-          :preferences => headers_store          
+          :preferences => headers_store
         }
         data[:attachments].push attachment
       end

+ 216 - 0
test/fixtures/mail10.box

@@ -0,0 +1,216 @@
+From smith@example.com  Tue Oct 23 14:55:00 2012
+Return-Path: <smith@example.com>
+X-Original-To: info@example.com
+Delivered-To: example-sales@samba.edenhofer.de
+X-Greylist: delayed 1679 seconds by postgrey-1.32 at samba; Tue, 23 Oct 2012 14:54:59 BST
+Received: from mailout109.bayern.de (mailout109.bayern.de [195.200.70.109])
+	by samba.edenhofer.de (Postfix) with ESMTP id F2FCD500B14
+	for <info@example.com>; Tue, 23 Oct 2012 14:54:59 +0100 (BST)
+Received: from avisout130.bybn.de (avisout130.bybn.de [10.197.20.130])
+	by mailout109.bayern.de (8.14.5/8.14.5) with ESMTP id q9NDR29S013763
+	for <info@example.com>; Tue, 23 Oct 2012 15:27:02 +0200
+Received: from post23.bybn.de (post23.bybn.de [10.197.20.23])
+	by avisout130.bybn.de (8.14.4/8.14.4) with ESMTP id q9NDR1NJ003273
+	for <info@example.com>; Tue, 23 Oct 2012 15:27:02 +0200
+	(envelope-from smith@example.com)
+Received: from lramail1.Landratsamt.de ([10.38.19.31])
+	by post23.bybn.de (8.14.5/8.14.4) with ESMTP id q9NDR1CF018327
+	for <info@example.com>; Tue, 23 Oct 2012 15:27:01 +0200
+Content-class: urn:content-classes:message
+MIME-Version: 1.0
+Content-Type: multipart/related;
+	boundary="----_=_NextPart_001_01CDB122.15B956D2";
+	type="multipart/alternative"
+X-MimeOLE: Produced By Microsoft Exchange V6.5
+Subject: =?iso-8859-1?Q?Gru=DF_aus_Oberalteich?=
+Date: Tue, 23 Oct 2012 15:27:00 +0200
+Message-ID: <8FD7A79CBC14344E85C71183DF75D85A019B1699@lramail1.Landratsamt.de>
+X-MS-Has-Attach: 
+X-MS-TNEF-Correlator: 
+Thread-Topic: =?iso-8859-1?Q?Gru=DF_aus_Oberalteich?=
+Thread-Index: Ac2xIg1UWZ9khKyyT0yHHVxGjysbXQ==
+From: "Smith Sepp" <smith@example.com>
+To: <info@example.com>
+X-Keywords:                 
+X-UID: 108
+Status: RO
+Content-Length: 6878
+Lines: 176
+
+This is a multi-part message in MIME format.
+
+------_=_NextPart_001_01CDB122.15B956D2
+Content-Type: multipart/alternative;
+	boundary="----_=_NextPart_002_01CDB122.15B956D2"
+
+
+------_=_NextPart_002_01CDB122.15B956D2
+Content-Type: text/plain;
+	charset="iso-8859-1"
+Content-Transfer-Encoding: quoted-printable
+
+Herzliche Gr=FC=DFe aus Oberalteich sendet Herrn Smith
+
+=20
+
+Sepp Smith  - Dipl.Ing. agr. (FH)
+
+Gesch=E4ftsf=FChrer der example Straubing-Bogen
+
+Klosterhof 1 | 94327 Bogen-Oberalteich
+
+Tel: 09422-505601 | Fax: 09422-505620
+
+Internet: http://example-straubing-bogen.de <http://example-straubing-bogen.de/> =
+
+
+Facebook: http://facebook.de/examplesrbog <http://facebook.de/examplesrbog>=20
+
+   -  European Foundation f=FCr Quality Management
+
+=20
+
+
+------_=_NextPart_002_01CDB122.15B956D2
+Content-Type: text/html;
+	charset="iso-8859-1"
+Content-Transfer-Encoding: quoted-printable
+
+<html xmlns:v=3D"urn:schemas-microsoft-com:vml" =
+xmlns:o=3D"urn:schemas-microsoft-com:office:office" =
+xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
+xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" =
+xmlns=3D"http://www.w3.org/TR/REC-html40"><head><meta =
+http-equiv=3DContent-Type content=3D"text/html; =
+charset=3Diso-8859-1"><meta name=3DGenerator content=3D"Microsoft Word =
+14 (filtered medium)"><!--[if !mso]><style>v\:* =
+{behavior:url(#default#VML);}
+o\:* {behavior:url(#default#VML);}
+w\:* {behavior:url(#default#VML);}
+.shape {behavior:url(#default#VML);}
+</style><![endif]--><style><!--
+/* Font Definitions */
+@font-face
+	{font-family:Calibri;
+	panose-1:2 15 5 2 2 2 4 3 2 4;}
+@font-face
+	{font-family:Tahoma;
+	panose-1:2 11 6 4 3 5 4 4 2 4;}
+@font-face
+	{font-family:Verdana;
+	panose-1:2 11 6 4 3 5 4 4 2 4;}
+@font-face
+	{font-family:"Viner Hand ITC";
+	panose-1:3 7 5 2 3 5 2 2 2 3;}
+/* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:11.0pt;
+	font-family:"Calibri","sans-serif";
+	mso-fareast-language:EN-US;}
+a:link, span.MsoHyperlink
+	{mso-style-priority:99;
+	color:blue;
+	text-decoration:underline;}
+a:visited, span.MsoHyperlinkFollowed
+	{mso-style-priority:99;
+	color:purple;
+	text-decoration:underline;}
+p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
+	{mso-style-priority:99;
+	mso-style-link:"Sprechblasentext Zchn";
+	margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:8.0pt;
+	font-family:"Tahoma","sans-serif";
+	mso-fareast-language:EN-US;}
+span.E-MailFormatvorlage17
+	{mso-style-type:personal-compose;
+	font-family:"Calibri","sans-serif";
+	color:windowtext;}
+span.SprechblasentextZchn
+	{mso-style-name:"Sprechblasentext Zchn";
+	mso-style-priority:99;
+	mso-style-link:Sprechblasentext;
+	font-family:"Tahoma","sans-serif";}
+.MsoChpDefault
+	{mso-style-type:export-only;
+	font-family:"Calibri","sans-serif";
+	mso-fareast-language:EN-US;}
+@page WordSection1
+	{size:612.0pt 792.0pt;
+	margin:70.85pt 70.85pt 2.0cm 70.85pt;}
+div.WordSection1
+	{page:WordSection1;}
+--></style><!--[if gte mso 9]><xml>
+<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
+</xml><![endif]--><!--[if gte mso 9]><xml>
+<o:shapelayout v:ext=3D"edit">
+<o:idmap v:ext=3D"edit" data=3D"1" />
+</o:shapelayout></xml><![endif]--></head><body lang=3DDE link=3Dblue =
+vlink=3Dpurple><div class=3DWordSection1><p class=3DMsoNormal>Herzliche =
+Gr=FC=DFe aus Oberalteich sendet Herrn Smith<o:p></o:p></p><p =
+class=3DMsoNormal><o:p>&nbsp;</o:p></p><p class=3DMsoNormal><span =
+style=3D'font-size:14.0pt;font-family:"Viner Hand =
+ITC";mso-fareast-language:DE'>Sepp Smith=A0 - </span><span =
+style=3D'font-size:8.0pt;font-family:"Verdana","sans-serif";mso-fareast-l=
+anguage:DE'>Dipl.Ing. agr. (FH)</span><span =
+style=3D'font-size:14.0pt;font-family:"Viner Hand =
+ITC";mso-fareast-language:DE'><o:p></o:p></span></p><p =
+class=3DMsoNormal><span =
+style=3D'mso-fareast-language:DE'>Gesch=E4ftsf=FChrer der example =
+Straubing-Bogen<o:p></o:p></span></p><p class=3DMsoNormal><span =
+style=3D'mso-fareast-language:DE'>Klosterhof 1 | 94327 =
+Bogen-Oberalteich<o:p></o:p></span></p><p class=3DMsoNormal><span =
+style=3D'mso-fareast-language:DE'>Tel: 09422-505601 | Fax: =
+09422-505620<o:p></o:p></span></p><p class=3DMsoNormal><span =
+style=3D'mso-fareast-language:DE'>Internet: <a =
+href=3D"http://example-straubing-bogen.de/"><span =
+style=3D'color:blue'>http://example-straubing-bogen.de</span></a><o:p></o:p><=
+/span></p><p class=3DMsoNormal><span lang=3DEN-US =
+style=3D'mso-fareast-language:DE'>Facebook: </span><span =
+style=3D'mso-fareast-language:DE'><a =
+href=3D"http://facebook.de/examplesrbog"><span lang=3DEN-US =
+style=3D'color:blue'>http://facebook.de/examplesrbog</span></a></span><span =
+lang=3DEN-US style=3D'mso-fareast-language:DE'><o:p></o:p></span></p><p =
+class=3DMsoNormal><b><span =
+style=3D'font-size:7.5pt;color:navy;mso-fareast-language:DE'><img =
+border=3D0 width=3D60 height=3D19 id=3D"Bild_x0020_1" =
+src=3D"cid:image001.jpg@01CDB132.D8A510F0" alt=3D"Beschreibung: =
+Beschreibung: efqmLogo"></span></b><b><span lang=3DEN-US =
+style=3D'font-size:7.5pt;color:navy;mso-fareast-language:DE'>=A0 -=A0 =
+European Foundation f=FCr Quality Management</span></b><span =
+lang=3DEN-US style=3D'mso-fareast-language:DE'><o:p></o:p></span></p><p =
+class=3DMsoNormal><span =
+lang=3DEN-US><o:p>&nbsp;</o:p></span></p></div></body></html>
+------_=_NextPart_002_01CDB122.15B956D2--
+
+------_=_NextPart_001_01CDB122.15B956D2
+Content-Type: image/jpeg;
+	name="image001.jpg"
+Content-Transfer-Encoding: base64
+Content-ID: <image001.jpg@01CDB132.D8A510F0>
+Content-Description: image001.jpg
+Content-Location: image001.jpg
+
+/9j/4AAQSkZJRgABAQEAYABgAAD//gAcU29mdHdhcmU6IE1pY3Jvc29mdCBPZmZpY2X/2wBDAAoH
+BwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8
+SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7
+Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAATADwDASIAAhEBAxEB/8QAGwAAAgIDAQAAAAAAAAAAAAAA
+AAYEBQIDBwj/xAAuEAABAwMDAwMDAwUAAAAAAAABAgMEAAURBhJBByExEyJhFFFxFRZDgZGhsdH/
+xAAZAQACAwEAAAAAAAAAAAAAAAACBQADBAH/xAAiEQACAgEDBAMAAAAAAAAAAAABAgARAwQSITFB
+UXETocH/3QAEACj/2gAMAwEAAhEDEQA/ANWnrxrfVV4ukWLqluEmG4ceu2nBBUQAO3GKstUz9Y6S
+0e7Lk6lbmSXJraG3WED2I2qyk9uTikvTcTSsy/XkapnriNpeUWChZTuO9WfAPxVvq9nSkPp89G0t
+cFS2/wBRbcf3rKiklCgPIH2pmyL8gFcev2B2jNabX1BuUGHcP3nGS3IQh30y0MgHBx484ptdem3a
+U4xCllpln2rW2Ofzz/SlnSHTWyogWi+JkTfqiy2/tL3s3FOfGPHer63y1WRhyI+EodUVKaLh2pUo
+cE8Z7d6Ta5g2RUJpTdnpNeAUpYCyOk3SU3e0Mev9V9W013O7yRyD/wBpE6ha9vdk1Jbl2mXtiORU
+PKjlAKVnccg88Ux3DqHZJFufhPPG3ziNjkeYNhR9znwofYiki+llzqHpL01peaW2yclJwoFxXB4o
+9HjbHqCpFpXfzJkIbFuPDX9RtunVq0taQbudvKXLjJBQiIruWnOSr4H+e1IEHqNq95lSl3hZO8/x
+o7ePiuixeldmtmpZd7ThbAQVx4ik+1peDk/IHA4riluWPScOfLpP+qb6dcLXtF+5kJM9IK0Vphxa
+lrsUFSlElRLIySfNZDR+m0x1xk2SEGXFBa0BoYUR4J/uaKKWbm8wpaMMNRWEMMNpbabTtQhIwEge
+AKi3GJHmMbJDSXAO4zwaKKqygFDcsxkhgRIKdM2OWhpUq2R31MHc2p1G4pP5PHxUyRYrVMmNTpFv
+juyY4HpOqQCpGO4xRRXcJOwSZOWNyeQFJKVDIPYg81UI0dppsEIscIAnJwyKKKsBI6QJ/9k=
+
+------_=_NextPart_001_01CDB122.15B956D2--
+

+ 22 - 2
test/unit/email_parser_test.rb

@@ -195,13 +195,33 @@ Hof",
           :body         => "Enjoy!\n\n-Martin\n\n--\nOld programmers never die. They just branch to a new address."
         },
       },
+      {
+        :data         => IO.read('test/fixtures/mail10.box'),
+        :body_md5     => '8d6ea42f7f36a790e67f50e3a5f27063',
+        :attachments  => [
+          {
+            :md5      => '08b0c83fd155db23f22bed845715225d',
+            :filename => 'message.html',
+          },
+          {
+            :md5      => 'a618d671348735744d4c9a4005b56799',
+            :filename => 'image001.jpg',
+          },
+        ],
+        :params   => {
+          :from               => 'Smith Sepp <smith@example.com>',
+          :from_email         => 'smith@example.com',
+          :from_display_name  => 'Smith Sepp',
+          :subject            => 'Gruß aus Oberalteich',
+#          :body         => "Herzliche Grüße aus Oberalteich sendet Herrn Smith\n\n \n\nSepp Smith  - Dipl.Ing. agr. (FH)\n\nGeschäftsführer der example Straubing-Bogen\n\nKlosterhof 1 | 94327 Bogen-Oberalteich\n\nTel: 09422-505601 | Fax: 09422-505620\n\nInternet: http://example-straubing-bogen.de <http://example-straubing-bogen.de/> \n\nFacebook: http://facebook.de/examplesrbog <http://facebook.de/examplesrbog> \n\n   -  European Foundation für Quality Management\n\n"
+        },
+      },
     ]
 
     files.each { |file|
- 
       parser = Channel::EmailParser.new
       data = parser.parse( file[:data] )
-      
+
       # check body
       md5 = Digest::MD5.hexdigest( data[:body] )
       assert_equal( file[:body_md5], md5 )