multidrop
上传用户:xxcykj
上传日期:2007-01-04
资源大小:727k
文件大小:8k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. From mlievaart@orion.nl  Mon Jan 10 10:46:33 2000
  2. From: Martijn Lievaart <mlievaart@orion.nl>
  3. To: Eric S. Raymond <esr@thyrsus.com>
  4. Date: zondag 9 januari 2000 0:38
  5. Subject: Re: Thanks for fetchmail and a solution to the multidrop problem (I
  6. Status: O
  7. Content-Length: 8086
  8. Lines: 226
  9. think)
  10. Hello Eric,
  11. Let me first state that I'm no sendmail nor unix guru, so although this
  12. seems to work, I certainly would not say this is the "best" solution. In
  13. fact I would welcome all comments to make this better. In particular, it
  14. seems that that the mailertable feature was made just for this, but I'm
  15. still studying that.
  16. Also, This mail will have lines wrapped. I will put up this on a website
  17. asap, so people can download the relevant portions. In the meantime, I'm
  18. using (stuck on) Outlook, so I won't even attempt to format this mail.
  19. Accept my apoligies and try to mentally reconnect the lines.
  20. Finally, this mail is a bit lengthy, but I guess it is better to get all
  21. information in, so please bear with me.
  22. After some very frustrating attempts to get multidrop to work reliably, it
  23. suddenly hit me. When sendmail has translated the recipient to the mailbox,
  24. the recipient is gone (in the cases we're talking about). So the solution is
  25. not to let sendmail do this translation (completely).
  26. The trick is to let a custom MDA be called with both the mailbox and the
  27. full recipient name. This MDA then just stuffs it in the correct mailbox
  28. after adding the appropriate headers. Luckily I hit on the formail utility.
  29. It reformats a mailmessage and does just what I wanted. Specifically my
  30. script uses it to:
  31. - add a custom header (default: "Delivered-To:") with the recipient
  32. - rewrite the message-ID, so fetchmail will download the same message
  33. multiple times.
  34. - add another header, just for fun.
  35. The rewriting of the message-ID is needed because fetchmail will suppress
  36. multiple messages with the same ID, normally a good idea, but now it gets in
  37. the way. A switch on fetchmail to suppress this behaviour would be great.
  38. At first I hardcoded the domains in the sendmail.cf, but I quickly set out
  39. to do one better and came up with the following solution. In sendmail.cf,
  40. add the following line somewhere at the top.
  41. Kmultidroptable hash -o /etc/mail/multidroptable
  42. this defines a table for all domains we want to use multidrop for. The
  43. format of this file is multiple lines of the format:
  44. <domain>    <mailbox>
  45. e.g:
  46. mailtest.orion.nl       mailtest
  47. mailtest2.orion.nl      mailtest
  48. mailtest3.orion.nl      mailtest
  49. bvh-communicatie.nl     b.bvh
  50. krakatau.nl             b.bvh
  51. personeelzaak.nl        b.bvh
  52. maslowassociates.nl     b.bvh
  53. rtij.nl                 rtij
  54. Of course, create a .db file with makemap. Also, the domains must be added
  55. to class w, so they should be added to your sendmail.cw or RelayTo file, or
  56. whatever you use.
  57. Now add to sendmail.cf:
  58. R$+ < @ $* . >                          $: <MULTIDROP> $(multidroptable $2
  59. $: <NO> $) <?> $1 < @ $2 . >
  60. R<MULTIDROP> <NO> <?> $*                $: $1
  61. R<MULTIDROP> $+ <?> $+ < @ $* . >       $#drop $@ $2 @ $3 $: $1
  62. These lines should be above the existing lines that read:
  63. # short circuit local delivery so forwarded email works
  64. R$=L < @ $=w . >        $#local $: @ $1         special local names
  65. R$+ < @ $=w . >         $#local $: $1                   regular local name
  66. This works as follows (in fact these comments are above my modification in
  67. our sendmail.cf).
  68. #
  69. # MLI. Any drop host gets passed to the drop script
  70. #
  71. # The first rule looks up the domain in the multidrop table.
  72. # The input at this point is always:
  73. #       user@<dom.ain.>
  74. #  If found, the resulting line looks like this:
  75. #       <MULTIDROP> mailbox <?> user@<dom.ain.>
  76. # if not found, the resulting line will be:
  77. #       <MULTIDROP> <NO> <?> user@<dom.ain.>
  78. # The second line restores the "not found" case back to user@<dom.ain.>
  79. # So if this domain was found in the multidroptable, we still have a line
  80. starting with <MULTIDROP>
  81. # as shown above. The third line hands this to the drop script.
  82. #
  83. # Note that the user ($:) is the mailbox this message should be stuffed in,
  84. the host ($@) is the full
  85. # user@<dom.ain>. This is how the dropscript expects it.
  86. #
  87. I guess sendmail guru's are now laughing their pants off, and I hope someone
  88. will show me a better way to achieve this. For now, it works.
  89. Next, we need to define mailer drop (somewhere in the sendmail.cf)
  90. #
  91. # multidrop pop3 support.
  92. #
  93. Mdrop,          P=/usr/local/bin/dropmail, F=lFS,
  94.                 T=X-Unix,
  95.                 A=dropmail $u $h
  96. The S flag here is crucial, otherwise the dropmail script won't run as root,
  97. and under linux (==bash) suid scripts are not permited. I gather most unices
  98. now disalow suid scripts, so this would be necessary on most unices. There
  99. probably are other flags that would make this better, but this works, so I
  100. decided to divert my attention to other tasks at hand (busy, busy, busy....
  101. ;^>).
  102. Now we only need the dropmail script, /usr/local/bin/dropmail, mode 700. It
  103. looks big, but effectively one pipeline does the real work. The rest is
  104. configuration, error checking and locking the mailbox.
  105. #!/bin/bash
  106. #
  107. # Script to force a mail message in a format that fetchmail will recognise.
  108. # use as a MDA from sendmail. Must be executed with F=S.
  109. #
  110. #
  111. # Configuration:
  112. #
  113. maildir=/var/spool/mail
  114. envelope=Delivered-To:
  115. #
  116. # set PATH to a known value to avoid some security issues
  117. #
  118. export PATH=/bin:/usr/bin
  119. #
  120. #
  121. #
  122. to=$2
  123. user=$1
  124. mbox=$maildir/$user
  125. #
  126. # If the mailbox does not exist, create it. Note that we act pretty
  127. paranoid, this is hopefully
  128. # resistant to symlink attacks
  129. #
  130. if [ ! -f $mbox ]
  131. then
  132.         oldumask=`umask`
  133.         umask 077
  134.         touch $mbox
  135.         chmod 660 $mbox || exit 1
  136.         chown $user $mbox || exit 1
  137.         chgrp mail $mbox || exit 1
  138.         umask $oldumask
  139. fi
  140. # First lock the mailbox, if this doesn't succeed in 64 seconds, give up and
  141. send
  142. # mail to postmaster.
  143. # If this period is to short, increase the retries (-r flag to lockfile)
  144. #
  145. # Then run the message through formail to get it into the right mailbox
  146. format with the
  147. # right headers added.
  148. #
  149. # Delivered-To will make fetchmail propagate this mail to the correct user
  150. when
  151. # run with '-E "Delivered-To"'. Set this in the advanced settings of the
  152. TeamInternet f.i.
  153. # (if you changed the envelope at the start of this script, adapt this
  154. accordingly)
  155. #
  156. # We also muck up the messageid, so fetchmail will never skip a message on
  157. the basis of
  158. # duplicate messageIDs. The -i "Message-ID" will rename the old message ID,
  159. the -a will
  160. # add a new one.
  161. #
  162. # Lastly, we add a header indicating which host did the rewriting.
  163. #
  164. if lockfile -r 8 $mbox.lock >/dev/null 2>&1
  165. then
  166.         cat - | formail -i "$envelope <$to>" -i "Message-ID:" -a
  167. "Message-ID:" -i "X-Multidrop-Processing: <`hostname`>" >>$mbox
  168.         rm -f $mbox.lock
  169. else
  170.         (echo "Subject: Cannot lock mailbox for $user" & cat -) |
  171. /usr/lib/sendmail postmaster
  172. fi
  173. #
  174. # EOF
  175. #
  176. This obviously is very Linux (even RedHat?) dependant, locking mailboxes,
  177. creating mailboxes with the right permissions, probably even bash dependent.
  178. I would say that it should be fairly easy to port to other systems, but
  179. alas, my unix knowledge is lacking for that. I'll also rewrite it someday,
  180. a.o. that umask handling can be done much better and the location of the
  181. sendmail binairy should not be fixed.
  182. Now the only thing left to do is to retrieve the mail with fetchmail, using
  183. 'envelope "Delivered-To:"' in the poll line. The above script has added this
  184. line, so this is all that fetchmail needs.
  185. All parts of this solution need carefull examination. In particular I think
  186. the new rule lines may not catch all cases, although they worked for
  187. everything I threw at them and work satisfactorily in production. I'm also
  188. wondering if there is a more standard way to drop something in a mailbox. I
  189. yet have to investigate procmail, but all other MDA's mucked with the
  190. message and effectively undid my carefully added header. I'll experiment
  191. some more and rethink it all as I learn more.
  192. I'm still wondering, if I can get formail to include another received
  193. line.... "Received from localhost by dropmail for <user>...." to make it
  194. work without the envelope flag. Well I'll have to experiment. Do you know if
  195. there is a header I can add so fetchmail works out-of-the-box?
  196. Regards,
  197. Martijn Lievaart