MBOX-Line: From Pidgeot18 at verizon.net  Thu Aug 16 20:46:44 2012
To: imap-protocol@u.washington.edu
From: Joshua Cranmer <Pidgeot18@verizon.net>
Date: Fri Jun  8 12:34:48 2018
Subject: [Imap-protocol] IMAP part numbering corner case
Message-ID: <502DBEA4.2070204@verizon.net>

For various reasons, I've been writing my own custom MIME parser. One 
goal I had was to be able to match IMAP's part numbering for all parts, 
so I don't have to pass metadata around on part numbers all the time. 
The parser I've been cribbing off of uses a rather different numbering 
scheme (effectively, anything that can hold a subpart gets a number, so 
the part identified as 3.1 in the example is actually part 1.3.1.1 in 
the internal numbering scheme), so following its logic was completely 
out of the question. On a careful reading of the spec, however, it seems 
that a critical part of the algorithm goes completely undefined. This is 
not noticeable except on an evil message like the following:

------
Date: Fri, 01 Jan 2010 12:00 -0500
To: x@x.x
From: y@y.y
Subject: download on demand problem
MIME-Version: 1.0
Content-Type: message/rfc822

Date: Fri, 01 Jan 2012 12:00 -0500
To: y@y.y
From: x@x.x
Subject: Blast from the future
MIME-Version:1.0
Content-Type: text/plain

Do you know what to do when you see this message?
-------

What should FETCH BODY[1] return for this message? BODY[1.TEXT]? BODY[1.1]?

I tested the results on 4 different IMAP servers and got 4 different 
answers:
[Unknown server, ID returns NIL]
BODY[TEXT]: The entire inner message
BODY[1]: The entire inner message
BODY[1.1]: Do you know...
BODY[1.MIME]: Headers of the outer message
BODY[1.HEADER]: Headers of the inner message
BODY[1.TEXT]: Do you know...

[GMail]:
BODY[TEXT]: The entire inner message
BODY[1]: NIL
BODY[1.1]: NIL
BODY[1.MIME]: NIL
BODY[1.HEADER]: NIL
BODY[1.TEXT]: NIL

[Zimbra, specifically 7.2.0_GA_2669]:
BODY[TEXT]: The entire inner message
BODY[1]: The entire inner message
BODY[1.1]: Do you know...
BODY[1.MIME]: Headers of the outer message
BODY[1.HEADER]: Headers of the outer message
BODY[1.TEXT]: The entire inner message

[Outlook, I'm pretty sure, but it doesn't implement ID]:
BODY[TEXT]: The entire inner message
BODY[1]: The entire inner message
BODY[1.1]: NIL
BODY[1.MIME]: NIL
BODY[1.HEADER]: NIL
BODY[1.TEXT]: NIL

FWIW, as an aside, I'm currently putting together a testsuite of MIME 
messages in part to be able to do things like ensure correctness of 
things like IMAP servers, even in the face of horribly malformed 
messages. I'm frankly shocked by how not comprehensive the testsuites I 
can find are, which makes it hard to judge whether or not edge cases are 
viable to change or not in handling.

-- 
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald E. Knuth


