~ubuntu-branches/debian/squeeze/sympa/squeeze

« back to all changes in this revision

Viewing changes to src/smtp.pm

  • Committer: Bazaar Package Importer
  • Author(s): Christian Perrier
  • Date: 2007-01-20 18:09:28 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070120180928-0e42mbwg87mlo44y
Tags: 5.2.3-1.2
* Non-maintainer upload to re-fix l10n issues
* As debconf-updatepo was not run in previous versions, the French
  translation was outdated. Hence fix it.
* Remove several duplicate spaces in the debconf templates

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# smtp.pm - This module does the SMTP job, it does send messages
2
 
# RCS Identication ; $Revision: 1.23 $ ; $Date: 2004/01/15 16:25:03 $ 
3
 
#
4
 
# Sympa - SYsteme de Multi-Postage Automatique
5
 
# Copyright (c) 1997, 1998, 1999, 2000, 2001 Comite Reseau des Universites
6
 
# Copyright (c) 1997,1998, 1999 Institut Pasteur & Christophe Wolfhugel
7
 
#
8
 
# This program is free software; you can redistribute it and/or modify
9
 
# it under the terms of the GNU General Public License as published by
10
 
# the Free Software Foundation; either version 2 of the License, or
11
 
# (at your option) any later version.
12
 
#
13
 
# This program is distributed in the hope that it will be useful,
14
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
# GNU General Public License for more details.
17
 
#
18
 
# You should have received a copy of the GNU General Public License
19
 
# along with this program; if not, write to the Free Software
20
 
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
 
 
22
 
package smtp;
23
 
 
24
 
use POSIX;
25
 
use Mail::Internet;
26
 
use Conf;
27
 
use Language;
28
 
use Log;
29
 
 
30
 
require 'tools.pl';
31
 
 
32
 
use strict;
33
 
 
34
 
## RCS identification.
35
 
#my $id = '@(#)$Id: smtp.pm,v 1.23 2004/01/15 16:25:03 salaun Exp $';
36
 
 
37
 
my $opensmtp = 0;
38
 
my $fh = 'fh0000000000';        ## File handle for the stream.
39
 
 
40
 
my $max_arg = eval { &POSIX::_SC_ARG_MAX; };
41
 
