aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/multidrop
blob: 37f87b4c6d815751680a8dbe7f504967a6f47c95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
From mlievaart@orion.nl  Mon Jan 10 10:46:33 2000
From: Martijn Lievaart <mlievaart@orion.nl>
To: Eric S. Raymond <esr@thyrsus.com>
Date: zondag 9 januari 2000 0:38
Subject: Re: Thanks for fetchmail and a solution to the multidrop problem (I
Status: O
Content-Length: 8086
Lines: 226

think)

Hello Eric,

Let me first state that I'm no sendmail nor unix guru, so although this
seems to work, I certainly would not say this is the "best" solution. In
fact I would welcome all comments to make this better. In particular, it
seems that that the mailertable feature was made just for this, but I'm
still studying that.

Also, This mail will have lines wrapped. I will put up this on a website
asap, so people can download the relevant portions. In the meantime, I'm
using (stuck on) Outlook, so I won't even attempt to format this mail.
Accept my apoligies and try to mentally reconnect the lines.

Finally, this mail is a bit lengthy, but I guess it is better to get all
information in, so please bear with me.

After some very frustrating attempts to get multidrop to work reliably, it
suddenly hit me. When sendmail has translated the recipient to the mailbox,
the recipient is gone (in the cases we're talking about). So the solution is
not to let sendmail do this translation (completely).

The trick is to let a custom MDA be called with both the mailbox and the
full recipient name. This MDA then just stuffs it in the correct mailbox
after adding the appropriate headers. Luckily I hit on the formail utility.
It reformats a mailmessage and does just what I wanted. Specifically my
script uses it to:
- add a custom header (default: "Delivered-To:") with the recipient
- rewrite the message-ID, so fetchmail will download the same message
multiple times.
- add another header, just for fun.

The rewriting of the message-ID is needed because fetchmail will suppress
multiple messages with the same ID, normally a good idea, but now it gets in
the way. A switch on fetchmail to suppress this behaviour would be great.

At first I hardcoded the domains in the sendmail.cf, but I quickly set out
to do one better and came up with the following solution. In sendmail.cf,
add the following line somewhere at the top.

Kmultidroptable hash -o /etc/mail/multidroptable

this defines a table for all domains we want to use multidrop for. The
format of this file is multiple lines of the format:
<domain>    <mailbox>

e.g:
mailtest.orion.nl       mailtest
mailtest2.orion.nl      mailtest
mailtest3.orion.nl      mailtest
bvh-communicatie.nl     b.bvh
krakatau.nl             b.bvh
personeelzaak.nl        b.bvh
maslowassociates.nl     b.bvh
rtij.nl                 rtij

Of course, create a .db file with makemap. Also, the domains must be added
to class w, so they should be added to your sendmail.cw or RelayTo file, or
whatever you use.

Now add to sendmail.cf:

R$+ < @ $* . >                          $: <MULTIDROP> $(multidroptable $2
$: <NO> $) <?> $1 < @ $2 . >
R<MULTIDROP> <NO> <?> $*                $: $1
R<MULTIDROP> $+ <?> $+ < @ $* . >       $#drop $@ $2 @ $3 $: $1

These lines should be above the existing lines that read:

# short circuit local delivery so forwarded email works
R$=L < @ $=w . >        $#local $: @ $1         special local names
R$+ < @ $=w . >         $#local $: $1                   regular local name

This works as follows (in fact these comments are above my modification in
our sendmail.cf).
#
# MLI. Any drop host gets passed to the drop script
#
# The first rule looks up the domain in the multidrop table.
# The input at this point is always:
#       user@<dom.ain.>
#  If found, the resulting line looks like this:
#       <MULTIDROP> mailbox <?> user@<dom.ain.>
# if not found, the resulting line will be:
#       <MULTIDROP> <NO> <?> user@<dom.ain.>
# The second line restores the "not found" case back to user@<dom.ain.>
# So if this domain was found in the multidroptable, we still have a line
starting with <MULTIDROP>
# as shown above. The third line hands this to the drop script.
#
# Note that the user ($:) is the mailbox this message should be stuffed in,
the host ($@) is the full
# user@<dom.ain>. This is how the dropscript expects it.
#

I guess sendmail guru's are now laughing their pants off, and I hope someone
will show me a better way to achieve this. For now, it works.

Next, we need to define mailer drop (somewhere in the sendmail.cf)

#
# multidrop pop3 support.
#

Mdrop,          P=/usr/local/bin/dropmail, F=lFS,
                T=X-Unix,
                A=dropmail $u $h

The S flag here is crucial, otherwise the dropmail script won't run as root,
and under linux (==bash) suid scripts are not permited. I gather most unices
now disalow suid scripts, so this would be necessary on most unices. There
probably are other flags that would make this better, but this works, so I
decided to divert my attention to other tasks at hand (busy, busy, busy....
;^>).

Now we only need the dropmail script, /usr/local/bin/dropmail, mode 700. It
looks big, but effectively one pipeline does the real work. The rest is
configuration, error checking and locking the mailbox.

#!/bin/bash

#
# Script to force a mail message in a format that fetchmail will recognise.
# use as a MDA from sendmail. Must be executed with F=S.
#

#
# Configuration:
#
maildir=/var/spool/mail
envelope=Delivered-To:

#
# set PATH to a known value to avoid some security issues
#
export PATH=/bin:/usr/bin

#
#
#
to=$2
user=$1
mbox=$maildir/$user

#
# If the mailbox does not exist, create it. Note that we act pretty
paranoid, this is hopefully
# resistant to symlink attacks
#
if [ ! -f $mbox ]
then
        oldumask=`umask`
        umask 077
        touch $mbox
        chmod 660 $mbox || exit 1
        chown $user $mbox || exit 1
        chgrp mail $mbox || exit 1
        umask $oldumask
fi

# First lock the mailbox, if this doesn't succeed in 64 seconds, give up and
send
# mail to postmaster.
# If this period is to short, increase the retries (-r flag to lockfile)
#
# Then run the message through formail to get it into the right mailbox
format with the
# right headers added.
#
# Delivered-To will make fetchmail propagate this mail to the correct user
when
# run with '-E "Delivered-To"'. Set this in the advanced settings of the
TeamInternet f.i.
# (if you changed the envelope at the start of this script, adapt this
accordingly)
#
# We also muck up the messageid, so fetchmail will never skip a message on
the basis of
# duplicate messageIDs. The -i "Message-ID" will rename the old message ID,
the -a will
# add a new one.
#
# Lastly, we add a header indicating which host did the rewriting.
#

