[mel-base-devel] mel.mime:parts not working properly for rfc 2822 (reading from a file)

Fred Gibson fred at streamfocus.com
Fri Jan 29 00:58:48 UTC 2010


Hi Jochen,

I found a problem with the find-viewable-part function when parsing
multipart/related, so I wrote a new version to handle any structure
which seems to work in all cases:

(defun eml-message->viewable-part (obj)
  "takes a part or eml message"
  (flet ((eml-content-subtype (o)
           (multiple-value-bind (a b c)(mel.mime:content-type o)
             (declare (ignore a c))
             b))
         (eml-content-type (o)
           (multiple-value-bind (a b c)(mel.mime:content-type o)
             (declare (ignore b c))
             a)))
    (if (eq (eml-content-subtype obj) :plain)
        obj
        (let ((parts (mel.mime:parts obj)))
          (when parts
            (or
             (find :plain parts :key #'eml-content-subtype)
             (let ((mpart (find :multipart parts :key #'eml-content-type)))
               (when mpart (eml-message->viewable-part mpart)))))))))

On Thu, Jan 28, 2010 at 10:15 AM, Fred Gibson <fred at streamfocus.com> wrote:
> Sorry about that, the method should read:
>
> (defmethod part-body-stream ((part part))
>  "Skip headers to beginning of part body and return stream"
>  (let* ((message (loop for parent = (parent part) then (parent parent)
>                     until (typep parent 'message)
>                     finally (return parent)))
>         (stream (message-body-stream message))
>         (boundary (boundary-tag (parent part))))
>      (dotimes (number (part-number part))
>        (scan-forward-boundary-tag stream boundary))
>      (read-rfc2822-header stream)
>      stream))
>
> My best,
>
> Fred
>
> On Thu, Jan 28, 2010 at 9:40 AM, Fred Gibson <fred at streamfocus.com> wrote:
>> Hi Jochen,
>>
>> This seems to do the trick nicely:
>>
>> (defmethod part-body-stream ((part part))
>>  "Skip headers to beginning of part body and return stream"
>>  (let* ((stream (message-body-stream (part-to-message part)))
>>         (parent (loop for parent = (parent part) then (parent parent)
>>                    until (typep parent 'message)
>>                    finally (return parent)))
>>         (boundary (boundary-tag (parent part))))
>>      (dotimes (number (part-number part))
>>        (scan-forward-boundary-tag stream boundary))
>>      (read-rfc2822-header stream)
>>      stream))
>>
>> My best,
>>
>> Fred
>>
>> On Thu, Jan 28, 2010 at 8:56 AM, Jochen Schmidt <js at crispylogics.com> wrote:
>>>
>>> Am 28.01.2010 um 17:49 schrieb Fred Gibson:
>>>
>>>> Would that approach work with an alternative structure where both a
>>>> text/plain and a text/html have the same boundary?  I was thinking
>>>> that the content-type would need to be used to get an exact part
>>>> match.
>>>
>>> No you use the part-number. This is a strict numbering on the same level. So if you scan for a part with part number 2 you have to skip the first found boundary.
>>>
>>>>
>>>> How about:
>>>>
>>>>> Given some part P with boundary B
>>>>> 1) Locate the message object by following the parent chain
>>>>> 2) Get a message-body-stream
>>>>> 3) scan the stream for the boundary B
>>>> 4) if boundary is found
>>>> 5)  process the content-type
>>>>          if content-type matches
>>>>          then return stream as part-stream
>>>>          else go to 3)
>>>
>>> That isn't needed - the bodystructure (and the mel-base part objects) already contain the part-number.
>>>
>>> ciao,
>>> Jochen
>>>
>>>
>>
>>
>>
>> --
>> Fred Gibson
>>
>> Founder / Software Developer
>> http://www.streamfocus.com
>>
>> (c)2010 Organon Technologies LLC
>>
>
>
>
> --
> Fred Gibson
>
> Founder / Software Developer
> http://www.streamfocus.com
>
> (c)2010 Organon Technologies LLC
>



-- 
Fred Gibson

Founder / Software Developer
http://www.streamfocus.com

(c)2010 Organon Technologies LLC




More information about the mel-base-devel mailing list