Closed net1957 closed 13 years ago
I have found the same error too in some mails. In my case they had a wrong content_type (images/jpeg instead of image/jpeg) but it would be cool that it just skip the part instead of failing. Its easy to reproduce (using 2.2.1):
require 'rubygems'
require 'mail'
Mail::VERSION::STRING
mail = Mail.new do
to "aaaa@aaaa.aaa"
from "aaaa2@aaaa.aaa"
subject "a subject"
date Time.now
text_part do
content_type 'text/plain; charset=UTF-8'
body "a body\nsimple\n"
end
end
mail.attachments["tux.jpg"] = { :content => File.read("/tmp/tux.jpg")}
puts "no problem here"
Mail.new mail.encoded
puts "fails_here"
Mail.new mail.encoded.gsub("image/jpeg", "images/jpeg")
the result is:
irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'mail'
=> true
irb(main):003:0>
irb(main):004:0* Mail::VERSION::STRING
=> "2.2.1"
irb(main):005:0>
irb(main):006:0* mail = Mail.new do
irb(main):007:1* to "aaaa@aaaa.aaa"
irb(main):008:1> from "aaaa2@aaaa.aaa"
irb(main):009:1> subject "a subject"
irb(main):010:1> date Time.now
irb(main):011:1> text_part do
irb(main):012:2* content_type 'text/plain; charset=UTF-8'
irb(main):013:2> body "a body\nsimple\n"
irb(main):014:2> end
irb(main):015:1> end
=> #<Mail::Message:69994379933780, Multipart: true, Headers: <Date: Thu, 13 May 2010 12:51:29 +0200>, <From: aaaa2@aaaa.aaa>, <To: aaaa@aaaa.aaa>, parameters' for #<Mail::UnstructuredField:0x7f51ac1e67c0> from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/field.rb:122:in
send'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/field.rb:122:in method_missing' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/header.rb:164:in
charset'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/header.rb:78:in fields=' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/header.rb:76:in
each'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/header.rb:76:in fields=' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/header.rb:250:in
split_header'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/header.rb:40:in initialize' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:359:in
new'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:359:in header=' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/part.rb:88:in
parse_message'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:1839:in init_with_string' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:119:in
initialize'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/body.rb:260:in new' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/body.rb:260:in
split!'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/body.rb:260:in each' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/body.rb:260:in
split!'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:1756:in separate_parts' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:1840:in
init_with_string'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:119:in initialize' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/mail.rb:50:in
new'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/mail.rb:50:in `new'
from (irb):23
from :0irb(main):024:0>
I have been realized that problem is quite worse than I thought: I have been testing 2.2.0/1 and many mails that were parsed in 2.1.3 are not parsed now. So, I can't use 2.2 version since it is broken for my app.
This is a sample that shows how it works for older version and not for new one:
Let's try this code and setting Mail version to 2.1.3: require 'rubygems' gem 'mail', '<= 2.1.3' require 'mail'
puts Mail::VERSION::STRING
Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: text/plain; charset=us-ascii\n\nsome text\n\n"
Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: Text/Plain\n\nsome text\n\n"
Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: Text/Plain; charset=us-ascii\n\nsome text\n\n"
all mails are parsed fine:
irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> gem 'mail', '<= 2.1.3'
=> true
irb(main):003:0> require 'mail'
=> true
irb(main):004:0>
irb(main):005:0* puts Mail::VERSION::STRING
2.1.3
=> nil
irb(main):006:0>
irb(main):007:0* Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: text/plain; charset=us-ascii\n\nsome text\n\n"
=> #<Mail::Message:69823812939580, Multipart: false, Headers: <From: bb@bb.bb>, <To: aa@aa.aa>,
Now lets start a new irb and try with 2.2.1 version:
require 'rubygems'
gem 'mail', '>= 2.2.0'
require 'mail'
puts Mail::VERSION::STRING
Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: text/plain; charset=us-ascii\n\nsome text\n\n"
Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: Text/Plain\n\nsome text\n\n"
Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: Text/Plain; charset=us-ascii\n\nsome text\n\n"
As we can see, last mail fails parsing:
irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> gem 'mail', '>= 2.2.0'
=> true
irb(main):003:0> require 'mail'
=> true
irb(main):004:0>
irb(main):005:0* puts Mail::VERSION::STRING
2.2.1
=> nil
irb(main):006:0>
irb(main):007:0* Mail.new "To:aa@aa.aa\nFrom: bb@bb.bb\nSubject: a subject\nContent-Type: text/plain; charset=us-ascii\n\nsome text\n\n"
=> #<Mail::Message:70079067537860, Multipart: false, Headers: <From: bb@bb.bb>, <To: aa@aa.aa>, main_type' for #<Mail::UnstructuredField:0x7f791bcae6d0> from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/field.rb:122:in
send'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/field.rb:122:in method_missing' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:1400:in
main_type'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:1421:in multipart?' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:1840:in
init_with_string'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/message.rb:119:in initialize' from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/mail.rb:50:in
new'
from /var/lib/gems/1.8/gems/mail-2.2.1/lib/mail/mail.rb:50:in `new'
from (irb):9
from :0
Looks like caps in the content_type with some charset breaks parsing. As a curious side note, many mails that had failed in my tests where from ruby-core mail list :p
Same problem for me. mail 2.2.x breaks on many real-world mails that 2.1.3 processed fine. This is a show stopper for me. I cannot upgrade to 2.2.x unless this bug has been fixed.
Here is another example that shows the problem:
require 'mail' --8<-- Mail.new <<'EOT' From joe@company.com Fri Feb 19 08:41:30 2010 From: Big Bug bb@bug.com To: rubymail@ruby-lang.org Subject: undef method parameter bug Date: Fri, 19 Feb 2010 10:08:29 +0300 MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Message-Id: 201002191008.30117.foo.bar@company.com
foo bar EOT -->8--
And this is the stack trace:
/usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/field.rb:122:in method_missing': undefined method
parameters' for Text/Plain; charset="iso-8859-1":Mail::UnstructuredField (NoMethodError)
from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/header.rb:164:in charset' from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/header.rb:78:in
block in fields='
from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/header.rb:76:in each' from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/header.rb:76:in
fields='
from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/header.rb:250:in split_header' from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/header.rb:40:in
initialize'
from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/message.rb:359:in new' from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/message.rb:359:in
header='
from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/message.rb:1740:in parse_message' from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/message.rb:1839:in
init_with_string'
from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/message.rb:119:in initialize' from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/mail.rb:50:in
new'
from /usr/local/lib/ruby/gems/1.9.1/gems/mail-2.2.1/lib/mail/mail.rb:50:in new' from mail-undef-par-meth-bug.rb:4:in
This is happening because the Mail gem assumes that the headers of an email are split on the carriage return, but many emails we receive have header values which span multiple lines.
The Mail::Header#split_header method is the source of this bug.
For clarity, I created issue #68 for header parsing bug.
Sorry guys for the ticket spam, I was wrong in my original thoughts on this bug. Not sure what is causing the underlying issue but some of the parameter/content-type parsing methods are getting choked up on certain emails.
I did a little modification (http://github.com/lls/mail/blob/master/lib/mail/fields/content_type_field.rb), basically downcasing content type in case of error and it seems to work. There will probably be a better way to do it, maybe touching the parser, but I'm quite unfamiliar with it.
Hopefully mikel will look at this issue sometime. Unfortunately, he may also have a life and a job so he can't be fulltime in this project :P
I put in a similar fix last night as well. Basically the parameters method was getting invoked without checking if that object had the method (your fix addresses this as well). There were a few other places that had a similar issue which popped up once I fixed the parameters one, so there's a fix in my commit for those as well.
See here: http://github.com/justinperkins/mail/commit/5c64e85aaca0798ee275097d8d031e46010fcf0f
OK, so lets get this fixed :) I am at RailsConf now and playing with releasing another version of mail and putting in some of the more recent fixes.
Justin, please do write a spec, the easiest spec to write would be just to find an email that fails with mail, and creating a new file in the spec/fixtures/emails/error_emails/ directory. Just give it an intelligent sounding filename so it is clear the error it makes.
Then you should be able to run the specs, see it fail on that email, and then applying the fixes should handle it.
If you can incorporate Ils and your fixes to a new commit, with that failing spec, that would be awesome :)
Mikel
Well, as I said earlier, I am not a spec guy. I tried my best, installed rspec and the seemingly endless chain of dependency gems, and then ran spec *_/__spec.rb from the spec directory and oh boy did I get a lot of failures. 89 to be exact. It's probably a versioning issue or something, but it's really hard for me to debug since I am in unfamiliar territory. I have an email on hand that triggers this exception and have verified that it is fixed with the latest copy of my fork. I'm sorry I cannot be more help.
I will checkin the email I was referring to to my fork and send you a pull request.
http://gist.github.com/467892 fixes this issue.
I'm not happy with [iI] [mM] [aA] [gG] [eE] though, didn't found other way to ignore case with treetop.
The piece of header in spec taken from real-life e-mail.
I applied libc's patch, but it still fails on certain emails.
Check issue 82 for an example.
Are you sure you applied it right?
>> Mail.new(open('http://gist.github.com/raw/472080/11dc9c739e115e430b3385ff3abb67c22fcb159b/test.image-att.eml').read).parts[1].content_type
=> "image/jpeg; name=IMG_8476.jpg"
Update: I see, content-disposition issue.
I added a spec that shows this problem and issued a pull request.
http://github.com/yyyc514/mail/commit/3a256a72aae7ddcea348f772dbbad75e0c18b368
Added some commit notes here:
This isn't a 100% fix for the underlying problem.
And my suggested fix: http://github.com/yyyc514/mail/commit/2139c003b924c87c9ae2062decff5ea2f5ccc0ce
Just down case the beginning of the Content-Type header inside the cleaned methods before it's passed to the parser. Makes sense to me since the parser seems to only expect downcased values in the first place, and that's how you usually see content type written out in "proper" form.
Ok, libc's fix looks good. I've committed that to my fork and issues a pull request.
http://github.com/yyyc514/mail/commit/510cf0d35968ecd0acbe121b11e44d165f28095a
I've also come across this problem. Looking forward to when it's in core.
If you use Bundler it's easy enough to pin to an arbitrary version on github... here is how I've done it:
gem "mail", :git => "git://github.com/yyyc514/mail.git", :tag => "2.2.5-content_type_fix"
I've merged in libc's patch into my fork and then tagged it... and point bundler to that... and if you aren't using Bundler you should be. :)
+1 to yyyc514 's root cause. For some reason the first letter of the Content-Type header has to be lower-case. I have applied http://github.com/yyyc514/mail/commit/2139c003b924c87c9ae2062decff5ea2f5ccc0ce to my project but libc's fix is okay too. http://github.com/yyyc514/mail/commit/510cf0d35968ecd0acbe121b11e44d165f28095a
e.g. This causes the error in the title
Content-Type: Text/HTML;
This has no errors.
Content-Type: text/HTML;
I'd use libc's fix.. it's more proper and what I have committed to the top of my fork.
Any chance this will make it into an official release soon? I'm still stuck with 2.1.3 because all later versions have this showstopper bug.
It's easy enough to roll your own or pin another version of github... (such as mine)
For me, yes. For users of my app, no. They just want to do a 'gem install taskjuggler' and be good. That will only work once there is an official release available from rubygem.org.
Yeah... you're docs would have to mention that they need to pin a "correct" version of mail... icky situation.
I'll get it released this week.
That would be awesome. :)
OK, I have applied the spec and the patch and commited f3732e4 to master.
What about bumping the version and pushing a new gem?
Getting there :)
Pushed 2.2.5.1
Thanks. :) Will point our Gemfile to that come Monday. :)
Seems to work on my emails examples. Thanks.
Fantastic!
Mail 2.2.0 choke on in class ContentTypeElement with : ContentTypeElement can not parse |Multipart/Mixed| Reason was: Expected one of text, image, audio, video, application, 7bit, 8bit, binary, quoted-printable, base64, message, multipart at line 1, column 1 (byte 1) after
on this header : Content-type: Multipart/Mixed; boundary=Message-Boundary-27177
on ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-mingw32]
header are : Received: from spooler by sk-targa.sk.loc (Mercury/32 v4.72); 25 Apr 2010 21:13:07 +0200 X-Envelope-To: serge.kk@sk.loc X-CLAMWALL: Passed through antiviral test by ClamWall 1.4.0.96 on sk-targa.sk.loc (910) Return-path: serge.kk@sk.loc Received: from 192.168.0.2 by sk-targa.sk.loc (Mercury/32 v4.72) with ESMTP ID MG0002E1; 25 Apr 2010 21:12:57 +0200 From: "KUENY Serge" serge.kk@sk.loc To: serge.kk@sk.loc Date: Sun, 25 Apr 2010 21:12:57 +0200 MIME-Version: 1.0 Content-type: Multipart/Mixed; boundary=Message-Boundary-27177 Subject: pop3 Reply-to: serge.kk@sk.loc Message-ID: 4BD49439.30394.F8C705E@serge.kk@sk.loc Priority: normal X-mailer: Pegasus Mail for Windows (4.52, FR v4.51 R1.0) X-Text-Classification: normal X-POPFile-Link: http://127.0.0.1:8090/jump_to_message?view=23540 X-Recipient: serge.kk@sk.loc