Thanks,
Fred Gibson, Architect
Fred...@gibson-design.com Architecture Designed Objectively
==================================-----------||||||||||||||||||||||
Frederick Clifford Gibson Architect & Associates
1220 14th Avenue Suite 106
San Francisco, CA 94122
(c)1999 http://www.gibson-design.com
ZMAIL, the Lisp Machine mail reader. :)
Note that if you really do venture in that direction, be prepared to be
confused. It's heavily object-oriented and extremely complex, since it's
intended to be able to send mail using almost arbitrary protocols and needs
to be able to parse and generate messages in the syntax appropriate for
each.
--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
> Is anyone aware of a lisp routine that would take a standard email message
> as input, and then parse the email into its various components such as body,
> date, author, etc, etc. ?
>
I'm fairly certain that CL-HTTP (I'm not commenting on the licensing terms,
so let's not get into that :-) ) would have something to offer. I believe
one of the examples included with the package is a tool for managing a mail
list archive. I'd imagine they would have dealt to some degree with mail
parsing.
http://www.ai.mit.edu/projects/iiip/doc/cl-http/home-page.html
Sunil
This might help, then again it might not. -kelly
Code to handle full MIME encoded email is different
and more complicated.
;; copyright (c) 1998 Kelly E. Murray No Rights Reserved. :)
(function mh-load-mail (folder directory)
(loop for file in (lisp:directory directory)
finally (folder-update folder)
do
(mh-process-file folder file)))
(function mh-process-file (folder file)
(with-open-file (in file :direction :input)
(mh-inc-new-mail folder in)))
(function mh-inc-new-mail (folder in)
(loop with fields = nil
with content-string = nil
with len = (file-length in)
with msg = (make-msg :folder folder)
for line = (read-line in nil nil)
while line
finally
(move-msg msg folder) ;; already there, just need to update counters
etc
(return msg)
do
(if (equal line "")
then
(set content-string = (make-string (1- len)))
(read-sequence content-string in)
(push (make-field
:type (or (field-type-from-name "CONTENT")
(make-field-type :name "CONTENT"))
:value content-string)
fields)
(set (msg.fields msg) = fields)
(set (msg.date msg) =
(let date = (get-msg-field msg "DATE")
time = (parse-integer date :junk-allowed t)
do
(if time
then (fixup-msg-date msg)
time
else (decode-mail-date (get-msg-field msg "DATE")))))
(set (msg.subject msg) = (get-msg-field msg "SUBJECT"))
(set (msg.from msg) = (get-msg-field msg "FROM"))
else
;; we're still reading headers.
(set len = (- len (1+ (length line))))
(let len = (length line)
end = (or (position #\: line) len)
field-name = (string-upcase (subseq line 0 end))
field-type = (field-type-from-name field-name)
value = (subseq line (min len (+ end 2)))
do
;; see if we have a field continuation
(if (and (null field-type)
(> (length line) 0))
then
(if (or (eq (char field-name 0) #\tab)
(eq (char field-name 0) #\space))
then (set value = line)
else ;; create a new field type!
(set field-type = (make-field-type :name field-name)))
)
;;
;; if no field-type, then assume its a continuation line of the
;; previous field, so we append the value to that.
(if (null field-type)
then
(and fields
(set (field.value (first fields)) =
(concat (field.value (first fields))
value)))
else
(push (make-field
:type field-type
:value value)
fields)
)))))
value = (subseq line (min len (+ end 2)))
do
;; see if we have a field continuation
(if (and (null field-type)
(> (length line) 0))
then
(if (or (eq (char field-name 0) #\tab)
(eq (char field-name 0) #\space))
then (set value = line)
else ;; create a new field type!
(set field-type = (make-field-type :name field-name)))
)
;;
;; if no field-type, then assume its a continuation line of the
;; previous field, so we append the value to that.
(if (null field-type)
then
(and fields
(set (field.value (first fields)) =
(concat (field.value (first fields))
value)))
else
(push (make-field
:type field-type
:value value)
fields)
)))))
FCG> Is anyone aware of a lisp routine that would take a standard
FCG> email message as input, and then parse the email into its
FCG> various components such as body, date, author, etc, etc. ?
There is some scheme code meant for scsh that may do what you want.
I remember the code being adequately documented, but I have no idea
how hard it will be to convert to CL if that's what you are
after. Anyway, see:
http://www-swiss.ai.mit.edu/scsh/contrib/net/sunet.html
BM
Look at the elisp sources for gnus or rmail or VM
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
I wrote a general framework for this in Emacs Lisp some time ago. if you
have a recent Emacs, look for lisp/mail/mailheader.el. the code is close
to Common Lisp. (Allegro CL and Emacs cooperate on delivering my mail,
so this code is used a couple hundred times a day.)
#:Erik