pipeto.lib 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. # create a /tmp for here documents
  2. rfork en
  3. bind -c /mail/tmp /tmp
  4. # caller should set KEY
  5. USER=`{echo $1 | sed 's/local!//;s/[+\-].*//'}
  6. if(! ~ $#KEY 1)
  7. KEY=plan9
  8. cd /mail/box/$USER
  9. RECIP=$1
  10. MBOX=$2
  11. PF=/mail/box/$USER/_pattern
  12. TMP=/mail/tmp/$pid.$sysname
  13. BIN=/bin/upas
  14. D=/mail/fs/mbox/1
  15. # clean up files on exit
  16. fn sigexit {
  17. rm -f $TMP.*
  18. }
  19. fn log {
  20. if(~ $#USER 1)
  21. echo `{date} $* >>/mail/box/$USER/_log >[2]/dev/null
  22. }
  23. fn gonefishing {
  24. if (test -e gone.fishing) {
  25. MAILTO=`{cat $D/replyto}
  26. grep '^'$"MAILTO'$' gone.addrs >/dev/null >[2=1] || {
  27. echo $MAILTO >>gone.addrs
  28. message=gone.msg
  29. if (! test -e $message)
  30. message=/mail/lib/gone.msg
  31. # only respond if $USER is mentioned in To: or cc:
  32. # header. this avoids autoresponding to mailing lists.
  33. tohdr=`{cat $D/to}
  34. cchdr=`{cat $D/cc}
  35. if (~ ' '^$"tohdr^' ' \
  36. *' '^$USER@* *!$USER' '* *' '$USER' '* ||
  37. ~ ' '^$"cchdr^' ' \
  38. *' '^$USER@* *!$USER' '* *' '$USER' '*)
  39. mail $MAILTO <$message
  40. if not
  41. status=''
  42. }
  43. }
  44. if not
  45. status='' # ensure good exit status
  46. }
  47. # deliver mail to a local file
  48. fn spool {
  49. if(~ $#* 0)
  50. _mbox=$MBOX
  51. if not
  52. _mbox=$1
  53. $BIN/deliver $RECIP $D/from $_mbox < $D/raw || exit $status
  54. gonefishing
  55. }
  56. # spool but change the subject line to note spam
  57. fn spool-tagged-spam {
  58. if(~ $#* 0)
  59. _mbox=$MBOX
  60. if not
  61. _mbox=$1
  62. {
  63. cat $D/rawheader | sed 's/^[Ss][Uu][Bb][Jj][Ee][Cc][Tt]:/& SPAM:/'
  64. if(! grep -si '^subject:' $D/rawheader)
  65. echo 'Subject: SPAM: '
  66. echo
  67. cat $D/rawbody
  68. } | $BIN/deliver $RECIP $D/from $_mbox || exit $status
  69. gonefishing
  70. }
  71. # forward mail to a list of addresses
  72. fn forward {
  73. upasname=`{awk '{print $2}' $D/unixheader} cat $D/raw | upas/send $* || exit $status
  74. }
  75. # pipe mail through a command
  76. fn pipe {
  77. if(~ $#* 0)
  78. exit 'bad pipe command'
  79. {cat $D/unixheader $D/raw; echo} | $* || exit $status
  80. }
  81. # add @domain to all unqualified addresses in the message
  82. fn qualify {
  83. if(! ~ $#* 1){
  84. echo 'usage: qualify domain' >[1=2]
  85. exit bad-qualify
  86. }
  87. {
  88. sed 1q $TMP.msg
  89. cat $TMP.msg | sed 1d | upas/smtp -fh $1 a b
  90. } >$TMP.msg2 || exit $status
  91. mv $TMP.msg2 $TMP.msg || exit $status
  92. unmount /mail/fs
  93. upas/fs -pf $TMP.msg || exit $status
  94. }
  95. # classify message according to token-based white list
  96. fn tokenfilter {
  97. if($BIN/list check $PF $D/from $D/sender $D/replyto)
  98. echo match
  99. if not if(~ $status *!match*)
  100. echo !match
  101. if not if($BIN/token $KEY $D/subject)
  102. echo token
  103. if not
  104. echo new
  105. }
  106. # reject a message due to the token-based white list
  107. fn tokenreply {
  108. TOKEN=`{upas/token $KEY}
  109. if(! ~ $#MAILTO 1)
  110. exit 'bad token reply: no MAILTO variable'
  111. {
  112. cat /mail/lib/token.msg |
  113. sed 's/TOKEN/'$TOKEN'/g;s/USER/'$USER'/g;s/MAILTO/'$MAILTO'/g'
  114. cat $D/raw
  115. } | upasname=/dev/null mail `{cat $D/replyto}
  116. }
  117. # add addresses in message to white list
  118. fn listupdate {
  119. $BIN/list add $PF $D/from $D/to $D/cc $D/sender
  120. }
  121. # microsoft virus going around 9/22/2003
  122. fn isvirus {
  123. virus=no
  124. if(grep -s '\.(exe|scr|bat|com)' $D/2/2/mimeheader >[2]/dev/null){
  125. s=`{ls -l $D/2/2/raw | awk '{print $6}'}
  126. if(~ $s 1440??) virus=yes
  127. }
  128. if(~ $virus yes)
  129. status=''
  130. if not
  131. status='not this virus'
  132. }
  133. fn hasgifattachment {
  134. gif=no
  135. if(grep -s '\.gif' $D/2/mimeheader >[2]/dev/null){
  136. gif=yes
  137. }
  138. if(~ $gif yes)
  139. status=''
  140. if not
  141. status='not this gif'
  142. }
  143. # bayesian spam filter. alternative to token. see /mail/lib/setup.bayes
  144. fn isspam {
  145. for(i in _prof.mbox _prof.spam _bounced){
  146. if(! test -f $i){
  147. echo 'need '^$i >[1=2]
  148. exit 'need '^$i
  149. }
  150. }
  151. {
  152. echo '# hash table'
  153. upas/msgcat $TMP.msg | upas/msgtok |
  154. grep -v '^....................(.*) ' |
  155. sed 's/$/ 1/'
  156. } >$TMP.tok
  157. x=`{upas/bayes -k _prof.mbox _prof.spam ~ $TMP.tok | sed 's/_prof.//'}
  158. where=$x(1)
  159. prob=$x(2)
  160. prob1000=`{echo $prob '*1000' | hoc | sed 's/\..*//'}
  161. echo `{sed 's/^From ([^ ]+) (.*)/\2 from \1/' $D/unixheader} $x >>_bounced
  162. if(~ $where spam && test $prob1000 -lt 999)
  163. where=mbox
  164. upas/addhash -o _prof.$where _prof.$where 1 $TMP.tok 1
  165. if(~ $where spam)
  166. where=''
  167. status=$where
  168. }
  169. # save and parse the mail file
  170. sed '/^$/,$ s/^From / From /' >$TMP.msg
  171. upas/fs -pf $TMP.msg || exit $status