26
26
@ISA = qw(Exporter);
27
@EXPORT = qw(mailback mailarc mailfile set_send_spool);
27
@EXPORT = qw(mail_file mail_message mail_forward set_send_spool);
36
41
## RCS identification.
37
#my $id = '@(#)$Id: mail.pm,v 1.18 2002/09/17 09:04:46 salaun Exp $';
42
#my $id = '@(#)$Id: mail.pm,v 1.35 2006/03/08 15:17:23 sympa-authors Exp $';
45
my $fh = 'fh0000000000'; ## File handle for the stream.
47
my $max_arg = eval { &POSIX::_SC_ARG_MAX; };
50
printf STDERR gettext("Your system does not conform to the POSIX P1003.1 standard, or\nyour Perl system does not define the _SC_ARG_MAX constant in its POSIX\nlibrary. You must modify the smtp.pm module in order to set a value\nfor variable $max_arg.\n");
52
$max_arg = POSIX::sysconf($max_arg);
57
my $send_spool; ## for calling context
61
#################################### PUBLIC FUNCTIONS ##############################################
64
####################################################
65
# public set_send_spool
66
####################################################
67
# set in global $send_spool, the concerned spool for
68
# sending message when it is not done by smtpto
70
# IN : $spool (+): spool concerned by sending
73
####################################################
41
74
sub set_send_spool {
44
77
$send_spool = $spool;
47
## Mail back a response to the given address.
48
## Data is a reference to an array or a scalar.
50
my($data, $headers, $from, $to, $robot, @rcpt) = @_;
51
do_log('debug2', 'mail::mailback(%s, %s)', $from, join(',', @rcpt));
53
my ($fh, $sympa_file);
80
####################################################
82
####################################################
86
# IN : -$filename(+) : tt2 filename (with .tt2) | ''
87
# -$rcpt(+) : SCALAR |ref(ARRAY) : SMTP "RCPT To:" field
88
# -$data(+) : used to parse tt2 file, ref(HASH) with keys :
89
# -return_path(+) : SMTP "MAIL From:" field if send by smtp,
90
# "X-Sympa-From:" field if send by spool
91
# -to : "To:" header field
92
# -lang : tt2 language if $filename
93
# -list : ref(HASH) if $sign_mode = 'smime', keys are :
96
# -from : "From:" field if not a full msg
97
# -subject : "Subject:" field if not a full msg
98
# -replyto : "Reply-to:" field if not a full msg
99
# -body : body message if not $filename
100
# -headers : ref(HASH) with keys are headers mail
102
# -$sign_mode :'smime' | '' | undef
105
####################################################
107
my ($filename, $rcpt, $data,$robot,$sign_mode) = @_;
108
&do_log('debug2', 'mail::mail_file(%s, %s, %s)', $filename, $rcpt, $sign_mode);
113
my $header_possible = 0; # =1 : it is possible there are some headers
114
my %header_ok; # hash containing no missing headers
115
my $existing_headers = 0;# the message already contains headers
55
my $sympa_email = &Conf::get_robot_conf($robot, 'sympa');
57
## Don't fork if used by a CGI (FastCGI problem)
58
if (defined $send_spool) {
59
$sympa_file = "$send_spool/T.$sympa_email.".time.'.'.int(rand(10000));
60
my $rcpt = join ',', @rcpt;
62
unless (open TMP, ">$sympa_file") {
63
&do_log('notice', 'Cannot create %s : %s', $sympa_file, $!);
117
## We may receive a list a recepients
119
unless (ref ($rcpt) eq 'ARRAY') {
120
&do_log('notice', 'mail:mail_file : Wrong type of reference for rcpt');
126
if ($filename =~ /\.tt2$/) {
128
my @path = split /\//, $filename;
129
&Language::PushLang($data->{'lang'}) if (defined $data->{'lang'});
130
&tt2::parse_tt2($data, $path[$#path], \$output);
131
&Language::PopLang() if (defined $data->{'lang'});
132
$message .= join('',$output);
133
$header_possible = 1;
136
$message .= $data->{'body'};
67
printf TMP "X-Sympa-To: %s\n", $rcpt;
68
printf TMP "X-Sympa-From: %s\n", $sympa_email;
69
printf TMP "X-Sympa-Checksum: %s\n", &tools::sympa_checksum($rcpt);
139
## ## Does the message include headers ?
140
if ($header_possible) {
141
foreach my $line (split(/\n/,$message)) {
142
last if ($line=~/^\s*$/);
73
$fh = smtp::smtpto($sympa_email, \@rcpt);
144
if ($line=~/^[\w-]+:\s+\S/) {
150
foreach my $header ('to','from','subject','reply-to','mime-version', 'content-type','content-transfer-encoding') {
151
if ($line=~/^$header:/i) {
152
$header_ok{$header} = 1;
76
159
## Charset for encoding
77
my $charset = sprintf (Msg(12, 2, 'us-ascii'));
79
printf $fh "To: %s\n", MIME::Words::encode_mimewords($to, 'Q', $charset);
80
if ($from eq 'sympa') {
81
printf $fh "From: %s\n", MIME::Words::encode_mimewords((sprintf (Msg(12, 4, 'SYMPA <%s>'), $sympa_email)), 'Q', $charset);
160
my $charset = sprintf (gettext("_charset_"));
162
## ADD MISSING HEADERS
165
unless ($header_ok{'to'}) {
83
printf $fh "From: %s\n", $from;
85
foreach my $field (keys %{$headers}) {
86
printf $fh "%s: %s\n", $field, MIME::Words::encode_mimewords($headers->{$field}, 'Q', $charset);
88
printf $fh "MIME-Version: %s\n", Msg(12, 1, '1.0');
89
printf $fh "Content-Type: text/plain; charset=%s\n", Msg(12, 2, 'us-ascii');
90
printf $fh "Content-Transfer-Encoding: %s\n", Msg(12, 3, '7bit');
171
$to = join(",\n ", @{$rcpt});
176
$headers .= "To: ".MIME::Words::encode_mimewords($to, ('Encode' => 'Q', 'Charset' => $charset))."\n";
178
unless ($header_ok{'from'}) {
179
if ($data->{'from'} eq 'sympa') {
180
$headers .= "From: ".MIME::Words::encode_mimewords((sprintf ("SYMPA <%s>",&Conf::get_robot_conf($robot, 'sympa'))), ('Encode' => 'Q', 'Charset' => $charset))."\n";
182
$headers .= "From: ".MIME::Words::encode_mimewords($data->{'from'},('Encode' => 'Q', 'Charset' => $charset))."\n";
185
unless ($header_ok{'subject'}) {
186
$headers .= "Subject: ".MIME::Words::encode_mimewords($data->{'subject'},('Encode' => 'Q', 'Charset' => $charset))."\n";
188
unless ($header_ok{'reply-to'}) {
189
$headers .= "Reply-to: ".MIME::Words::encode_mimewords($data->{'replyto'},('Encode' => 'Q', 'Charset' => $charset))."\n" if ($data->{'replyto'})
191
if ($data->{'headers'}) {
192
foreach my $field (keys %{$data->{'headers'}}) {
193
$headers .= $field.': '.MIME::Words::encode_mimewords($data->{'headers'}{$field},('Encode' => 'Q', 'Charset' => $charset))."\n";
196
unless ($header_ok{'mime-version'}) {
197
$headers .= "MIME-Version: 1.0\n";
199
unless ($header_ok{'content-type'}) {
200
$headers .= "Content-Type: text/plain; charset=$charset\n";
202
unless ($header_ok{'content-transfer-encoding'}) {
203
$headers .= "Content-Transfer-Encoding:";
204
$headers .= gettext("_encoding_");
207
unless ($existing_headers) {
211
$message = "$headers"."$message";
93
if (ref($data) eq 'SCALAR') {
95
} elsif (ref($data) eq 'ARRAY') {
100
if (defined $sympa_file) {
101
my $new_file = $sympa_file;
102
$new_file =~ s/T\.//g;
214
if (ref($data->{'list'}) eq "HASH") {
215
$listname = $data->{'list'}{'name'};
216
} elsif ($data->{'list'}) {
217
$listname = $data->{'list'};
104
unless (rename $sympa_file, $new_file) {
105
&do_log('notice', 'Cannot rename %s to %s : %s', $sympa_file, $new_file, $!);
222
unless (defined &sending($message,$rcpt,$data->{'return_path'},$robot,$listname,$sign_mode)) {
226
unless (defined &sending($message,\$rcpt,$data->{'return_path'},$robot,$listname,$sign_mode)) {
113
## send an archive file
115
my($filename, $subject, @rcpt) = @_;
116
do_log('debug2', 'mail::mailarc(%s, %s)', $subject, join(',', @rcpt));
120
if (!open(IN, $filename)) {
121
fatal_err("Can't send %s to %s: %m", $filename, join(',', @rcpt));
123
my($fh) = &smtp::smtpto($Conf{'robots'}{$robot}{'sympa'} || $Conf{'request'}, \@rcpt);
124
printf $fh "To: %s\n", join(",\n ", @rcpt);
125
print $fh "Subject: $subject\n";
126
printf $fh "MIME-Version: %s\n", Msg(12, 1, '1.0');
127
printf $fh "Content-Type: text/plain; charset=%s\n", Msg(12, 2, 'us-ascii');
128
printf $fh "Content-Transfer-Encoding: %s\n", Msg(12, 3, '7bit');
130
print $fh $i while ($i = <IN>);
234
####################################################
235
# public mail_message
236
####################################################
237
# distribute a message to a list, Crypting if needed
239
# IN : -$message(+) : ref(Message)
240
# -$from(+) : message from
242
# -{verp=>[on|off]} : a hash to introduce verp parameters, starting just on or off, later will probably introduce optionnal parameters
243
# -@rcpt(+) : recepients
244
# OUT : -$numsmtp : number of sendmail process | undef
246
####################################################
248
my($message, $list, $verp, @rcpt) = @_;
251
my $host = $list->{'admin'}{'host'};
252
my $robot = $list->{'domain'};
253
my $name = $list->{'name'};
255
# normal return_path (ie used if verp is not enabled)
256
my $from = $list->{'name'}.&Conf::get_robot_conf($robot, 'return_path_suffix').'@'.$host;
258
do_log('debug', 'mail::mail_message(from: %s, , file:%s, %s, verp->%s %d rcpt)', $from, $message->{'filename'}, $message->{'smime_crypted'}, $verp->{'enable'}, $#rcpt+1);
261
my($i, $j, $nrcpt, $size, @sendto);
264
## If message contain a footer or header added by Sympa use the object message else
265
## Extract body from original file to preserve signature
266
my ($msg_body, $msg_header);
268
$msg_header = $message->{'msg'}->head;
270
if ($message->{'altered'}) {
271
$msg_body = $message->{'msg'}->body_as_string;
273
}elsif ($message->{'smime_crypted'}) {
274
$msg_body = ${$message->{'msg_as_string'}};
277
## Get body from original file
278
unless (open MSG, $message->{'filename'}) {
279
do_log ('notice',"mail::mail_message : Unable to open %s:%s",$message->{'filename'},$!);
287
$in_header = 0 if (/^$/);
293
## if the message must be crypted, we need to send it using one smtp session for each rcpt
294
## n.b. : sendto can send by setting in spool, however, $numsmtp is incremented (=> to change)
295
# ignore verp if crypted. It should be better to do the reverse : allway use verp if crypted (sa 03/01/2006)
297
if (($message->{'smime_crypted'})||($verp->{'enable'} eq 'on')){
299
while (defined ($i = shift(@rcpt))) {
300
my $return_path = $from;
301
if ($verp->{'enable'} eq 'on') {
303
$return_path =~ s/\@/\=\=a\=\=/;
304
$return_path = "$Conf{'bounce_email_prefix'}+$return_path\=\=$name\@$robot";
306
$numsmtp++ if (&sendto($msg_header, $msg_body, $return_path, [$i], $robot, $message->{'smime_crypted'}));
316
while (defined ($i = shift(@rcpt))) {
317
my @k = reverse(split(/[\.@]/, $i));
318
my @l = reverse(split(/[\.@]/, $j));
321
if ($i =~ /\@(.*)$/) {
325
$rcpt_by_dom{$dom} += 1 ;
326
&do_log('debug2', "domain: $dom ; rcpt by dom: $rcpt_by_dom{$dom} ; limit for this domain: $Conf{'nrcpt_by_domain'}{$dom}");
328
if (defined ($Conf{'nrcpt_by_domain'}{$dom}) && ( $rcpt_by_dom{$dom} >= $Conf{'nrcpt_by_domain'}{$dom} )){
330
$numsmtp++ if (&sendto($msg_header, $msg_body, $from, \@sendto, $robot));
335
if ($j && $#sendto >= &Conf::get_robot_conf($robot, 'avg') && lc("$k[0] $k[1]") ne lc("$l[0] $l[1]")) {
337
$numsmtp++ if (&sendto($msg_header, $msg_body, $from, \@sendto, $robot));
341
if ($#sendto >= 0 && (($size + length($i)) > $max_arg || $nrcpt >= &Conf::get_robot_conf($robot, 'nrcpt'))) {
343
$numsmtp++ if (&sendto($msg_header, $msg_body, $from, \@sendto, $robot));
347
$nrcpt++; $size += length($i) + 5;
352
$numsmtp++ if (&sendto($msg_header, $msg_body, $from, \@sendto, $robot));
134
## send welcome, bye, expire removed or reminder message to a user
136
my ($filename, $rcpt, $data, $robot, $sign_mode) = @_;
137
do_log('debug2', 'mail::mailfile(%s, %s, %s, %s)', $filename, $rcpt, $robot, $sign_mode);
139
my ($full_msg, $return_path, $sendmail, $to, $sympa_file);
141
## We may receive a list a recepients
360
####################################################
361
# public mail_forward
362
####################################################
365
# IN : -$msg(+) : ref(Message)|ref(MIME::Entity)|string
366
# -$from(+) : message from
367
# -$rcpt(+) : ref(SCALAR) | ref(ARRAY) - recepients
371
####################################################
373
my($msg,$from,$rcpt,$robot)=@_;
374
&do_log('debug3', "mail::mail_forward($from,$rcpt)");
377
if (ref($msg) eq 'Message') {
378
$message = $msg->{'msg'};
144
unless (ref ($rcpt) eq 'ARRAY') {
145
&do_log('notice', 'Wrong type of reference for rcpt');
384
unless (defined &sending($message,$rcpt,$from,$robot,'','none')) {
385
&do_log('err','mail::mail_forward from %s impossible to send',$from);
149
# if ($sign_mode eq 'smime') {
150
# &do_log('notice', 'Cannot sign a message with multiple recepients');
392
#####################################################################
394
#####################################################################
395
# Non blocking function called by : mail::smtpto(), sympa::main_loop
396
# task_manager::INFINITE_LOOP scanning the queue,
397
# bounced::infinite_loop scanning the queue,
398
# just to clean the defuncts list by waiting to any processes and
399
# decrementing the counter.
403
#####################################################################
408
$block = 1 unless (defined($block));
409
while (($i = waitpid(-1, $block ? &POSIX::WNOHANG : 0)) > 0) {
411
if (!defined($pid{$i})) {
412
&do_log('debug2', "Reaper waited $i, unknown process to me");
418
&do_log('debug2', "Reaper unwaited pids : %s\nOpen = %s\n", join(' ', sort keys %pid), $opensmtp);
423
#################################### PRIVATE FUNCTIONS ##############################################
425
####################################################
427
####################################################
428
# send messages, S/MIME encryption if needed,
429
# grouped sending (or not if encryption)
431
# IN: $msg_header (+): message header : MIME::Head object
432
# $msg_body (+): message body
433
# $from (+): message from
434
# $rcpt(+) : ref(SCALAR) | ref(ARRAY) - message recepients
436
# $encrypt : 'smime_crypted' | undef
437
# OUT : 1 - call to smtpto (sendmail) | 0 - push in spool | undef
439
####################################################
441
my($msg_header, $msg_body, $from, $rcpt, $robot, $encrypt) = @_;
442
do_log('debug2', 'mail::sendto(%s, %s, %s', $from, $rcpt, $encrypt);
446
## Encode subject before sending
447
$msg_header->replace('Subject', MIME::Words::encode_mimewords($msg_header->get('Subject')));
449
if ($encrypt eq 'smime_crypted') {
451
if (ref($rcpt) eq 'SCALAR') {
452
$email = lc ($$rcpt) ;
456
do_log('err',"incorrect call for encrypt with $#rcpts recipient(s)");
459
$email = lc ($rcpt->[0]);
461
$msg = &tools::smime_encrypt ($msg_header, $msg_body, $email);
157
$to = join(",\n ", @{$rcpt});
463
$msg = $msg_header->as_string . "\n" . $msg_body;
467
my $result = &sending($msg,$rcpt,$from,$robot,'','none');
164
# unless ($sign_mode eq 'smime') {
166
## Don't fork if used by a CGI (FastCGI problem)
167
if (defined $send_spool) {
168
my $sympa_email = $data->{'conf'}{'sympa'} || &Conf::get_robot_conf($robot, 'sympa');
169
$sympa_file = "$send_spool/T.$sympa_email.".time.'.'.int(rand(10000));
171
unless (open TMPMSG, ">$sympa_file") {
172
&do_log('notice', 'Cannot create %s : %s', $sympa_file, $!);
176
printf TMPMSG "X-Sympa-To: %s\n", $rcpt;
177
printf TMPMSG "X-Sympa-From: %s\n", $data->{'return_path'};
178
printf TMPMSG "X-Sympa-Checksum: %s\n", &tools::sympa_checksum($rcpt);
180
$sendmail = \*TMPMSG;
184
$sendmail = &smtp::smtpto($data->{'return_path'}, $rcpt);
186
$sendmail = &smtp::smtpto($data->{'return_path'}, \$rcpt);
191
## Does the file include headers ?
192
if ($filename =~ /\.tpl$/) {
194
my $first_line = <TPL>;
195
$full_msg = 1 if ($first_line =~ /^From:\s/);
199
## If message needs to be signed
201
if ($sign_mode eq 'smime') {
202
$tmp_file = $Conf{'tmpdir'}.'/sympa_mailfile_'.time.'.'.$$;
204
unless (open TMPSMIME, ">$tmp_file") {
205
&do_log('notice', 'Cannot create %s : %s', $tmp_file, $!);
476
####################################################
478
####################################################
479
# send a message using smpto function or puting it
480
# in spool according to the context
484
# IN : -$msg(+) : ref(MIME::Entity) | string - message to send
485
# -$rcpt(+) : ref(SCALAR) | ref(ARRAY) - recepients
486
# (for SMTP : "RCPT To:" field)
487
# -$from(+) : for SMTP "MAIL From:" field , for
488
# spool sending : "X-Sympa-From" field
490
# -$listname : listname | ''
491
# -$sign_mode(+) : 'smime' | 'none' for signing
492
# -$sympa_email : for the file name for spool
494
# OUT : 1 - call to smtpto (sendmail) | 0 - push in spool
497
####################################################
499
my ($msg,$rcpt,$from,$robot,$listname,$sign_mode,$sympa_email) = @_;
500
&do_log('debug3', 'mail::sending()');
503
my $signed_msg; # if signing
507
## Don't fork if used by a CGI (FastCGI problem)
508
if (defined $send_spool) {
509
unless ($sympa_email) {
510
$sympa_email = &Conf::get_robot_conf($robot, 'sympa');
513
$sympa_file = "$send_spool/T.$sympa_email.".time.'.'.int(rand(10000));
516
if (ref($rcpt) eq "ARRAY") {
517
$all_rcpt = join (',', @$rcpt);
522
unless (open TMP, ">$sympa_file") {
523
&do_log('notice', 'mail::sending : Cannot create %s : %s', $sympa_file, $!);
527
printf TMP "X-Sympa-To: %s\n", $all_rcpt;
528
printf TMP "X-Sympa-From: %s\n", $from;
529
printf TMP "X-Sympa-Checksum: %s\n", &tools::sympa_checksum($all_rcpt);
539
if ($sign_mode eq 'smime') {
540
my $parser = new MIME::Parser;
541
$parser->output_to_core(1);
544
if (ref($msg) eq "MIME::Entity") {
549
unless ($in_msg = $parser->parse_data($msg)) {
550
&do_log('notice', 'mail::sending : unable to parse message for signing', $listname);
555
unless ($signed_msg = &tools::smime_sign($in_msg,$listname, $robot)) {
556
&do_log('notice', 'mail::sending : unable to sign message from %s', $listname);
561
*SMTP = &smtpto($from, $rcpt, $robot);
567
if (ref($signed_msg)) {
568
$signed_msg->print(\*SMTP);
570
}elsif (ref($msg) eq "MIME::Entity") {
578
## If spool sending : renaming file
579
if (defined $sympa_file) {
580
my $new_file = $sympa_file;
581
$new_file =~ s/T\.//g;
583
unless (rename $sympa_file, $new_file) {
584
&do_log('notice', 'mail::sending : Cannot rename %s to %s : %s', $sympa_file, $new_file, $!);
590
if (defined $send_spool) {
598
##################################################################################
600
##################################################################################
601
# Makes a sendmail ready for the recipients given as argument, uses a file
602
# descriptor in the smtp table which can be imported by other parties.
603
# Before, waits for number of children process < number allowed by sympa.conf
605
# IN : $from :(+) for SMTP "MAIL From:" field
606
# $rcpt :(+) ref(SCALAR)|ref(ARRAY)- for SMTP "RCPT To:" field
608
# OUT : mail::$fh - file handle on opened file for ouput, for SMTP "DATA" field
611
##################################################################################
613
my($from, $rcpt, $robot, $sign_mode) = @_;
616
&do_log('err', 'Missing Return-Path in mail::smtpto()');
619
if (ref($rcpt) eq 'SCALAR') {
620
&do_log('debug2', 'mail::smtpto(%s, %s, %s )', $from, $$rcpt,$sign_mode);
214
printf $fh "To: %s\n", $to;
217
## Not a complete MIME message
218
unless ( $full_msg or ($filename =~ /\.mime$/) ){
219
print $fh "From: $data->{'from'}\n";
220
print $fh "Subject: $data->{'subject'}\n";
221
print $fh "Reply-to: $data->{'replyto'}\n" if ($data->{'replyto'}) ;
222
printf $fh "MIME-Version: %s\n", Msg(12, 1, '1.0');
223
printf $fh "Content-Type: text/plain; charset=%s\n", Msg(12, 2, 'us-ascii');
224
printf $fh "Content-Transfer-Encoding: %s\n", Msg(12, 3, '7bit');
229
if ($filename =~ /\.tpl$/) {
230
&parser::parse_tpl($data, $filename, $fh);
622
&do_log('debug2', 'mail::smtpto(%s, %s, %s)', $from, join(',', @{$rcpt}), $sign_mode);
627
## Escape "-" at beginning of recepient addresses
628
## prevent sendmail from taking it as argument
630
if (ref($rcpt) eq 'SCALAR') {
236
s/\[listname\]/$data->{'list'}{'name'}/g;
237
s/\[subscriber_email\]/$data->{'user'}{'email'}/g;
238
s/\[email_subscriber\]/$data->{'user'}{'email'}/g;
239
s/\[subscriber_gecos\]/$data->{'user'}{'gecos'}/g;
240
s/\[sympa_email\]/$data->{'conf'}{'sympa'}/g;
241
s/\[sympa_host\]/$data->{'conf'}{'host'}/g;
634
foreach my $i (0..$#emails) {
635
$rcpt->[$i] =~ s/^-/\\-/;
247
print $fh $data->{'body'};
251
if ($sign_mode eq 'smime') {
252
## Open and parse the file
253
if (!open(MSG, $tmp_file)) {
254
&do_log('info', 'Can\'t open %s: %m', $tmp_file);
258
my $parser = new MIME::Parser;
259
$parser->output_to_core(1);
261
unless ($in_msg = $parser->read(\*MSG)) {
262
do_log('notice', 'Unable to parse message %s', $file);
268
## Signing the message
270
unless ($signed_msg = &tools::smime_sign($in_msg,$data->{'list'}{'name'}, $data->{'list'}{'dir'})) {
271
do_log('notice', 'Unable to sign message from %s', $data->{'list'}{'name'});
274
# dump signed message to sendmail
276
$signed_msg->print($sendmail);
281
if (defined $sympa_file) {
282
my $new_file = $sympa_file;
283
$new_file =~ s/T\.//g;
285
unless (rename $sympa_file, $new_file) {
286
&do_log('notice', 'Cannot rename %s to %s : %s', $sympa_file, $new_file, $!);
639
## Check how many open smtp's we have, if too many wait for a few
640
## to terminate and then do our job.
642
do_log('debug3',"Open = $opensmtp");
643
while ($opensmtp > &Conf::get_robot_conf($robot, 'maxsmtp')) {
644
do_log('debug3',"mail::smtpto: too many open SMTP ($opensmtp), calling reaper" );
645
last if (&reaper(0) == -1); ## Blocking call to the reaper.
648
*IN = ++$fh; *OUT = ++$fh;
651
if (!pipe(IN, OUT)) {
652
fatal_err(sprintf gettext("Unable to create a channel in smtpto: %m"), $!); ## No return
654
$pid = &tools::safefork();
657
my $sendmail = &Conf::get_robot_conf($robot, 'sendmail');
658
my $sendmail_args = &Conf::get_robot_conf($robot, 'sendmail_args');
664
if (ref($rcpt) eq 'SCALAR') {
665
exec $sendmail, split(/\s+/,$sendmail_args), '-f', $from, $$rcpt;
667
exec $sendmail, split(/\s+/,$sendmail_args), '-f', $from, @$rcpt;
669
exit 1; ## Should never get there.
671
if ($main::options{'mail'}) {
672
$str = "safefork: $sendmail $sendmail_args -f $from ";
673
if (ref($rcpt) eq 'SCALAR') {
676
$str .= join(' ', @$rcpt);
678
do_log('notice', $str);
682
select(undef, undef,undef, 0.3) if ($opensmtp < &Conf::get_robot_conf($robot, 'maxsmtp'));
683
return("mail::$fh"); ## Symbol for the write descriptor.
690
####################################################
691
# send_in_spool : not used but if needed ...
692
####################################################
693
# send a message by putting it in global $send_spool
695
# IN : $rcpt (+): ref(SCALAR)|ref(ARRAY) - recepients
697
# $sympa_email : for the file name
698
# $XSympaFrom : for "X-Sympa-From" field
700
# -filename : name of temporary file
701
# needing to be renamed
702
# -fh : file handle opened for writing
704
####################################################
706
my ($rcpt,$robot,$sympa_email,$XSympaFrom) = @_;
707
&do_log('debug3', 'mail::send_in_spool(%s,%s, %s)',$XSympaFrom,$rcpt);
709
unless ($sympa_email) {
710
$sympa_email = &Conf::get_robot_conf($robot, 'sympa');
713
unless ($XSympaFrom) {
714
$XSympaFrom = &Conf::get_robot_conf($robot, 'sympa');
717
my $sympa_file = "$send_spool/T.$sympa_email.".time.'.'.int(rand(10000));
720
if (ref($rcpt) eq "ARRAY") {
721
$all_rcpt = join (',', @$rcpt);
726
unless (open TMP, ">$sympa_file") {
727
&do_log('notice', 'Cannot create %s : %s', $sympa_file, $!);
731
printf TMP "X-Sympa-To: %s\n", $all_rcpt;
732
printf TMP "X-Sympa-From: %s\n", $XSympaFrom;
733
printf TMP "X-Sympa-Checksum: %s\n", &tools::sympa_checksum($all_rcpt);
736
$return->{'filename'} = $sympa_file;
737
$return->{'fh'} = \*TMP;
742
#####################################################################