mailman-sendmail.pl 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #!@l_prefix@/bin/perl
  2. ##
  3. ## Sendmail mailer for Mailman
  4. ##
  5. ## Simulates these aliases:
  6. ##
  7. ##testlist: "|/home/mailman/mail/mailman post testlist"
  8. ##testlist-admin: "|/home/mailman/mail/mailman admin testlist"
  9. ##testlist-bounces: "|/home/mailman/mail/mailman bounces testlist"
  10. ##testlist-confirm: "|/home/mailman/mail/mailman confirm testlist"
  11. ##testlist-join: "|/home/mailman/mail/mailman join testlist"
  12. ##testlist-leave: "|/home/mailman/mail/mailman leave testlist"
  13. ##testlist-owner: "|/home/mailman/mail/mailman owner testlist"
  14. ##testlist-request: "|/home/mailman/mail/mailman request testlist"
  15. ##testlist-subscribe: "|/home/mailman/mail/mailman subscribe testlist"
  16. ##testlist-unsubscribe: "|/home/mailman/mail/mailman unsubscribe testlist"
  17. ##owner-testlist: testlist-owner
  18. ## Some assembly required.
  19. $MMWRAPPER = "@l_prefix@/libexec/mailman/mail/mailman";
  20. $MMLISTDIR = "@l_prefix@/var/mailman/lists";
  21. $SENDMAIL = "@l_prefix@/sbin/sendmail -oem -oi";
  22. $VERSION = '$Id: mailman-sendmail.pl,v 1.1 2005/04/30 17:18:54 rse Exp $';
  23. ## Comment this if you offer local user addresses.
  24. $NOUSERS = "\nPersonal e-mail addresses are not offered by this server.";
  25. # uncomment for debugging....
  26. #$DEBUG = 1;
  27. use FileHandle;
  28. use Sys::Hostname;
  29. use Socket;
  30. ($VERS_STR = $VERSION) =~ s/^\$\S+\s+(\S+),v\s+(\S+\s+\S+\s+\S+).*/\1 \2/;
  31. $BOUNDARY = sprintf("%08x-%d", time, time % $$);
  32. ## Informative, non-standard rejection letter
  33. sub mail_error {
  34. my ($in, $to, $list, $server, $reason) = @_;
  35. my $sendmail;
  36. if ($server && $server ne "") {
  37. $servname = $server;
  38. } else {
  39. $servname = "This server";
  40. $server = &get_ip_addr;
  41. }
  42. #$sendmail = new FileHandle ">/tmp/mm-$$";
  43. $sendmail = new FileHandle "|$SENDMAIL $to";
  44. if (!defined($sendmail)) {
  45. print STDERR "$0: cannot exec \"$SENDMAIL\"\n";
  46. exit (-1);
  47. }
  48. $sendmail->print ("From: MAILER-DAEMON\@$server
  49. To: $to
  50. Subject: Returned mail: List unknown
  51. Mime-Version: 1.0
  52. Content-type: multipart/mixed; boundary=\"$BOUNDARY\"
  53. Content-Disposition: inline
  54. --$BOUNDARY
  55. Content-Type: text/plain; charset=us-ascii
  56. Content-Description: Error processing your mail
  57. Content-Disposition: inline
  58. Your mail for $list could not be sent:
  59. $reason
  60. For a list of publicly-advertised mailing lists hosted on this server,
  61. visit this URL:
  62. http://$server/
  63. If this does not resolve your problem, you may write to:
  64. postmaster\@$server
  65. or
  66. mailman-owner\@$server
  67. $servname delivers e-mail to registered mailing lists
  68. and to the administrative addresses defined and required by IETF
  69. Request for Comments (RFC) 2142 [1].
  70. $NOUSERS
  71. The Internet Engineering Task Force [2] (IETF) oversees the development
  72. of open standards for the Internet community, including the protocols
  73. and formats employed by Internet mail systems.
  74. For your convenience, your original mail is attached.
  75. [1] Crocker, D. \"Mailbox Names for Common Services, Roles and
  76. Functions\". http://www.ietf.org/rfc/rfc2142.txt
  77. [2] http://www.ietf.org/
  78. --$BOUNDARY
  79. Content-Type: message/rfc822
  80. Content-Description: Your undelivered mail
  81. Content-Disposition: attachment
  82. ");
  83. while ($_ = <$in>) {
  84. $sendmail->print ($_);
  85. }
  86. $sendmail->print ("\n");
  87. $sendmail->print ("--$BOUNDARY--\n");
  88. close($sendmail);
  89. }
  90. ## Get my IP address, in case my sendmail doesn't tell me my name.
  91. sub get_ip_addr {
  92. my $host = hostname;
  93. my $ip = gethostbyname($host);
  94. return inet_ntoa($ip);
  95. }
  96. ## Split an address into its base list name and the appropriate command
  97. ## for the relevant function.
  98. sub split_addr {
  99. my ($addr) = @_;
  100. my ($list, $cmd);
  101. my @validfields = qw(admin bounces confirm join leave owner request
  102. subscribe unsubscribe);
  103. if ($addr =~ /(.*)-(.*)\+.*$/) {
  104. $list = $1;
  105. $cmd = "$2";
  106. } else {
  107. $addr =~ /(.*)-(.*)$/;
  108. $list = $1;
  109. $cmd = $2;
  110. }
  111. if (grep /^$cmd$/, @validfields) {
  112. if ($list eq "owner") {
  113. $list = $cmd;
  114. $cmd = "owner";
  115. }
  116. } else {
  117. $list = $addr;
  118. $cmd = "post";
  119. }
  120. return ($list, $cmd);
  121. }
  122. ## The time, formatted as for an mbox's "From_" line.
  123. sub mboxdate {
  124. my ($time) = @_;
  125. my @days = qw(Sun Mon Tue Wed Thu Fri Sat);
  126. my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
  127. my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
  128. localtime($time);
  129. ## Two-digit year handling complies with RFC 2822 (section 4.3),
  130. ## with the addition that three-digit years are accommodated.
  131. if ($year < 50) {
  132. $year += 2000;
  133. } elsif ($year < 1900) {
  134. $year += 1900;
  135. }
  136. return sprintf ("%s %s %2d %02d:%02d:%02d %d",
  137. $days[$wday], $months[$mon], $mday,
  138. $hour, $min, $sec, $year);
  139. }
  140. BEGIN: {
  141. $sender = undef;
  142. $server = undef;
  143. @to = ();
  144. while ($#ARGV >= 0) {
  145. if ($ARGV[0] eq "-r") {
  146. $sender = $ARGV[1];
  147. shift @ARGV;
  148. } elsif (!defined($server)) {
  149. $server = $ARGV[0];
  150. } else {
  151. push(@to, $ARGV[0]);
  152. }
  153. shift @ARGV;
  154. }
  155. if ($DEBUG) {
  156. $to = join(',', @to);
  157. print STDERR "to: $to, @to\n";
  158. print STDERR "sender: $sender\n";
  159. print STDERR "server: $server\n";
  160. exit(-1);
  161. }
  162. ADDR: for $addr (@to) {
  163. $prev = undef;
  164. $list = $addr;
  165. $cmd= "post";
  166. if (! -f "$MMLISTDIR/$list/config.pck") {
  167. ($list, $cmd) = &split_addr($list);
  168. if (! -f "$MMLISTDIR/$list/config.pck") {
  169. $was_to = $addr;
  170. $was_to .= "\@$server" if ("$server" ne "");
  171. mail_error(\*STDIN, $sender, $was_to, $server,
  172. "no list named \"$list\" is known by $server");
  173. next ADDR;
  174. }
  175. }
  176. $wrapper = new FileHandle "|$MMWRAPPER $cmd $list";
  177. if (!defined($wrapper)) {
  178. ## Defer?
  179. print STDERR "$0: cannot exec ",
  180. "\"$MMWRAPPER $cmd $list\": deferring\n";
  181. exit (-1);
  182. }
  183. # Don't need these without the "n" flag on the mailer def....
  184. #$date = &mboxdate(time);
  185. #$wrapper->print ("From $sender $date\n");
  186. # ...because we use these instead.
  187. $from_ = <STDIN>;
  188. $wrapper->print ($from_);
  189. $wrapper->print ("X-Mailman-Handler: $VERSION\n");
  190. while (<STDIN>) {
  191. $wrapper->print ($_);
  192. }
  193. close($wrapper);
  194. }
  195. }