[mel-base-devel] maildir multipart
Jochen Schmidt
js at codeartist.org
Sun May 17 21:03:20 UTC 2009
Am 15.05.2009 um 17:13 schrieb Timothy Ritchey:
> If I do something like:
>
> (defun check-email ()
> (let* ((folder (mel:make-imaps-folder :host
> "imap.gmail.com" :username "XXXXX" :password "XXXXX"))
> (messages (mel:messages folder)))
> (dolist (m messages)
> (format t "~a~%" (find-plain-text m))) folder))
>
> I am able to find the plain text part of the messages using:
>
> (defun find-plain-text (message)
> (let ((parts (mel:parts message))
> (body "Unable to process email contents"))
> (dolist (p parts)
> (multiple-value-bind (a b) (mel:content-type p)
> (if (and (equal a :TEXT) (equal b :PLAIN))
> (let ((b (mel:part-body-string p))
> (encoding (mel:content-transfer-encoding p)))
> (if (string-equal encoding "quoted-printable")
> (setf body (mel:decode-quoted-printable b))
> (setf body b)))
> (progn
> (when (and (equal a :MULTIPART) (equal b :ALTERNATIVE))
> (find-plain-text p))))))
> body))
>
> but if I try to move things over to a maildir, and run from there, my
> FIND-PLAIN-TEXT function doesn't work. Is the maildir message format
> different than a message in an imap folder?
No the message format is the same (octet wise). One of the design
principles of mel-base was to never modify the content of a message.
(Trivia: I started mel-base because the "standard" python mail library
modified my mails while fetching them). You can compared the file
stored in the maildir folder with one saved using e.g. Apple Mail.app
from the IMAP server - they ought to be identical.
The problem here is that perhaps the message is interpreted
differently when accessing its parts. IMAP is a cool thing - you get
many things from it without much work. RFC2060 (IMAP) defines a thing
called "Body Structure" which describes the structure of the message-
body. If you use IMAP, mel-base can just query the server for the body
structure - if not it will have to compute it by itself. It seems that
the body structure of your message parsed by your server is different
from the one parsed by mel-base.
The folder protocol of mel-base has a GF called COMPUTE-BODYSTRUCTURE-
USING-FOLDER. Which has two implemented methods: One for IMAP-Foldes
and one for all others. The user-level function is called COMPUTE-
BODYSTRUCTURE and can be called on a message object to get the body
structure of it.
I've tried it using my current snapshot here on some multipart message
in my mail account.
The IMAP gives:
(((:TEXT :PLAIN (:CHARSET "us-ascii") NIL NIL :QUOTED-PRINTABLE 1638
45 NIL NIL NIL)
(:APPLICATION :PGP-SIGNATURE (:NAME "signature.asc") NIL NIL :7BIT
205 NIL NIL NIL NIL)
:SIGNED
(:MICALG "pgp-sha1" :PROTOCOL "application/pgp-signature" :BOUNDARY
"=-N3IPeK0F6Rq/H013D1bn")
NIL
NIL)
(:TEXT :PLAIN (:CHARSET "us-ascii") NIL NIL :7BIT 165 4 NIL NIL NIL)
:MIXED
(:BOUNDARY "===============1035646608==")
NIL
NIL)
And the copied message in the Maildir-folder:
(((:TEXT :PLAIN NIL NIL NIL :QUOTED-PRINTABLE 1638 45 NIL NIL NIL)
(:APPLICATION :PGP-SIGNATURE (:NAME "signature.asc") NIL NIL NIL
205 7 NIL NIL NIL)
:SIGNED
(:BOUNDARY "=-N3IPeK0F6Rq/H013D1bn" :PROTOCOL "application/pgp-
signature" :MICALG "pgp-sha1")
NIL
NIL)
(:TEXT :PLAIN (:CHARSET "us-ascii") NIL NIL :7BIT 165 4 NIL NIL NIL)
:MIXED
(:BOUNDARY "===============1035646608==")
NIL
NIL)
There seem to be some differences here too. As of now - mel-base
doesn't get the charset "us-ascii" of the first text/plain part. This
is ok since charset us-ascii is implicitely us-ascii. The mail-file
doesn't specify us-ascii on that part - its the IMAP server that adds
it to the bodystructure to make it explicit. I could do so too - but
it is not against the spec to let it implicit. I also fixed a bug
with computation of octet and line-counts of the parts. I always
counted the last empty line before the closing boundary - this is
actually not part of the part (pardon the pun ;-) ).
I've built a new release of mel-base (0.9-0) uploaded it to my server
and registered it at CLiki (so that things like ASDF-INSTALL work).
You can just try it - I've reimplemented the computation of the
bodystructure so that it now gives the exact same result as my IMAP
server. I've also reworked the character coding infrastructure (now
using bivalent streams and flexi-streams were appropriate).
To see whats wrong in your case, I would need a bit more information.
Can you send the result of COMPUTE-BODYSTRUCTURE for IMAP and Maildir?
ciao,
Jochen
--
Jochen Schmidt
js at codeartist.org
http://www.codeartist.org
>
> (defun check-email ()
> (let* ((folder (mel:make-imaps-folder :host
> "imap.gmail.com" :username "XXXXX" :password "XXXXX"))
> (tmp-folder (mel:make-maildir-folder "/tmp/test-maildir/" :if-does-
> not-exist :create)))
> (mel:move-folder folder tmp-folder)
> (mel:map-messages
> (lambda (m)
> (let ((body (find-plain-text m)))
> (format t "~a~%" body)))
> tmp-folder)))
>
>
>
> _______________________________________________
> mel-base-devel mailing list
> mel-base-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/mel-base-devel
Jochen Schmidt
js at codeartist.org
http://www.codeartist.org
More information about the mel-base-devel
mailing list