if ($@) {
42
 
    $max_arg = 4096;
43
 
    print STDERR Msg(11, 1,'Your system is not POSIX P1003.1 compliant, or it does not define
44
 
the _SC_ARG_MAX constant in its POSIX library. You will need to manually edit
45
 
smtp.pm and configure $max_arg
46
 
');
47
 
} else {
48
 
    $max_arg = POSIX::sysconf($max_arg);
49
 
}
50
 
 
51
 
my %pid = ();
52
 
 
53
 
## Reaper - Non blocking function called by the main loop, just to
54
 
## clean the defuncts list by waiting to any processes and decrementing
55
 
## the counter.
56
 
sub reaper {
57
 
   my $block = shift;
58
 
   my $i;
59
 
 
60
 
   $block = 1 unless (defined($block));
61
 
   while (($i = waitpid(-1, $block ? &POSIX::WNOHANG : 0)) > 0) {
62
 
      $block = 1;
63
 
      if (!defined($pid{$i})) {
64
 
         &do_log('debug2', "Reaper waited $i, unknown process to me");
65
 
         next;
66
 
      }
67
 
      $opensmtp--;
68
 
      delete($pid{$i});
69
 
   }
70
 
   &do_log('debug2', "Reaper unwaited pids : %s\nOpen = %s\n", join(' ', sort keys %pid), $opensmtp);
71
 
   return $i;
72
 
}
73
 
 
74
 
## Makes a sendmail ready for the recipients given as
75
 
## argument, uses a file descriptor in the smtp table
76
 
## which can be imported by other parties.
77
 
sub smtpto {
78
 
   my($from, $rcpt, $sign_mode) = @_;
79
 
 
80
 
   unless ($from) {
81
 
       &do_log('err', 'Missing Return-Path in smtp::smtpto()');
82
 
   }
83
 
   
84
 
   if (ref($rcpt) eq 'SCALAR') {
85
 
       do_log('debug2', 'smtp::smtpto(%s, %s, %s )', $from, $$rcpt,$sign_mode);
86
 
   }else {
87
 
       do_log('debug2', 'smtp::smtpto(%s, %s, %s)', $from, join(',', @{$rcpt}), $sign_mode);
88
 
   }
89
 
 
90
 
   my($pid, $str);
91
 
 
92
 
   ## Escape "-" at beginning of recepient addresses
93
 
   ## prevent sendmail from taking it as argument
94
 
 
95
 
   if (ref($rcpt) eq 'SCALAR') {
96
 
       $$rcpt =~ s/^-/\\-/;
97
 
   }else {
98
 
       my @emails = @$rcpt;
99
 
       foreach my $i (0..$#emails) {
100
 
           $rcpt->[$i] =~ s/^-/\\-/;
101
 
       }
102
 
   }
103
 
   
104
 
   ## Check how many open smtp's we have, if too many wait for a few
105
 
   ## to terminate and then do our job.
106
 
 
107
 
   do_log('debug3',"Open = $opensmtp");
108
 
   while ($opensmtp > $Conf{'maxsmtp'}) {
109
 
       do_log('debug3',"Smtpto: too many open SMTP ($opensmtp), calling reaper" );
110
 
       last if (&reaper(0) == -1); ## Blocking call to the reaper.
111
 
   }
112
 
 
113
 
   *IN = ++$fh; *OUT = ++$fh;
114
 
   
115
 
 
116
 
   if (!pipe(IN, OUT)) {
117
 
       fatal_err(Msg(11, 2, "Can't create a pipe in smtpto: %m")); ## No return
118
 
   }
119
 
   $pid = &tools::safefork();
120
 
   $pid{$pid} = 0;
121
 
   if ($pid == 0) {
122
 
       close(OUT);
123
 
       open(STDIN, "<&IN");
124
 
 
125
 
       if (ref($rcpt) eq 'SCALAR') {
126
 
           exec $Conf{'sendmail'}, split(/\s+/,$Conf{'sendmail_args'}), '-f', $from, $$rcpt;
127
 
       }else{
128
 
           exec $Conf{'sendmail'}, split(/\s+/,$Conf{'sendmail_args'}), '-f', $from, @$rcpt;
129
 
       }
130
 
       exit 1; ## Should never get there.
131
 
   }
132
 
   if ($main::options{'mail'}) {
133
 
       $str = "safefork: $Conf{'sendmail'} $Conf{'sendmail_args'} -f $from ";
134
 
       if (ref($rcpt) eq 'SCALAR') {
135
 
           $str .= $$rcpt;
136
 
       } else {
137
 
           $str .= join(' ', @$rcpt);
138
 
       }
139
 
       do_log('notice', $str);
140
 
   }
141
 
   close(IN);
142
 
   $opensmtp++;
143
 
   select(undef, undef,undef, 0.3) if ($opensmtp < $Conf{'maxsmtp'});
144
 
   return("smtp::$fh"); ## Symbol for the write descriptor.
145
 
}
146
 
 
147
 
 
148
 
## Makes a sendmail ready for the recipients given as
149
 
## argument, uses a file descriptor in the smtp table
150
 
## which can be imported by other parties.
151
 
sub smime_sign {
152
 
    my $from = shift;
153
 
    my $temporary_file  = shift;
154
 
    
155
 
    do_log('debug2', 'smtp::smime_sign (%s)', $from);
156
 
 
157
 
    exec "$Conf{'openssl'} smime -sign -signer cert.pem -inkey private_key -out $temporary_file";
158
 
    exit 1; ## Should never get there.
159
 
}
160
 
 
161
 
 
162
 
sub sendto {
163
 
    my($msg_header, $msg_body, $from, $rcpt, $encrypt) = @_;
164
 
    do_log('debug2', 'smtp::sendto(%s, %s, %s)', $from, $rcpt, $encrypt);
165
 
 
166
 
    my $msg;
167
 
 
168
 
    ## Encode subject before sending
169
 
    $msg_header->replace('Subject', MIME::Words::encode_mimewords($msg_header->get('Subject')));
170
 
 
171
 
    if ($encrypt eq 'smime_crypted') {
172
 
        my $email ;
173
 
        if (ref($rcpt) eq 'SCALAR') {
174
 
            $email = lc ($$rcpt) ;
175
 
        }else{
176
 
            my @rcpts = @$rcpt;
177
 
            if ($#rcpts != 0) {
178
 
                do_log('err',"incorrect call for encrypt with $#rcpts recipient(s)"); 
179
 
                return undef;
180
 
            }
181
 
            $email = lc ($rcpt->[0]); 
182
 
        }
183
 
        $msg = &tools::smime_encrypt ($msg_header, $msg_body, $email);
184
 
    }else {
185
 
        $msg = $msg_header->as_string . "\n" . $msg_body;
186
 
    }
187
 
    
188
 
    if ($msg) {
189
 
        *SMTP = &smtpto($from, $rcpt);
190
 
        print SMTP $msg;
191
 
        close SMTP;
192
 
        return 1;
193
 
    }else{    
194
 
        return undef;
195
 
    }
196
 
}
197
 
 
198
 
sub mailto {
199
 
   my($message, $from, @rcpt) = @_;
200
 
   do_log('debug2', 'smtp::mailto(from: %s, , file:%s, %s, %d rcpt)', $from, $message->{'filename'}, $message->{'smime_crypted'}, $#rcpt+1);
201
 
 
202
 
   my($i, $j, $nrcpt, $size, @sendto);
203
 
   my $numsmtp = 0;
204
 
   
205
 
   ## If message contain a footer or header added by Sympa  use the object message else
206
 
   ## Extract body from original file to preserve signature
207
 
   my ($msg_body, $msg_header);
208
 
 
209
 
   $msg_header = $message->{'msg'}->head;
210
 
 
211
 
   if ($message->{'altered'}) {
212
 
       $msg_body = $message->{'msg'}->body_as_string;
213
 
       
214
 
   }elsif ($message->{'smime_crypted'}) {
215
 
       $msg_body = ${$message->{'msg_as_string'}};
216
 
       
217
 
   }else {
218
 
       ## Get body from original file
219
 
       unless (open MSG, $message->{'filename'}) {
220
 
           do_log ('notice',"Unable to open %s:%s",$message->{'filename'},$!);
221
 
           return undef;
222
 
       }
223
 
       my $in_header = 1 ;
224
 
       while (<MSG>) {
225
 
           if ( !$in_header)  { 
226
 
               $msg_body .= $_;       
227
 
           }else {
228
 
               $in_header = 0 if (/^$/); 
229
 
           }
230
 
       }
231
 
       close (MSG);
232
 
   }
233
 
   
234
 
   ## if the message must be crypted,  we need to send it using one smtp session for each rcpt
235
 
   if ($message->{'smime_crypted'}){
236
 
       $numsmtp = 0;
237
 
       while (defined ($i = shift(@rcpt))) {
238
 
           &sendto($msg_header, $msg_body, $from, [$i], $message->{'smime_crypted'});
239
 
           $numsmtp++
240
 
           }
241
 
       
242
 
       return ($numsmtp);
243
 
   }
244
 
 
245
 
   while (defined ($i = shift(@rcpt))) {
246
 
       my @k = reverse(split(/[\.@]/, $i));
247
 
       my @l = reverse(split(/[\.@]/, $j));
248
 
       if ($j && $#sendto >= $Conf{'avg'} && lc("$k[0] $k[1]") ne lc("$l[0] $l[1]")) {
249
 
           &sendto($msg_header, $msg_body, $from, \@sendto);
250
 
           $numsmtp++;
251
 
           $nrcpt = $size = 0;
252
 
           @sendto = ();
253
 
       }
254
 
       if ($#sendto >= 0 && (($size + length($i)) > $max_arg || $nrcpt >= $Conf{'nrcpt'})) {
255
 
           &sendto($msg_header, $msg_body, $from, \@sendto);
256
 
           $numsmtp++;
257
 
           $nrcpt = $size = 0;
258
 
           @sendto = ();
259
 
       }
260
 
       $nrcpt++; $size += length($i) + 5;
261
 
       push(@sendto, $i);
262
 
       $j = $i;
263
 
   }
264
 
   if ($#sendto >= 0) {
265
 
       &sendto($msg_header, $msg_body, $from, \@sendto) if ($#sendto >= 0);
266
 
       $numsmtp++;
267
 
   }
268
 
   
269
 
   return $numsmtp;
270
 
}
271
 
 
272
 
1;
273
 
 
274
 
 
275
 
 
276
 
 
277