mboxrd-read
(require mboxrd-read) | package: mboxrd-read |
procedure
(mboxrd-parse path) → (stream/c (list/c bytes? bytes?))
path : path?
You are responsible for any locking needed to protect the file from modification while it’s being read. Different MUAs and MDAs have different locking protocols. Good luck.
procedure
(mboxrd-parse/port port) → (stream/c (list/c bytes? bytes?))
port : input-port?
NB: this procedure assumes that it’s the only one reading the port. Bad stuff will happen if its not; it doesn’t leave the "From " of the next message on the stream.
EFFECT: reads from stream, closes it when peek-char returns eof.
1 mboxcl2
Well, it turns out that dovecot actually uses mboxcl2. Ah well. In fact, mboxcl2 looks like a bit of a win; since it uses Content-Length to locate the next header, it should be possible to parse faster, since you can set the file position rather than scanning those hideously long base64 body strings looking for the next line starting with "From ". The down side is that since the body strings aren’t read eagerly, closing the file port is a separate operation that you’re responsible for.
procedure
(mboxcl2-parse path [#:fallback fallback?])
→
(-> void?) (stream/c (list/c bytes? (-> bytes?))) path : path-string? fallback? : boolean? = #f
When fallback? is true, a message whose header lacks a Content-Length field will instead be processed by searching forward for a line beginning with "From ".
Please note that the header gets rfc822-style newlines, but the body does not.
Note that after the closer function is called, it’s not possible to extend the lazy list or to extract bodies.
Again, you are responsible for any locking required to protect this file from modification while it’s being read.
2 maildir
Despite its increasingly narrow name, this package now also parses maildir directories, with a similar interface.
procedure
→ (stream/c (list/c (or/c bytes? false?) (-> (or/c input-port? false?)))) path : path-string?
Maildir was designed to avoid the need for locking, and indeed, it’s less problematic in this regard than other formats. The most likely problem is that the list of files will change while you’re looking at the directory. This may mean that the lazily constructed stream will contain references to files that aren’t there any more by the time you ask for their headers or their bodies, which means that both headers and body-ports can wind up being false. Beyond this, though, you don’t need to worry about locking.
3 leftovers
Additionally, you can use the utilities (e.g. extract-field and validate-headers) in "net/head" to process the header.
Let me know of any bugs.
John Clements