if lockfile -r 8 $mbox.lock >/dev/null 2>&1
then
        cat - | formail -i "$envelope <$to>" -i "Message-ID:" -a
"Message-ID:" -i "X-Multidrop-Processing: <`hostname`>" >>$mbox
        rm -f $mbox.lock
else
        (echo "Subject: Cannot lock mailbox for $user" & cat -) |
/usr/lib/sendmail postmaster
fi

#
# EOF
#

This obviously is very Linux (even RedHat?) dependant, locking mailboxes,
creating mailboxes with the right permissions, probably even bash dependent.
I would say that it should be fairly easy to port to other systems, but
alas, my unix knowledge is lacking for that. I'll also rewrite it someday,
a.o. that umask handling can be done much better and the location of the
sendmail binairy should not be fixed.

Now the only thing left to do is to retrieve the mail with fetchmail, using
'envelope "Delivered-To:"' in the poll line. The above script has added this
line, so this is all that fetchmail needs.

All parts of this solution need carefull examination. In particular I think
the new rule lines may not catch all cases, although they worked for
everything I threw at them and work satisfactorily in production. I'm also
wondering if there is a more standard way to drop something in a mailbox. I
yet have to investigate procmail, but all other MDA's mucked with the
message and effectively undid my carefully added header. I'll experiment
some more and rethink it all as I learn more.

I'm still wondering, if I can get formail to include another received
line.... "Received from localhost by dropmail for <user>...." to make it
work without the envelope flag. Well I'll have to experiment. Do you know if
there is a header I can add so fetchmail works out-of-the-box?

