#!/bin/sh # This is a shell archive (produced by GNU sharutils 4.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 1997-02-09 01:48 MET by . # Source directory was `/var/home/olaf/mysrc/qbsmtp'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 1389 -r--r--r-- README # 3654 -r-xr-xr-x rsmtp # 2914 -r-xr-xr-x maildir2bsmtp # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # # ============= README ============== if test -f 'README' && test X"$1" != X"-c"; then echo 'x - skipping README (file already exists)' else echo 'x - extracting README (text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && This is a simple add-on to allow qmail to process BSMTP. X The "rsmtp" program handles incoming messages. Install this where uuxqt can find it. Under the name "rcsmtp" or "rgsmtp" it will invoke gzip for uncompressing its input. X The "maildir2bsmtp" program handles outgoing messages. It takes messages from a maildir and converts them into BSMTP format, much like maildir2smtp. To use it, deliver your outgoing mail into a maildir: maildirmake /var/qmail/bsmtp; chown -R alias /var/qmail/bsmtp Put X :alias-uucp into control/virtualdomains and X /var/qmail/bsmtp/ into ~alias/.qmail-uucp-default. Then run from crontab for user "alias" the following: X maildir2bsmtp -s100000 /var/qmail/bsmtp "uucp-" \ X "gzip -cf | uux - -r -gC uucphost!rgsmtp" (note the quotes!). X maildir2bsmtp puts processed messages in the "cur" subfolder tagged "batched". It puts messages that could not be processed due to some error in the "cur" subfolder tagged "BAD". It deletes messages which are tagged "batched" and older than 24 hours from the "cur" subfolder and cleans up the "tmp" subfolder as required by maildir(5). X The programs are written in perl (4 or 5). Make sure to set the #! lines and PATH right. X The BSMTP format was essentially copied from smail. In particular, lines end with NL only. rsmtp handles incoming CRLF line endings, however. X January 1997 - Olaf Titz SHAR_EOF $shar_touch -am 0204122797 'README' && chmod 0444 'README' || echo 'restore of README failed' shar_count="`wc -c < 'README'`" test 1389 -eq "$shar_count" || echo "README: original size 1389, current size $shar_count" fi # ============= rsmtp ============== if test -f 'rsmtp' && test X"$1" != X"-c"; then echo 'x - skipping rsmtp (file already exists)' else echo 'x - extracting rsmtp (text)' sed 's/^X//' << 'SHAR_EOF' > 'rsmtp' && #!/usr/local/bin/perl4 X # RSMTP for qmail by Olaf Titz , Jan.97, public domain # $Id: rsmtp,v 1.2 1997/02/09 00:47:21 olaf Exp $ X # Take BSMTP on standard input and feed it into qmail-queue. # Attempt to generate a bounce message on error. # If invoked as r[cgfz]smtp, call gzip for unpacking. X $version="$0-qm-ot 0.4"; $version=~s:^.*/::g; $ENV{"PATH"} = "/bin:/usr/bin:/var/qmail/bin"; if (open(F, "/var/qmail/control/me")) { X $me=; close F; } $me=~s/[^\040-\177].*$//; $me="UNKNOWN" unless $me; # Should not happen unless (($i,$j,$uidsend)=getpwnam("qmails")) { $uidsend=32766; } unless (($i,$j,$uidsmtp)=getpwnam("qmaild")) { $uidsmtp=32766; } @Month=("Jan", "Feb", "Mar", "Apr", "May", "Jun", X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); X if ($0=~/r[cgfz]smtp/) { X while (1) { X $zippid=open(ZIP, "gzip -cdf |"); X last if defined($zippid); X sleep 30; X } X open(STDIN, "<&ZIP"); } X sub qmailopen # helo, proto, uid, to { X local($helo, $proto, $uid, @t)=@_; X pipe(XCTL, CTL) || die "can't pipe"; # XX error handling? X while (1) { X $pid=open(QMAIL, "|-"); X last if defined($pid); X sleep 30; X } X if (!$pid) { X open(STDOUT, "<&XCTL"); # yes, it uses stdout as input X close CTL; close XCTL; close STDERR; X ($<,$>)=($uid,$uid); X exec "qmail-queue"; X exit 126; X } X close XCTL; X @d=gmtime; X printf QMAIL X # really got this 822-conformant... ugh X "Received: from $helo by $me with $proto ($version) for %s%s; ". X "%d %s %d %02d:%02d:%02d -0000\n", X $t[0], $#t==0 ? "" : " (and ".join(",", @t[1..$#t]).")", X $d[3], @Month[$d[4]], $d[5]+1900, $d[2], $d[1], $d[0]; } X sub qmailfinish # from, to... { X local($snd, @rcp)=@_; X printf CTL "F%s%c", $snd, 0; X foreach (@rcp) { X printf CTL "T%s%c", $_, 0; X } X printf CTL "%c", 0; X close CTL; close QMAIL; X return ($?>>8); } X sub addr { X local($_)=@_; X /\<([^>]*)\>/ && do { X $_=$1; X }; X s/[^\040-\177].*$//; # XX X return $_; } X sub procdata { X while () { X s=\r\n=\n=; X if ($_ eq ".\n") { X return 1; X } X s=^\.\.=.=; X print QMAIL; X } X return 0; } X sub err { X local($e)=@_; X $t=($from || "postmaster"); X $helo || ($helo="(UNKNOWN)"); X &qmailopen($me, "QSBMF", $uidsend, $t); X print QMAIL <<"_END"; XFrom: MAILER-DAEMON\@$me To: $t Subject: Failed mail X Hi. This is the rsmtp mail receiver at $me. While processing mail sent by $helo, the following error occurred: $e Therefore I could not deliver mail to the following address(es): X _END X foreach $_ (@rcpt) { X printf QMAIL "<$_>:\nBSMTP protocol error\n"; X } X print QMAIL <<"_END"; X --- Below is the original message, if it could be recovered. X _END X &procdata; X &qmailfinish("", $t); X exit 1; } X sub dodata { X &err("Missing HELO") unless defined($helo); X &err("Missing MAIL") unless defined($from); X &err("Missing RCPT") unless ($#rcpt>=0); X &qmailopen($helo, "BSMTP", $uidsmtp, @rcpt); X &procdata || X print QMAIL <<"_END"; X -- Note from the mail delivery system -- The message apparently arrived truncated at $me See the header Received lines matching this name for tracking down the error _END } X while () { X s=\r\n=\n=; X /^HELO\s*(.*)$/i && do { X $helo=$1; X undef $from; X undef @rcpt; X next; X }; X /^MAIL\s+FROM:?\s*(.*)$/i && do { X $from=&addr($1); X next; X }; X /^RCPT\s+TO:?\s*(.*)$/i && do { X push(@rcpt, &addr($1)); X next; X }; X /^DATA/i && do { X &dodata; X if ($x=&qmailfinish($from, @rcpt)) { X exit $x; X } X undef @rcpt; X next; X }; X /^QUIT/i && do { X last; X }; } $s=($helo)?0:128; X if ($zippid) { X close ZIP; X $s+=($?>>8); } exit $s; SHAR_EOF $shar_touch -am 0209014797 'rsmtp' && chmod 0555 'rsmtp' || echo 'restore of rsmtp failed' shar_count="`wc -c < 'rsmtp'`" test 3654 -eq "$shar_count" || echo "rsmtp: original size 3654, current size $shar_count" fi # ============= maildir2bsmtp ============== if test -f 'maildir2bsmtp' && test X"$1" != X"-c"; then echo 'x - skipping maildir2bsmtp (file already exists)' else echo 'x - extracting maildir2bsmtp (text)' sed 's/^X//' << 'SHAR_EOF' > 'maildir2bsmtp' && #!/usr/local/bin/perl4 X # BSMTP for qmail by Olaf Titz , Feb.97, public domain # $Id: maildir2bsmtp,v 1.2 1997/02/09 00:47:21 olaf Exp $ X # maildir2bsmtp [-h holdtime] [-s maxsize] dir prefix [command] # take messages from maildir "dir", make BSMTP out of them # Remove "prefix" prefix from every recipient address # keep delivered messages in 'cur' subdir for "holdtime" seconds (0: forever) # if "command" is given, pipe into this command # if "maxsize" is given, start a new command when this size was exceeded X require "getopts.pl"; $opt_h=86400; # one day &Getopts("h:s:"); umask(0077); $ctl="/var/qmail/control"; X $maildir=shift || &fatal('required "dir" parameter missing'); chdir $maildir || &fatal("cannot chdir to `$maildir'"); $prefix=shift || &fatal('required "prefix" parameter missing'); $comm=shift; X opendir(D, "new") || &fatal("cannot read `new' subdir"); while ($_=readdir(D)) { X /^[0-9]/ && push(@f, $_); } closedir(D); if ($#f<0) { X &cleanup(0); } @files=sort {$a<=>$b} @f; # this puts oldest message first X if (open(H, "$ctl/helohost") || open(H, "$ctl/me")) { X $helo=; close H; } $helo=~s/[^\040-\177].*$//; $helo="UNKNOWN" unless $helo; X while ($#files>=0) { X if ($comm) { X open(STDOUT, "|$comm") || &fatal("cannot invoke `$comm'"); X } X select STDOUT; $|=1; X print "HELO $helo\n"; X $bsiz=0; X File: while ($f=shift(@files)) { X if (open(F, "new/$f")) { X $_=; X if (!/^Return-Path:\s*\<([^>]*)\>/i) { X &badmsg($f, "no/bad Return-Path line"); next; X } X $fr=$1; X $_=; chop; X if (!/^Delivered-To:\s*(.*)$/i) { X &badmsg($f, "no/bad Delivered-To line"); next; X } X $_=$1; s/^$prefix//o; X print "MAIL FROM:<$fr>\nRCPT TO:<$_>\nDATA\n"; X while () { X s/^\./../; X print; X }; X print ".\n"; X $bsiz+=(-s F); X close F; X if (!rename("new/$f", "cur/$f:batched")) { X print STDERR "cannot move `$f', will re-deliver\n"; X } X last File if ($opt_s && ($bsiz>$opt_s)); X } else { X print STDERR "message `$f' vanished\n"; X } X } X print "QUIT\n"; } &cleanup(0); Xexit 0; X sub badmsg # filename, explanation { X local($f,$m)=@_; X print STDERR "message `$f': $m\n"; X if (!rename("new/$f", "cur/$f:BAD")) { X print STDERR "cannot move `$f' - something is wrong\n"; X } } X sub cleandir # dirname, suffix, time { X local($d,$s,$t)=@_; X if (!opendir(D, $d)) { X print STDERR "cannot read `$d' subdir\n"; X return; X } X while ($_=readdir(D)) { X next unless /^[0-9].*$s$/; X if (@S=stat("$d/$_")) { X unlink("$d/$_") if ($S[9]+$t<$^T); X } else { X print STDERR "cannot stat `$f'\n"; X } X } X closedir(D); } X sub cleanup # exitstatus { X local($e)=@_; X &cleandir("tmp", "", 129600); # 36h - maildir spec X &cleandir("cur", ":batched", $opt_h) if ($opt_h); X exit $e; } X sub fatal # message { X local($_)=@_; X print STDERR "$_\n"; X exit 111; } SHAR_EOF $shar_touch -am 0209014797 'maildir2bsmtp' && chmod 0555 'maildir2bsmtp' || echo 'restore of maildir2bsmtp failed' shar_count="`wc -c < 'maildir2bsmtp'`" test 2914 -eq "$shar_count" || echo "maildir2bsmtp: original size 2914, current size $shar_count" fi exit 0