193 lines
4.1 KiB
Plaintext
193 lines
4.1 KiB
Plaintext
# create a /tmp for here documents
|
|
rfork en
|
|
bind -c /mail/tmp /tmp
|
|
|
|
# caller should set KEY
|
|
|
|
USER=`{echo $1 | sed 's/local!//;s/[+\-].*//'}
|
|
if(! ~ $#KEY 1)
|
|
KEY=plan9
|
|
|
|
cd /mail/box/$USER
|
|
RECIP=$1
|
|
MBOX=$2
|
|
PF=/mail/box/$USER/_pattern
|
|
TMP=/mail/tmp/$pid.$sysname
|
|
BIN=/bin/upas
|
|
D=/mail/fs/mbox/1
|
|
|
|
# clean up files on exit
|
|
fn sigexit {
|
|
rm -f $TMP.*
|
|
}
|
|
|
|
fn log {
|
|
if(~ $#USER 1)
|
|
echo `{date} $* >>/mail/box/$USER/_log >[2]/dev/null
|
|
}
|
|
|
|
fn gonefishing {
|
|
if (test -e gone.fishing) {
|
|
MAILTO=`{cat $D/replyto}
|
|
grep '^'$"MAILTO'$' gone.addrs >/dev/null >[2=1] || {
|
|
echo $MAILTO >>gone.addrs
|
|
message=gone.msg
|
|
if (! test -e $message)
|
|
message=/mail/lib/gone.msg
|
|
|
|
# only respond if $USER is mentioned in To: or cc:
|
|
# header. this avoids autoresponding to mailing lists.
|
|
tohdr=`{cat $D/to}
|
|
cchdr=`{cat $D/cc}
|
|
if (~ ' '^$"tohdr^' ' \
|
|
*' '^$USER@* *!$USER' '* *' '$USER' '* ||
|
|
~ ' '^$"cchdr^' ' \
|
|
*' '^$USER@* *!$USER' '* *' '$USER' '*)
|
|
mail $MAILTO <$message
|
|
if not
|
|
status=''
|
|
}
|
|
}
|
|
if not
|
|
status='' # ensure good exit status
|
|
}
|
|
|
|
# deliver mail to a local file
|
|
fn spool {
|
|
if(~ $#* 0)
|
|
_mbox=$MBOX
|
|
if not
|
|
_mbox=$1
|
|
$BIN/deliver $RECIP $D/from $_mbox < $D/raw || exit $status
|
|
gonefishing
|
|
}
|
|
|
|
# spool but change the subject line to note spam
|
|
fn spool-tagged-spam {
|
|
if(~ $#* 0)
|
|
_mbox=$MBOX
|
|
if not
|
|
_mbox=$1
|
|
{
|
|
cat $D/rawheader | sed 's/^[Ss][Uu][Bb][Jj][Ee][Cc][Tt]:/& SPAM:/'
|
|
if(! grep -si '^subject:' $D/rawheader)
|
|
echo 'Subject: SPAM: '
|
|
echo
|
|
cat $D/rawbody
|
|
} | $BIN/deliver $RECIP $D/from $_mbox || exit $status
|
|
gonefishing
|
|
}
|
|
|
|
# forward mail to a list of addresses
|
|
fn forward {
|
|
upasname=`{awk '{print $2}' $D/unixheader} cat $D/raw | upas/send $* || exit $status
|
|
}
|
|
|
|
# pipe mail through a command
|
|
fn pipe {
|
|
if(~ $#* 0)
|
|
exit 'bad pipe command'
|
|
{cat $D/unixheader $D/raw; echo} | $* || exit $status
|
|
}
|
|
|
|
# add @domain to all unqualified addresses in the message
|
|
fn qualify {
|
|
if(! ~ $#* 1){
|
|
echo 'usage: qualify domain' >[1=2]
|
|
exit bad-qualify
|
|
}
|
|
{
|
|
sed 1q $TMP.msg
|
|
cat $TMP.msg | sed 1d | upas/smtp -fh $1 a b
|
|
} >$TMP.msg2 || exit $status
|
|
mv $TMP.msg2 $TMP.msg || exit $status
|
|
unmount /mail/fs
|
|
upas/fs -pf $TMP.msg || exit $status
|
|
}
|
|
|
|
# classify message according to token-based white list
|
|
fn tokenfilter {
|
|
if($BIN/list check $PF $D/from $D/sender $D/replyto)
|
|
echo match
|
|
if not if(~ $status *!match*)
|
|
echo !match
|
|
if not if($BIN/token $KEY $D/subject)
|
|
echo token
|
|
if not
|
|
echo new
|
|
}
|
|
|
|
# reject a message due to the token-based white list
|
|
fn tokenreply {
|
|
TOKEN=`{upas/token $KEY}
|
|
if(! ~ $#MAILTO 1)
|
|
exit 'bad token reply: no MAILTO variable'
|
|
{
|
|
cat /mail/lib/token.msg |
|
|
sed 's/TOKEN/'$TOKEN'/g;s/USER/'$USER'/g;s/MAILTO/'$MAILTO'/g'
|
|
cat $D/raw
|
|
} | upasname=/dev/null mail `{cat $D/replyto}
|
|
}
|
|
|
|
# add addresses in message to white list
|
|
fn listupdate {
|
|
$BIN/list add $PF $D/from $D/to $D/cc $D/sender
|
|
}
|
|
|
|
# microsoft virus going around 9/22/2003
|
|
fn isvirus {
|
|
virus=no
|
|
if(grep -s '\.(exe|scr|bat|com)' $D/2/2/mimeheader >[2]/dev/null){
|
|
s=`{ls -l $D/2/2/raw | awk '{print $6}'}
|
|
if(~ $s 1440??) virus=yes
|
|
}
|
|
if(~ $virus yes)
|
|
status=''
|
|
if not
|
|
status='not this virus'
|
|
}
|
|
|
|
fn hasgifattachment {
|
|
gif=no
|
|
if(grep -s '\.gif' $D/2/mimeheader >[2]/dev/null){
|
|
gif=yes
|
|
}
|
|
if(~ $gif yes)
|
|
status=''
|
|
if not
|
|
status='not this gif'
|
|
}
|
|
|
|
# bayesian spam filter. alternative to token. see /mail/lib/setup.bayes
|
|
fn isspam {
|
|
for(i in _prof.mbox _prof.spam _bounced){
|
|
if(! test -f $i){
|
|
echo 'need '^$i >[1=2]
|
|
exit 'need '^$i
|
|
}
|
|
}
|
|
{
|
|
echo '# hash table'
|
|
upas/msgcat $TMP.msg | upas/msgtok |
|
|
grep -v '^....................(.*) ' |
|
|
sed 's/$/ 1/'
|
|
} >$TMP.tok
|
|
x=`{upas/bayes -k _prof.mbox _prof.spam ~ $TMP.tok | sed 's/_prof.//'}
|
|
where=$x(1)
|
|
prob=$x(2)
|
|
prob1000=`{echo $prob '*1000' | hoc | sed 's/\..*//'}
|
|
echo `{sed 's/^From ([^ ]+) (.*)/\2 from \1/' $D/unixheader} $x >>_bounced
|
|
if(~ $where spam && test $prob1000 -lt 999)
|
|
where=mbox
|
|
upas/addhash -o _prof.$where _prof.$where 1 $TMP.tok 1
|
|
if(~ $where spam)
|
|
where=''
|
|
status=$where
|
|
}
|
|
|
|
|
|
# save and parse the mail file
|
|
sed '/^$/,$ s/^From / From /' >$TMP.msg
|
|
upas/fs -pf $TMP.msg || exit $status
|
|
|