Regards,
Martijn Lievaart
iticism. * It is now possible to specify multiple local recipients by giving a list of names following "to" or "is". Each local recipient is checked for in the To:, Cc: and Bcc: headers of each message; if a match is found, the message is sent to that local recipient. This makes it possible to do mailing lists and multidrop mailboxes. See the man page for details (and note the caveat in the BUGS AND KNOWN PROBLEMS section). * It is possible to specify a size limit for retrieved messages. I resisted doing this because I don't want fetchmail to be in the filtering game, but too many Europeans begged for it because their telecomms monopolies are price-gouging them on per-second phone charges. I will ignore, or be extremely rude to, anyone who takes this feature as a license to beg me for kill files or any other form of content-based filtering. Use procmail on your server if you want that. * If you use an MDA, the internal changes to support multi-drop mailboxes require that you *remove* the %s at the end of your MDA string. Local delivery addresses will be appended to the end of the command in the obvious way. * The first message from a query now includes the number of old messages when this can be determined (that is not under POP2). * POP3 UID support really works now. I make rude noises at the POP3 mavens who forced us to this with RFC1725, but thank Al Longyear <longyear@sii.com> for fixing and verifying my slightly buggy implementation. * Kerberos support ditto. Thanks to Chris Hanson <cph@martigny.mit.edu> for this feature. * When there's a daemon fetchmail in background, running fetchmail in foreground without --quit now tries to wake the daemon and force it to poll immediately. * Add option to set server nonresponse timeout. * Password is no longer displayed in verbose mode. * You may use C-like escapes to embed non-printables in passwords and other strings. Fetchmail -V will display them in a printable form. * Program now tries to set itself to the ID of the local user before running an MDA, and reset to root afterwards. This will work on any system with seteuid(2), including Linux and the BSDs. bugs -- * Default user name to deliver to is now the calling user, unless program is running as root in which case it is the remote user name (default can be overridden with an `is' or `to' declaration). In versions up to 1.7 it was the calling user; in 1.8 the remote user ID. This created some confusion. * Accept RFC822 headers with a tab after the colon. * You now see a "skipping" message for each message not retrieved. * --keep no longer overrides --flush. * Rewrite "To: jrh (J. Random Hacker)" correctly. * Find "nnn octets" anywhere on a POP3 server's RETR response line. * Fixed various bugs in --check. It now reports PS_SUCCESS only if there is new mail waiting. * Under Linux, if fetchmail is run in daemon mode with the network inaccessible, each poll leaves a socket allocated but in CLOSE state (this is visible in netstat(1)'s output). These sockets aren't garbage-collected until fetchmail exits. When whatever kernel table is involved fills up, fetchmail can no longer run even if the network is up. To avoid this, fetchmail now commits seppuku after some number of unsuccessful socket opens. * Don't try using FLAGS.SILENT, some allegedly IMAP2bis servers seem to choke on it. fetchmail-1.8 (Fri Oct 11 15:08:10 EDT 1996): features -- * Use kill(0, pid) to make lock handling a bit smarter (thanks to Johan Vromans <JVromans@squirrel.nl> for the suggestion). * Arrange for timeout of client after 5 minutes if connection to server is dropped (thanks to Gaspar Sinai <gsinai@gol.com>). * All pretensions to RPOP support have been dropped. Yes, this is a feature, RPOP is very vulnerable to spoofing! Use APOP instead. * Normal start-of-read message now displays the byte (excuse me, "octet") size of the message. Yes, 3schwend, you can stop noodging me now :-). * Normal progress notifications now take only 1 line per message, not 2. * Linux packagers: building fetchmail now generates an RPM specfile for it. * Kerberos support via KPOP protocol (thanks to Chris Hanson). * New --check option for asking server whether there is mail without actually retrieving or deleting it. * UID support is back by popular demand. Bletch. * Permit spaces in IMAP passwords (ship them as quoted strings). bugs -- * Fix buggy getopt specification of P and p options. * Fix uninitialized-variable bug that was hanging second IMAP queries. fetchmail-1.7 (Tue Oct 8 11:32:44 EDT 1996): features -- * Noise words for rcfile syntax make English-like syntax possible. * Make configure more GNUish; it understands --prefix and other standard autoconf options now (see INSTALL for details) * Better documentation of the new .fetchmailrc extensions and the slightly stricter rules for ordering options. * Expanded installation instructions including how to test for correct operation without losing mail to misconfigured MDAs, alias loops, etc. bugs -- * You may have to rearrange the order of options in your .fetchmailrc. The grammar for the new multiple-user syntax requires that server options (protocol and port) come before any user options. * Fixed core dump bug that was screwing configurations with no .fetchmailrc. * Fixed broken 'p' option. * `norewrite' and `rewrite' in .fetchrc were the inverses of what they should have been (but the rewrite default was set correctly). fetchmail-1.6 (Sun Oct 6 20:55:09 EDT 1996): features -- * You can now have multiple entries for the same server but different users, and the right thing will happen (each user's mailbox will be queried). Even better, you can now specify multiple users in a single server entry. * Restore --mda, seems some people either can't run a port 25 listener due to bizarre dynamic-SLIP problems, or won't for security reasons. * When delivering to an MDA, print error and die (before deleting the message!) if the MDA returns nonzero status. Better safe than sorry. * If fetchmail is called through a link named `popclient' it will look in ~/.poprc for a run control file. Unless that file includes the deleted options limit and localfolder this should actually work. bug fixes -- * Makefile fixes for correct linking on Sparcs and avoiding duplication of the md5 files (leading to harmless install-time error messages). * Fix a bonehead coding error in pop3_delete() that was masked by the Intel register architecture. *blush* Thanks to Jay Anderson <anderson@optical.bms.com>. * Fix bug that prevented SMTP from being specified on the defaults line. * Allow program to generate correct lockfiles when USER is undefined (i.e. under zsh). * Allow program to run with no .fetchmailrc file again. fetchmail-1.5 (Thu Oct 3 04:35:15 EDT 1996): * Naturally, my decision to announce 1.4 on comp.os.linux.announce immediately caused the code to manifest its first real bug -- a core dump when the "From:" header is spelled "from:" (all lower case). Fixed. * Update and expansion of NOTES. * The --all and --flush flag validity checks move to driver.c. fetchmail-1.4 (Wed Oct 2 09:22:37 1996): * More man page improvements. * Lexer changes to work around bison's "feature" of silently ignoring 0-value tokens (caused options nokeep, norewrite, nofetchall, noskip to be no-ops). fetchmail-1.3 (Tue Oct 1 05:49:49 1996): * Significant man page improvements. * Escapes for newlines in .fetchmailrc are now optional. * Kill off -2 and -3 options, redundant popclient remnants. * IMAP code simplification and robustification. Use FETCH FLAGS to find seen messages. Code should now work even if unseen messages are interspersed with seen ones, and even if messages are appended to the mailbox during the run. fetchmail-1.2 (Sat Sep 28 15:40:50 EDT 1996): * The great option massacre. Remove --stdout, --limit, --local, --mda. We get a significant code and complexity shrinkage this way (a lot of the configuration machinery goes away too). These things are your MDA's job. (This also kills off the lose-mail-on-disk-full bug, which I've never seen but two users reported.) * Link APOP support by default. * Fix embarrassing Makefile bug. fetchmail-1.1 (Sat Sep 28 09:21:10 EDT 1996): * In POP3, don't send LAST if STAT shows count of waiting messages to be zero. * Document APOP better, we know it works now. * Lose the .fetchids file and give up on POP3 UIDs, they're a dead loss. fetchmail-1.0 (Thu Sep 26 11:59:38 EDT 1996): * SMTP forwarding and header-rewrite features work with POP2 now. * Stricter RFC822 conformance, so SMTP to qmail works. Thanks to Cameron MacPherson <unsound@oz.net> for these changes. * The program is quieter but more informative now (suppress printing of server greeting message; add the server host being queried to the message count information line). * Add `skip' option to make it easier to set up test entries. * Name change (it ain't just for POP any more). popclient-3.2 (Mon Sep 23 13:29:46 EDT 1996): * RPOP support (coded at a user's request but untested). * Ported to QNX (see the Makefile). * Add code by Michael Schwendt <3schwend@informatik.uni-hamburg.de> for improved sizeticker. * Improved RFC822 parsing (thanks to Rob Funk). * Move the per-user lockfile to /tmp so it gets cleared at reboot time. * Warn users that running concurrent instances of popclient is a bad idea. * Try USER and HOME to set defaults before going to the password file. This should work better in Sun NIS environments. popclient-3.1 (Thu Sep 12 15:45:25 EDT 1996): * MDA arguments are now dumped when using the -V option. * Sendmail delivery from background seems to work now. * We have IMAP2bis/IMAP4 support. * Code now autoprobes for a POP3, IMAP, or POP2 server if no protocol is specified. * SMTP forwarding support. Thanks to Harry Hochheiser <harry@tigger.jvnc.net> for this simple but clever idea. It's now the default delivery mode. * If no UNIX From line is found, popclient will now synthesize a correct line from the RFC822 From line. * It is now possible to specify the host TCP/IP port number to connect to. popclient-3.05 (Thu Aug 22 22:59:04 EDT 1996): * Experimental support for RFC1725-compliant POP servers with the UIDL command and without LAST. popclient-3.04 (Wed Aug 21 00:22:44 EDT 1996): * Logfile option works. popclient-3.03: * Minor bug fixes for password querying and redirection to stdout. popclient-3.02 (Fri Jul 19 11:37:56 EDT 1996): * Correct buggy processing of nokeep/noflush/fetchall. * Fix buggy -mda option processing. * Added -N/--norewrite option. * Delivery via sendmail now works in non-daemon mode. popclient-3.01 (Mon Jul 1 13:33:51 EDT 1996): * Fixed a lexical analyzer bug in quoted-string processing. * Fixed a bug in dump_options that caused username to be displayed incorrectly. * The lock assertion code was in the wrong place relative to the daemonize() call. popclient-3.0 (Fri Jun 28 11:33:34 EDT 1996): Eric S. Raymond <esr@thyrsus.com> hacked extensively on 3.0b6 and took over the package with the consent of Carl Harris, the original implementor. Some of the 3.0 feature additions were inspired by Sean Oh's fetchpop 1.8 code, and a few use code directly lifted from fetchpop. Here are my (Eric's) change notes: CONFIGURATION AND BUILDING * The autoconfigure script incorrectly assumed that all Linuxes use /usr/bin/deliver. Under Linux it now checks for both /usr/bin/delivermail and /bin/mail. * I added a distribution-maker production to Makefile.in. OPTIONS AND COMMAND LINE * I have removed the -p command-line option. Given that there's a run control facility there is no excuse for encouraging users to put plaintext passwords in scripts which might be readable. * Calling popclient with no arguments now causes it to query or operate on every host in the run control file. * I have made --version more useful by having it dump the computed connection options for each server specified. * The user can now explicitly set an MDA (such as procmail) with the new option -m or -mda. Various possible MDAs are listed on the man page. POPRC FILE SYNTAX * The run control file lexer now supports "-enclosed strings which may contain whitespace. * I added a --yydebug option to enable run control parser debugging at runtime if the parser was generated with --debug. It's not documented. * You may now have a `defaults' entry in the run control file which sets overrideable values for other entries. See the man page for details. * It is now possible to set keep, flush and fetchall in your run control file. * Fixed incorrect numbering of source lines in run control file parse error messages. * The configure.in specification no longer uses the obsolete AC_TRY_COMPILE macro (it uses AC_TRY_LINK instead). MAILBOX LOCKING * I have added mandatory locking of mailbox files where supported. This will cover Linux systems, in particular. * The default behavior is now to do lock-protected append on the user's system mailbox rather than using delivermail or some other MDA. (This is a performance hack.) * The autoconfigure script now looks for standard mail locations. The default mail delivery agent is used only if it can't find a mail spool directory in the standard places. FUNCTIONAL ENHANCEMENTS * When using POP3, message headers are edited so that replies won't foo up. Anything that looks like a mail ID local to the POP host gets @ and the pop servername attached to it before being appended to the user's mailbox or passed to an MDA. * I have implemented daemon mode. * I have added a lock check to ensure that there is only one popclient running per user, and a --quit option to kill the currently running one. DOCUMENTATION * All changes and feature additions have been tested in actual use and are documented on the man page. * I have turned the comments in the sample run control file into a new manual section documenting the file format. MISCELLANEOUS BUG FIXES * I fixed some de-initialization bugs in pop2.c and pop3.c that led to fd leaks (these became painfully obvious when I tested daemon mode!). * I've fixed the flaky parser error messages. They turned out to be due to a misdeclaration of yytext. These are Carl Harris's change notes from previous releases: 3.0b5 o "From " header fix in pop2.c and pop3.c o Surpress "..." output when --stdout option specified in pop3.c 3.0b4 o alloca fix. o various diagnostic/informational message fixes. 3.0b3 o Support for retrieving only new messages from maildrop when using POP3. o Support for retrieving only the first n lines of each message when using POP3. o APOP authentication support. o Buffered socket input. 3.0b2 This is a "new features" release. o support for .poprc file. o GNU-style long options. o fixed passwords appearing in 'ps' output o support for multiple servers on one command line 3.0b1 This is mostly a test of the autoconfigure integration. Among the functions performed by the new configure script, is the ability to detect known system types, configures the mail delivery agent (MDA) correctly. This should permanently solve the problem of using something other than an MDA for mail delivery (which continues to plague Linux slackware 1.2.9). For this beta, please check the values of MDA_PATH and MDA_ARGS carefully. They should match the values found in your sendmail.cf file on the line which begins with "Mlocal". Other changes from popclient version 2.21: o no longer uses getpass() from the C library. The internal getpassword() function allows the use of long passwords. o integrated GNU getopt() for long options. Long option names will appear in a future beta. o Several compiler warnings fixed. o Fixed problems related to missing include files in Solaris port.