In Unix terms, fetchmail is an
uncomfortably large program that bristles with options. Thinking
about the way mail transport works, one might think it would be
possible to decompose it into a pipeline. Suppose for a moment it were
broken up into several programs: a couple of fetch programs to get
mail from POP3 and IMAP sites, and a local SMTP injector. The
pipeline could pass Unix mailbox format. The present elaborate
fetchmail configuration could be replaced
by a shellscript containing command lines. One could even insert
filters in the pipeline to block spam.
#!/bin/sh
imap [email protected] | spamblocker | smtp jrandom
imap [email protected] | smtp jrandom
# pop [email protected] | smtp jrandom
This would be very elegant and Unixy. Unfortunately, it can't
work. We touched on the reason earlier; pipelines are
unidirectional.
One of the things the fetcher program
(imap or pop)
would have to do is decide whether to send a delete request for each
message it fetches. In fetchmail's present
organization, it can delay sending that request to the POP or IMAP
server until it knows that the local SMTP listener has accepted
responsibility for the message. The pipelined, small-component
version would lose that property.
Consider, for example, what would happen if the
smtp injector fails because the SMTP
listener reports a disk-full condition. If the fetcher has already
deleted the mail, we lose. This means the fetcher cannot delete mail
until it is notified to do so by the smtp
injector. This in turn raises a host of questions. How would they
communicate? What message, exactly, would the injector pass back?
The global complexity of the resulting system, and its vulnerability
to subtle bugs, would almost certainly be higher than that of a
monolithic program.
Pipelines are a marvelous tool, but not a universal one.