]> git.donarmstrong.com Git - debbugs.git/blob - scripts/process.in
[project @ 2003-05-03 20:01:20 by doogie]
[debbugs.git] / scripts / process.in
1 #!/usr/bin/perl
2 # $Id: process.in,v 1.66 2003/05/03 20:01:20 doogie Exp $
3 #
4 # Usage: process nn
5 # Temps:  incoming/Pnn
6
7 use Mail::Address;
8 use MIME::Parser;
9
10 $config_path = '/etc/debbugs';
11 $lib_path = '/usr/lib/debbugs';
12
13 require "$config_path/config";
14 require "$lib_path/errorlib";
15 $ENV{'PATH'} = $lib_path.':'.$ENV{'PATH'};
16
17 chdir( "$gSpoolDir" ) || die "chdir spool: $!\n";
18
19 #open(DEBUG,"> /tmp/debbugs.debug");
20 umask(002);
21 open DEBUG, ">/dev/null";
22
23 defined( $intdate= time ) || &quit( "failed to get time: $!" );
24
25 $_=shift;
26 m/^([BMQFDU])(\d*)\.\d+$/ || &quit("bad argument");
27 $codeletter= $1;
28 $tryref= length($2) ? $2+0 : -1;
29 $nn= $_;
30
31 if (!rename("incoming/G$nn","incoming/P$nn")) 
32 {
33     $_=$!.'';  m/no such file or directory/i && exit 0;
34     &quit("renaming to lock: $!");
35 }
36
37 $baddress= 'submit' if $codeletter eq 'B';
38 $baddress= 'maintonly' if $codeletter eq 'M';
39 $baddress= 'quiet' if $codeletter eq 'Q';
40 $baddress= 'forwarded' if $codeletter eq 'F';
41 $baddress= 'done' if $codeletter eq 'D';
42 $baddress= 'submitter' if $codeletter eq 'U';
43 $baddress || &quit("bad codeletter $codeletter");
44 $baddressroot= $baddress;
45 $baddress= "$tryref-$baddress" if $tryref>=0;
46
47 open(M,"incoming/P$nn");
48 @log=<M>;
49 close(M);
50
51 @msg=@log;
52 chomp @msg;
53
54 print DEBUG "###\n",join("##\n",@msg),"\n###\n";
55
56 chop($tdate= `date -u '+%a, %d %h %Y %T GMT'`);
57 $fwd= <<END;
58 Received: via spool by $baddress\@$gEmailDomain id=$nn
59           (code $codeletter ref $tryref); $tdate
60 END
61
62 # header and decoded body respectively
63 my (@headerlines, @bodylines);
64
65 my $parser = new MIME::Parser;
66 mkdir "$gSpoolDir/mime.tmp", 0777;
67 $parser->output_under("$gSpoolDir/mime.tmp");
68 my $entity = eval { $parser->parse_data(join('',@log)) };
69
70 if ($entity and $entity->head->tags) {
71     @headerlines = @{$entity->head->header};
72     chomp @headerlines;
73
74     my $entity_body = getmailbody($entity);
75     @bodylines = $entity_body ? $entity_body->as_lines() : ();
76     chomp @bodylines;
77
78     # set $i to beginning of encoded body data, so we can dump it out
79     # verbatim later
80     $i = 0;
81     ++$i while $msg[$i] =~ /./;
82 } else {
83     # Legacy pre-MIME code, kept around in case MIME::Parser fails.
84     for ($i = 0; $i <= $#msg; $i++) {
85         $_ = $msg[$i];
86         last unless length($_);
87         while ($msg[$i+1] =~ m/^\s/) {
88             $i++;
89             $_ .= "\n".$msg[$i];
90         }
91         push @headerlines, $_;
92     }
93
94     @bodylines = @msg[$i..$#msg];
95 }
96
97 for my $hdr (@headerlines) {
98     $_ = $hdr;
99     s/\n\s/ /g;
100     &finish if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
101     my $ins = !m/^subject:/i && !m/^reply-to:/i && !m/^return-path:/i
102            && !m/^From / && !m/^X-Debbugs-CC:/i;
103     $fwd .= $hdr."\n" if $ins;
104     # print DEBUG ">$_<\n";
105     if (s/^(\S+):\s*//) {
106         my $v = lc $1;
107         print DEBUG ">$v=$_<\n";
108         $header{$v} = $_;
109     } else {
110         print DEBUG "!>$_<\n";
111     }
112 }
113
114 # remove blank lines
115 shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
116
117 # Strip off RFC2440-style PGP clearsigning.
118 if (@bodylines and $bodylines[0] =~ /^-----BEGIN PGP SIGNED/) {
119     shift @bodylines while @bodylines and length $bodylines[0];
120     shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
121     for my $findsig (0 .. $#bodylines) {
122         if ($bodylines[$findsig] =~ /^-----BEGIN PGP SIGNATURE/) {
123             $#bodylines = $findsig - 1;
124             last;
125         }
126     }
127     map { s/^- // } @bodylines;
128 }
129
130 # extract pseudo-headers
131 for my $phline (@bodylines)
132 {
133     last if $phline !~ m/^([\w]+):\s*(\S.*)/;
134     my ($fn, $fv) = ($1, $2);
135     print DEBUG ">$fn|$fv|\n";
136     $fn = lc $fn;
137     $fv = lc $fv;
138     $pheader{$fn} = $fv;
139     print DEBUG ">$fn~$fv<\n";
140 }
141
142
143 $fwd .= join("\n",@msg[$i..$#msg]);
144
145 print DEBUG "***\n$fwd\n***\n";
146
147 if (defined $header{'resent-from'} && !defined $header{'from'}) {
148     $header{'from'} = $header{'resent-from'};
149 }
150 defined($header{'from'}) || &quit("no From header");
151 $replyto= defined($header{'reply-to'}) ? $header{'reply-to'} : $header{'from'};
152
153 $_= $replyto;
154 $_= "$2 <$1>" if m/^([^\<\> \t\n\(\)]+) \(([^\(\)\<\>]+)\)$/;
155 $replytocompare= $_;
156 print DEBUG "replytocompare >$replytocompare<\n";
157     
158 if (!defined($header{'subject'})) 
159 {
160         $brokenness.= <<END;
161
162 Your message did not contain a Subject field. They are recommended and
163 useful because the title of a $gBug is determined using this field.
164 Please remember to include a Subject field in your messages in future.
165 END
166
167 # RFC822 actually lists it as an `optional-field'.
168
169     $subject= '(no subject)';
170 } else { 
171     $subject= $header{'subject'}; 
172 }
173
174 $ref=-1;
175 $subject =~ s/^Re:\s*//i; $_= $subject."\n";
176 if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) {
177     $tryref= $1+0; 
178 }
179
180 if ($tryref >= 0) 
181 {
182     ($bfound, $data)= &lockreadbugmerge($tryref);
183     if ($bfound) { 
184         $ref= $tryref; 
185     } else {
186         &htmllog("Reply","sent", $replyto,"Unknown problem report number <code>$tryref</code>.");
187         &sendmessage(<<END, '');
188 From: $gMaintainerEmail ($gProject $gBug Tracking System)
189 To: $replyto
190 Subject: Unknown problem report $gBug#$tryref ($subject)
191 Message-ID: <handler.x.$nn.unknown\@$gEmailDomain>
192 In-Reply-To: $header{'message-id'}
193 References: $header{'message-id'} $data->{msgid}
194 Precedence: bulk
195 X-$gProject-PR-Message: error
196
197 You sent a message to the $gBug tracking system which gave (in the
198 Subject line or encoded into the recipient at $gEmailDomain),
199 the number of a nonexistent $gBug report (#$tryref).
200
201 This may be because that $gBug report has been resolved for more than $gRemoveAge
202 days, and the record of it has been expunged, or because you mistyped
203 the $gBug report number.
204
205 Your message was dated $header{'date'} and was sent to
206 $baddress\@$gEmailDomain.  It had
207 Message-ID $header{'message-id'}
208 and Subject $subject.
209
210 It has been filed (under junk) but otherwise ignored.
211
212 Please consult your records to find the correct $gBug report number, or
213 contact me, the system administrator, for assistance.
214
215 $gMaintainer
216 (administrator, $gProject $gBugs database)
217
218 (NB: If you are a system administrator and have no idea what I am
219 talking about this indicates a serious mail system misconfiguration
220 somewhere.  Please contact me immediately.)
221
222 END
223         &appendlog;
224         &finish;
225     }
226 } else { 
227     &filelock('lock/-1'); 
228 }
229
230 if ($codeletter eq 'D' || $codeletter eq 'F') 
231 {
232     if ($replyto =~ m/$gBounceFroms/o ||
233         $header{'from'} =~ m/$gBounceFroms/o)
234     { 
235         &quit("bounce detected !  Mwaap! Mwaap!"); 
236     }
237     $markedby= $header{'from'} eq $replyto ? $replyto :
238                "$header{'from'} (reply to $replyto)";
239     if ($codeletter eq 'F') {
240         (&appendlog,&finish) if length($data->{forwarded});
241         $receivedat= "forwarded\@$gEmailDomain";
242         $markaswhat= 'forwarded';
243         $set_forwarded= $header{'to'};
244         if ( length( $gListDomain ) > 0 && length( $gFowardList ) > 0 ) {
245             $generalcc= "$gFowardList\@$gListDomain";
246         } else { 
247             $generalcc=''; 
248         }
249     } else {
250         (&appendlog,&finish) if length($data->{done});
251         $receivedat= "done\@$gEmailDomain";
252         $markaswhat= 'done';
253         $set_done= $header{'from'};
254         if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) {
255             $generalcc= "$gDoneList\@$gListDomain";
256         } else { 
257             $generalcc=''; 
258         }
259     }
260     if ($ref<0) {
261         &htmllog("Warning","sent",$replyto,"Message ignored.");
262         &sendmessage(<<END, '');
263 From: $gMaintainerEmail ($gProject $gBug Tracking System)
264 To: $replyto
265 Subject: Message with no $gBug number ignored by $receivedat
266          ($subject)
267 Message-ID: <header.x.$nn.warnignore\@$gEmailDomain>
268 In-Reply-To: $header{'message-id'}
269 References: $header{'message-id'} $data->{msgid}
270 Precedence: bulk
271 X-$gProject-PR-Message: error
272
273 You sent a message to the $gProject $gBug tracking system old-style
274 unified mark as $markaswhat address ($receivedat),
275 without a recognisable $gBug number in the Subject.
276 Your message has been filed under junk but otherwise ignored.
277
278 If you don't know what I'm talking about then probably either:
279
280 (a) you unwittingly sent a message to done\@$gEmailDomain
281 because you replied to all recipients of the message a developer used
282 to mark a $gBug as done and you modified the Subject.  In this case,
283 please do not be alarmed.  To avoid confusion do not do it again, but
284 there is no need to apologise or mail anyone asking for an explanation.
285
286 (b) you are a system administrator, reading this because the $gBug 
287 tracking system is responding to a misdirected bounce message.  In this
288 case there is a serious mail system misconfiguration somewhere - please
289 contact me immediately.
290
291 Your message was dated $header{'date'} and had
292 message-id $header{'message-id'}
293 and subject $subject.
294
295 If you need any assistance or explanation please contact me.
296
297 $gMaintainer
298 (administrator, $gProject $gBugs database)
299
300 END
301         &appendlog;
302         &finish;
303     }
304
305     &checkmaintainers;
306
307     $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs,@addsrcaddrs));
308     $noticeccval =~ s/\s+\n\s+/ /g; 
309     $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
310
311     if (length($noticeccval)) { $noticecc= "Cc: $noticeccval\n"; }
312     if (length($generalcc)) { $noticecc.= "Bcc: $generalcc\n"; }
313
314     @process= ($ref,split(/ /,$data->{mergedwith}));
315     $orgref= $ref;
316
317     for $ref (@process) {
318         if ($ref != $orgref) {
319             &unfilelock;
320             $data = &lockreadbug($ref)
321                 || die "huh ? $ref from $orgref out of @process";
322         }
323         $data->{done}= $set_done if defined($set_done);
324         $data->{forwarded}= $set_forwarded if defined($set_forwarded);
325         writebug($ref, $data);
326
327         my $hash = get_hashname($ref);
328         open(O,"db-h/$hash/$ref.report") || &quit("read original report: $!");
329         $x= join('',<O>); close(O);
330         if ($codeletter eq 'F') {
331             &htmllog("Reply","sent",$replyto,"You have marked $gBug as forwarded.");
332             &sendmessage(<<END."---------------------------------------\n".join( "\n", @msg ), '');
333 From: $gMaintainerEmail ($gProject $gBug Tracking System)
334 To: $replyto
335 ${noticecc}Subject: $gBug#$ref: marked as forwarded ($data->{subject})
336 Message-ID: <header.$ref.$nn.ackfwdd\@$gEmailDomain>
337 In-Reply-To: $header{'message-id'}
338 References: $header{'message-id'} $data->{msgid}
339 Precedence: bulk
340 X-$gProject-PR-Message: forwarded $ref
341 X-$gProject-PR-Package: $data->{package}
342 X-$gProject-PR-Keywords: $data->{keywords}
343
344 Your message dated $header{'date'}
345 with message-id $header{'message-id'}
346 has caused the $gProject $gBug report #$ref,
347 regarding $data->{subject}
348 to be marked as having been forwarded to the upstream software
349 author(s) $data->{forwarded}.
350
351 (NB: If you are a system administrator and have no idea what I am
352 talking about this indicates a serious mail system misconfiguration
353 somewhere.  Please contact me immediately.)
354
355 $gMaintainer
356 (administrator, $gProject $gBugs database)
357
358 END
359
360         } else {
361             &htmllog("Reply","sent",$replyto,"You have taken responsibility.");
362             &sendmessage(<<END."--------------------------------------\n".$x."---------------------------------------\n".join( "\n", @msg ), '');
363 From: $gMaintainerEmail ($gProject $gBug Tracking System)
364 To: $replyto
365 ${noticecc}Subject: $gBug#$ref: marked as done ($data->{subject})
366 Message-ID: <handler.$ref.$nn.ackdone\@$gEmailDomain>
367 In-Reply-To: $header{'message-id'}
368 References: $header{'message-id'} $data->{msgid}
369 Precedence: bulk
370 X-$gProject-PR-Message: closed $ref
371 X-$gProject-PR-Package: $data->{package}
372 X-$gProject-PR-Keywords: $data->{keywords}
373
374 Your message dated $header{'date'}
375 with message-id $header{'message-id'}
376 and subject line $subject
377 has caused the attached $gBug report to be marked as done.
378
379 This means that you claim that the problem has been dealt with.
380 If this is not the case it is now your responsibility to reopen the
381 $gBug report if necessary, and/or fix the problem forthwith.
382
383 (NB: If you are a system administrator and have no idea what I am
384 talking about this indicates a serious mail system misconfiguration
385 somewhere.  Please contact me immediately.)
386
387 $gMaintainer
388 (administrator, $gProject $gBugs database)
389
390 END
391             &htmllog("Notification","sent",$data->{originator}, 
392                 "$gBug acknowledged by developer.");
393             &sendmessage(<<END.join("\n",@msg),'');
394 From: $gMaintainerEmail ($gProject $gBug Tracking System)
395 To: $data->{originator}
396 Subject: $gBug#$ref acknowledged by developer
397          ($header{'subject'})
398 Message-ID: <handler.$ref.$nn.notifdone\@$gEmailDomain>
399 In-Reply-To: $data->{msgid}
400 References: $header{'message-id'} $data->{msgid}
401 X-$gProject-PR-Message: they-closed $ref
402 X-$gProject-PR-Package: $data->{package}
403 X-$gProject-PR-Keywords: $data->{keywords}
404 Reply-To: $ref\@$gEmailDomain
405
406 This is an automatic notification regarding your $gBug report
407 #$ref: $data->{subject},
408 which was filed against the $data->{package} package.
409
410 It has been closed by one of the developers, namely
411 $markedby.
412
413 Their explanation is attached below.  If this explanation is
414 unsatisfactory and you have not received a better one in a separate
415 message then please contact the developer, by replying to this email.
416
417 $gMaintainer
418 (administrator, $gProject $gBugs database)
419
420 END
421         }
422         &appendlog;
423     }
424     &finish;
425 }
426
427 if ($ref<0) {
428     if ($codeletter eq 'U') {
429         &htmllog("Warning","sent",$replyto,"Message not forwarded.");
430         &sendmessage(<<END, '');
431 From: $gMaintainerEmail ($gProject $gBug Tracking System)
432 To: $replyto
433 Subject: Message with no $gBug number cannot be sent to submitter !
434          ($subject)
435 Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
436 In-Reply-To: $header{'message-id'}
437 References: $header{'message-id'} $data->{msgid}
438 Precedence: bulk
439 X-$gProject-PR-Message: error
440
441 You sent a message to the $gProject $gBug tracking system send to $gBug 
442 report submitter address $baddress\@$gEmailDomain, without a
443 recognisable $gBug number in the Subject.  Your message has been filed
444 under junk but otherwise ignored.
445
446 If you don't know what I'm talking about then probably either:
447
448 (a) you unwittingly sent a message to $baddress\@$gEmailDomain
449 because you replied to all recipients of the message a developer sent
450 to a $gBug's submitter and you modified the Subject.  In this case,
451 please do not be alarmed.  To avoid confusion do not do it again, but
452 there is no need to apologise or mail anyone asking for an
453 explanation.
454
455 (b) you are a system administrator, reading this because the $gBug 
456 tracking system is responding to a misdirected bounce message.  In this
457 case there is a serious mail system misconfiguration somewhere - please
458 contact me immediately.
459
460 Your message was dated $header{'date'} and had
461 message-id $header{'message-id'}
462 and subject $subject.
463
464 If you need any assistance or explanation please contact me.
465
466 $gMaintainer
467 (administrator, $gProject $gBugs database)
468
469 END
470         &appendlog;
471         &finish;
472     }
473     if (!defined($pheader{'package'})) {
474         &htmllog("Warning","sent",$replyto,"Message not forwarded.");
475         &sendmessage(<<END."---------------------------------------------------------------------------\n".join("\n", @msg), '');
476 From: $gMaintainerEmail ($gProject $gBug Tracking System)
477 To: $replyto
478 Subject: Message with no Package: tag cannot be processed!
479          ($subject)
480 Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
481 In-Reply-To: $header{'message-id'}
482 References: $header{'message-id'} $data->{msgid}
483 Precedence: bulk
484 X-$gProject-PR-Message: error
485
486 Your message didn't have a Package: line at the start (in the
487 pseudo-header following the real mail header), or didn't have a
488 pseudo-header at all.
489
490 This makes it much harder for us to categorise and deal with your
491 problem report. Please _resubmit_ your report to $baddress\@$gEmailDomain
492 and tell us which package the report is on. For help, check out
493 http://$gWebDomain/Reporting$gHTMLSuffix.
494
495 Your message was dated $header{'date'} and had
496 message-id $header{'message-id'}
497 and subject $subject.
498 The complete text of it is attached to this message.
499
500 If you need any assistance or explanation please contact me.
501
502 $gMaintainer
503 (administrator, $gProject $gBugs database)
504
505 END
506         &appendlog;
507         &finish;
508     } else {
509         $data->{package}= $pheader{'package'}; 
510     }
511
512     $data->{versions}= '';
513     if (defined($pheader{'version'})) {
514         $data->{versions} = $pheader{'version'};
515         $data->{versions} =~ s/\s+/ /;
516         # BUG: need to bounce unknown versions back to submitter here
517     }
518
519     $data->{fixed_versions}= '';
520     if (defined($pheader{'fixed-in-version'})) {
521         $data->{fixed_versions} = $pheader{'fixed-in-version'};
522         $data->{fixed_versions} =~ s/\s+/ /;
523     }
524
525     $data->{keywords}= '';
526     if (defined($pheader{'keywords'})) {
527         $data->{keywords}= $pheader{'keywords'};
528     } elsif (defined($pheader{'tags'})) {
529         $data->{keywords}= $pheader{'tags'};
530     }
531     if (length($data->{keywords})) {
532         my @kws;
533         my %gkws = map { ($_, 1) } @gTags;
534         foreach my $kw (sort split(/[,\s]+/, lc($data->{keywords}))) {
535             push @kws, $kw if (defined $gkws{$kw});
536         }
537         $data->{keywords} = join(" ", @kws);
538     }
539     $data->{severity}= '';
540     if (defined($pheader{'severity'}) || defined($pheader{'priority'})) {
541         $data->{severity}= $pheader{'severity'};
542         $data->{severity}= $pheader{'priority'} unless ($data->{severity});
543         $data->{severity} =~ s/^\s*(.+)\s*$/$1/;
544
545         if (!grep($_ eq $data->{severity}, @severities, "$gDefaultSeverity")) {
546             $brokenness.= <<END;
547
548 Your message specified a Severity: in the pseudo-header, but
549 the severity value $data->{severity} was not recognised.
550 The default severity $gDefaultSeverity is being used instead.
551 The recognised values are: $gShowSeverities.
552 END
553 # if we use @gSeverityList array in the above line, perl -c gives:
554 # In string, @gSeverityList now must be written as \@gSeverityList at
555 #          process line 452, near "$gDefaultSeverity is being used instead.
556             $data->{severity}= '';
557         }
558     }
559     &filelock("nextnumber.lock");
560     open(N,"nextnumber") || &quit("nextnumber: read: $!");
561     $v=<N>; $v =~ s/\n$// || &quit("nextnumber bad format");
562     $ref= $v+0;  $v += 1;  $newref=1;
563     &overwrite('nextnumber', "$v\n");
564     &unfilelock;
565     my $hash = get_hashname($ref);
566     &overwrite("db-h/$hash/$ref.log",'');
567     $data->{originator} = $replyto;
568     $data->{date} = $intdate;
569     $data->{subject} = $subject;
570     $data->{msgid} = $header{'message-id'};
571     writebug($ref, $data);
572     &overwrite("db-h/$hash/$ref.report",
573                join("\n",@msg)."\n");
574 }
575
576 &checkmaintainers;
577
578 print DEBUG "maintainers >@maintaddrs<\n";
579
580 $orgsender= defined($header{'sender'}) ? "Original-Sender: $header{'sender'}\n" : '';
581 $newsubject= $subject;  $newsubject =~ s/^$gBug#$ref:*\s*//;
582
583 $xcchdr= $header{ 'x-debbugs-cc' };
584 if ($xcchdr =~ m/\S/) {
585     push(@resentccs,$xcchdr);
586     $resentccexplain.= <<END;
587
588 As you requested using X-Debbugs-CC, your message was also forwarded to
589    $xcchdr
590 (after having been given a $gBug report number, if it did not have one).
591 END
592 }
593
594 if (@maintaddrs && ($codeletter eq 'B' || $codeletter eq 'M')) {
595     push(@resentccs,@maintaddrs);
596     $resentccexplain.= <<END." ".join("\n ",@maintaddrs)."\n";
597
598 Your message has been sent to the package maintainer(s):
599 END
600 }
601
602 push(@resentccs, @addsrcaddrs);
603
604 $veryquiet= $codeletter eq 'Q';
605 if ($codeletter eq 'M' && !@maintaddrs) {
606     $veryquiet= 1;
607     $brokenness.= <<END;
608
609 You requested that the message be sent to the package maintainer(s)
610 but either the $gBug report is not associated with any package (probably
611 because of a missing Package pseudo-header field in the original $gBug
612 report), or the package(s) specified do not have any maintainer(s).
613
614 Your message has *not* been sent to any package maintainers; it has
615 merely been filed in the $gBug tracking system.  If you require assistance
616 please contact $gMaintainerEmail quoting the $gBug number $ref.
617 END
618 }
619
620 $resentccval.= join(', ',@resentccs);
621 $resentccval =~ s/\s+\n\s+/ /g; $resentccval =~ s/^\s+/ /; $resentccval =~ s/\s+$//;
622 if (length($resentccval)) { 
623     $resentcc= "Resent-CC: $resentccval\n"; 
624 }
625
626 if ($codeletter eq 'U') {
627     &htmllog("Message", "sent on", $data->{originator}, "$gBug#$ref.");
628     &sendmessage(<<END,$data->{originator},@resentccs);
629 Subject: $gBug#$ref: $newsubject
630 Reply-To: $replyto, $ref-quiet\@$gEmailDomain
631 ${orgsender}Resent-To: $data->{originator}
632 ${resentcc}Resent-Date: $tdate
633 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
634 Resent-Sender: $gMaintainerEmail
635 X-$gProject-PR-Message: report $ref
636 X-$gProject-PR-Package: $data->{package}
637 X-$gProject-PR-Keywords: $data->{keywords}
638 $fwd
639 END
640 } elsif ($codeletter eq 'B') {
641     &htmllog($newref ? "Report" : "Information", "forwarded",
642              join(', ',"$gSubmitList\@$gListDomain",@resentccs),
643              "<code>$gBug#$ref</code>".
644              (length($data->{package})? "; Package <code>".&sani($data->{package})."</code>" : '').
645              ".");
646     &sendmessage(<<END,"$gSubmitList\@$gListDomain",@resentccs);
647 Subject: $gBug#$ref: $newsubject
648 Reply-To: $replyto, $ref\@$gEmailDomain
649 Resent-From: $header{'from'}
650 ${orgsender}Resent-To: $gSubmitList\@$gListDomain
651 ${resentcc}Resent-Date: $tdate
652 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
653 Resent-Sender: $gMaintainerEmail
654 X-$gProject-PR-Message: report $ref
655 X-$gProject-PR-Package: $data->{package}
656 X-$gProject-PR-Keywords: $data->{keywords}
657 $fwd
658 END
659 } elsif (@resentccs) {
660     # D and F done far earlier; B just done - so this must be M or Q
661     # We preserve whichever it was in the Reply-To (possibly adding
662     # the $gBug#).
663     &htmllog($newref ? "Report" : "Information", "forwarded",
664              $resentccval,
665              "<code>$gBug#$ref</code>".
666              (length($data->{package})? "; Package <code>".&sani($data->{package})."</code>" : '').
667              ".");
668     &sendmessage(<<END,@resentccs);
669 Subject: $gBug#$ref: $newsubject
670 Reply-To: $replyto, $ref-$baddressroot\@$gEmailDomain
671 Resent-From: $header{'from'}
672 ${orgsender}Resent-To: $resentccval
673 Resent-Date: $tdate
674 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
675 Resent-Sender: $gMaintainerEmail
676 X-$gProject-PR-Message: report $ref
677 X-$gProject-PR-Package: $data->{package}
678 X-$gProject-PR-Keywords: $data->{keywords}
679 $fwd
680 END
681 }
682
683 $htmlbreak= length($brokenness) ? "<p>\n".&sani($brokenness)."\n<p>\n" : '';
684 $htmlbreak =~ s/\n\n/\n<P>\n\n/g;
685 if (length($resentccval)) {
686     $htmlbreak = "  Copy sent to <code>".&sani($resentccval)."</code>.".
687         $htmlbreak;
688 }
689 if ($newref) {
690     &htmllog("Acknowledgement","sent",$replyto,
691              ($veryquiet ?
692               "New $gBug report received and filed, but not forwarded." :
693               "New $gBug report received and forwarded."). $htmlbreak);
694     &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
695 From: $gMaintainerEmail ($gProject $gBug Tracking System)
696 To: $replyto
697 Subject: $gBug#$ref: Acknowledgement of QUIET report
698          ($subject)
699 Message-ID: <handler.$ref.$nn.ackquiet\@$gEmailDomain>
700 In-Reply-To: $header{'message-id'}
701 References: $header{'message-id'}
702 Precedence: bulk
703 X-$gProject-PR-Message: ack-quiet $ref
704 X-$gProject-PR-Package: $data->{package}
705 X-$gProject-PR-Keywords: $data->{keywords}
706 Reply-To: $ref-quiet\@$gEmailDomain
707
708 Thank you for the problem report you have sent regarding $gProject.
709 This is an automatically generated reply, to let you know your message
710 has been received.  It has not been forwarded to the developers or
711 their mailing list; you should ensure that the developers are aware of
712 the problem you have entered into the system - preferably quoting the
713 $gBug reference number, #$ref.
714 $resentccexplain
715 If you wish to submit further information on your problem, please send it
716 to $ref-$baddressroot\@$gEmailDomain (and *not*
717 to $baddress\@$gEmailDomain).
718
719 Please do not reply to the address at the top of this message,
720 unless you wish to report a problem with the $gBug-tracking system.
721 $brokenness
722 $gMaintainer
723 (administrator, $gProject $gBugs database)
724 END
725 From: $gMaintainerEmail ($gProject $gBug Tracking System)
726 To: $replyto
727 Subject: $gBug#$ref: Acknowledgement of maintainer-only report
728          ($subject)
729 Message-ID: <handler.$ref.$nn.ackmaint\@$gEmailDomain>
730 In-Reply-To: $header{'message-id'}
731 References: $header{'message-id'}
732 Precedence: bulk
733 X-$gProject-PR-Message: ack-maintonly $ref
734 X-$gProject-PR-Package: $data->{package}
735 X-$gProject-PR-Keywords: $data->{keywords}
736 Reply-To: $ref-maintonly\@$gEmailDomain
737
738 Thank you for the problem report you have sent regarding $gProject.
739 This is an automatically generated reply, to let you know your message has
740 been received.  It is being forwarded to the developers (but not the mailing
741 list, as you requested) for their attention; they will reply in due course.
742 $resentccexplain
743 If you wish to submit further information on your problem, please send
744 it to $ref-$baddressroot\@$gEmailDomain (and *not*
745 to $baddress\@$gEmailDomain).
746
747 Please do not reply to the address at the top of this message,
748 unless you wish to report a problem with the $gBug-tracking system.
749 $brokenness
750 $gMaintainer
751 (administrator, $gProject $gBugs database)
752 END
753 From: $gMaintainerEmail ($gProject $gBug Tracking System)
754 To: $replyto
755 Subject: $gBug#$ref: Acknowledgement ($subject)
756 Message-ID: <handler.$ref.$nn.ack\@$gEmailDomain>
757 In-Reply-To: $header{'message-id'}
758 References: $header{'message-id'}
759 Precedence: bulk
760 X-$gProject-PR-Message: ack $ref
761 X-$gProject-PR-Package: $data->{package}
762 X-$gProject-PR-Keywords: $data->{keywords}
763 Reply-To: $ref\@$gEmailDomain
764
765 Thank you for the problem report you have sent regarding $gProject.
766 This is an automatically generated reply, to let you know your message has
767 been received.  It is being forwarded to the developers mailing list for
768 their attention; they will reply in due course.
769 $resentccexplain
770 If you wish to submit further information on your problem, please send
771 it to $ref\@$gEmailDomain (and *not* to
772 $baddress\@$gEmailDomain).
773
774 Please do not reply to the address at the top of this message,
775 unless you wish to report a problem with the $gBug-tracking system.
776 $brokenness
777 $gMaintainer
778 (administrator, $gProject $gBugs database)
779 END
780 } elsif ($codeletter ne 'U' and
781          $header{'precedence'} !~ /\b(?:bulk|junk|list)\b/) {
782     &htmllog("Acknowledgement","sent",$replyto,
783              ($veryquiet ? "Extra info received and filed, but not forwarded." :
784               $codeletter eq 'M' ? "Extra info received and forwarded to maintainer." :
785               "Extra info received and forwarded to list."). $htmlbreak);
786     &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
787 From: $gMaintainerEmail ($gProject $gBug Tracking System)
788 To: $replyto
789 Subject: $gBug#$ref: Info received and FILED only
790          (was $subject)
791 Message-ID: <handler.$ref.$nn.ackinfoquiet\@$gEmailDomain>
792 In-Reply-To: $header{'message-id'}
793 References: $header{'message-id'}
794 Precedence: bulk
795 X-$gProject-PR-Message: ack-info-quiet $ref
796 X-$gProject-PR-Package: $data->{package}
797 X-$gProject-PR-Keywords: $data->{keywords}
798 Reply-To: $ref-quiet\@$gEmailDomain
799
800 Thank you for the additional information you have supplied regarding
801 this problem report.  It has NOT been forwarded to the developers, but
802 will accompany the original report in the $gBug tracking system.  Please
803 ensure that you yourself have sent a copy of the additional
804 information to any relevant developers or mailing lists.
805 $resentccexplain
806 If you wish to continue to submit further information on your problem,
807 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
808
809 Please do not reply to the address at the top of this message,
810 unless you wish to report a problem with the $gBug-tracking system.
811 $brokenness
812 $gMaintainer
813 (administrator, $gProject $gBugs database)
814 END
815 From: $gMaintainerEmail ($gProject $gBug Tracking System)
816 To: $replyto
817 Subject: $gBug#$ref: Info received for maintainer only
818          (was $subject)
819 Message-ID: <handler.$ref.$nn.ackinfomaint\@$gEmailDomain>
820 In-Reply-To: $header{'message-id'}
821 References: $header{'message-id'}
822 Precedence: bulk
823 X-$gProject-PR-Message: ack-info-maintonly $ref
824 X-$gProject-PR-Package: $data->{package}
825 X-$gProject-PR-Keywords: $data->{keywords}
826 Reply-To: $ref-maintonly\@$gEmailDomain
827
828 Thank you for the additional information you have supplied regarding
829 this problem report.  It has been forwarded to the developer(s) (but
830 not to the mailing list) to accompany the original report.
831 $resentccexplain
832 If you wish to continue to submit further information on your problem,
833 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
834
835 Please do not reply to the address at the top of this message,
836 unless you wish to report a problem with the $gBug-tracking system.
837 $brokenness
838 $gMaintainer
839 (administrator, $gProject $gBugs database)
840 END
841 From: $gMaintainerEmail ($gProject $gBug Tracking System)
842 To: $replyto
843 Subject: $gBug#$ref: Info received (was $subject)
844 Message-ID: <handler.$ref.$nn.ackinfo\@$gEmailDomain>
845 In-Reply-To: $header{'message-id'}
846 References: $header{'message-id'}
847 Precedence: bulk
848 X-$gProject-PR-Message: ack-info $ref
849 X-$gProject-PR-Package: $data->{package}
850 X-$gProject-PR-Keywords: $data->{keywords}
851 Disabled-Doogie-Reply-To: $ref\@$gEmailDomain
852
853 Thank you for the additional information you have supplied regarding
854 this problem report.  It has been forwarded to the developer(s) and
855 to the developers mailing list to accompany the original report.
856 $resentccexplain
857 If you wish to continue to submit further information on your problem,
858 please send it to $ref\@$gEmailDomain, as before.
859
860 Please do not reply to the address at the top of this message,
861 unless you wish to report a problem with the $gBug-tracking system.
862 $brokenness
863 $gMaintainer
864 (administrator, $gProject $gBugs database)
865 END
866 }
867
868 &appendlog;
869 &finish;
870
871 sub overwrite {
872     local ($f,$v) = @_;
873     open(NEW,">$f.new") || &quit("$f.new: create: $!");
874     print(NEW "$v") || &quit("$f.new: write: $!");
875     close(NEW) || &quit("$f.new: close: $!");
876     rename("$f.new","$f") || &quit("rename $f.new to $f: $!");
877 }
878
879 sub appendlog {
880     my $hash = get_hashname($ref);
881     if (!open(AP,">>db-h/$hash/$ref.log")) {
882         print DEBUG "failed open log<\n";
883         print DEBUG "failed open log err $!<\n";
884         &quit("opening db-h/$hash/$ref.log (li): $!");
885     }
886     print(AP "\7\n",@{escapelog(@log)},"\n\3\n") || &quit("writing db-h/$hash/$ref.log (li): $!");
887     close(AP) || &quit("closing db-h/$hash/$ref.log (li): $!");
888 }
889
890 sub finish {
891     utime(time,time,"db");
892     local ($u);
893     while ($u= $cleanups[$#cleanups]) { &$u; }
894     unlink("incoming/P$nn") || &quit("unlinking incoming/P$nn: $!");
895     exit $_[0];
896 }
897
898 &quit("wot no exit");
899
900 sub chldhandle { $chldexit = 'yes'; }
901
902 sub htmllog {
903     local ($whatobj,$whatverb,$where,$desc) = @_;
904     my $hash = get_hashname($ref);
905     open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lh): $!");
906     print(AP
907           "\6\n".
908           "<strong>$whatobj $whatverb</strong> to <code>".&sani($where).
909           "</code>:<br>\n". $desc.
910           "\n\3\n") || &quit("writing db-h/$hash/$ref.log (lh): $!");
911     close(AP) || &quit("closing db-h/$hash/$ref.log (lh): $!");
912 }    
913
914 sub get_addresses {
915         return
916                 map { $_->address() }
917                 map { Mail::Address->parse($_) } @_;
918 }
919
920 sub sendmessage {
921     local ($msg,@recips) = @_;
922     if ($recips[0] eq '' && $#recips == 0) { @recips= ('-t'); }
923     $msg = "X-Loop: $gMaintainerEmail\n" . $msg;
924
925     my $hash = get_hashname($ref);
926     #save email to the log
927     open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lo): $!");
928     print(AP "\2\n",join("\4",@recips),"\n\5\n",@{escapelog($msg)},"\n\3\n") ||
929         &quit("writing db-h/$hash/$ref.log (lo): $!");
930     close(AP) || &quit("closing db-h/$hash/$ref.log (lo): $!");
931     
932 #if debbuging.. save email to a log
933 #    open AP, ">>debug";
934 #    print AP join( '|', @recips )."\n>>";
935 #    print AP get_addresses( @recips );
936 #    print AP "<<\n".$msg;
937 #    print AP "\n--------------------------------------------------------\n";
938 #    close AP;
939
940     #start mailing
941     $_ = '';
942     $SIG{'CHLD'}='chldhandle';
943     #print DEBUG "mailing sigchild set up<\n";
944     $chldexit = 'no';
945     $c= open(U,"-|");
946     #print DEBUG "mailing opened pipe fork<\n";
947     defined($c) || die $!;
948     #print DEBUG "mailing opened pipe fork ok $c<\n";
949     if (!$c) { # ie, we are in the child process
950         #print DEBUG "mailing child<\n";
951         unless (open(STDERR,">&STDOUT")) {
952             #print DEBUG "mailing child opened stderr<\n";
953             print STDOUT "redirect stderr: $!\n";
954             #print DEBUG "mailing child opened stderr fail<\n";
955             exit 1;
956             #print DEBUG "mailing child opened stderr fail exit !?<\n";
957         }
958         #print DEBUG "mailing child opened stderr ok<\n";
959         $c= open(D,"|-");
960         #print DEBUG "mailing child forked again<\n";
961         defined($c) || die $!;
962         #print DEBUG "mailing child forked again ok $c<\n";
963         if (!$c) { # ie, we are the child process
964             #print DEBUG "mailing grandchild<\n";
965             exec '/usr/lib/sendmail','-f'."$gMaintainerEmail",'-odq','-oem','-oi',get_addresses(@recips);
966             #print DEBUG "mailing grandchild exec failed<\n";
967             die $!;
968             #print DEBUG "mailing grandchild died !?<\n";
969         }
970         #print DEBUG "mailing child not grandchild<\n";
971         print(D $msg) || die $!;
972         #print DEBUG "mailing child printed msg<\n";
973         close(D);
974         #print DEBUG "mailing child closed pipe<\n";
975         die "\n*** command returned exit status $?\n" if $?;
976         #print DEBUG "mailing child exit status ok<\n";
977         exit 0;
978         #print DEBUG "mailing child exited ?!<\n";
979     }
980     #print DEBUG "mailing parent<\n";
981     $results='';
982     #print DEBUG "mailing parent results emptied<\n";
983     while( $chldexit eq 'no' ) { $results.= $_; }
984     #print DEBUG "mailing parent results read >$results<\n";
985     close(U);
986     #print DEBUG "mailing parent results closed<\n";
987     $results.= "\n*** child returned exit status $?\n" if $?;
988     #print DEBUG "mailing parent exit status ok<\n";
989     $SIG{'CHLD'}='DEFAULT';
990     #print DEBUG "mailing parent sigchild default<\n";
991     if (length($results)) { &quit("running sendmail: $results"); }
992     #print DEBUG "mailing parent results ok<\n";
993 }
994
995 sub checkmaintainers {
996     return if $maintainerschecked++;
997     return if !length($data->{package});
998     open(MAINT,"$gMaintainerFile") || die &quit("maintainers open: $!");
999     while (<MAINT>) {
1000         m/^\n$/ && next;
1001         m/^\s*$/ && next;
1002         m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers bogus \`$_'");
1003         $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1004         $maintainerof{$1}= $2;
1005     }
1006     close(MAINT);
1007     open(MAINT,"$gMaintainerFileOverride") || die &quit("maintainers.override open: $!");
1008     while (<MAINT>) {
1009         m/^\n$/ && next;
1010         m/^\s*$/ && next;
1011         m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers.override bogus \`$_'");
1012         $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1013         $maintainerof{$1}= $2;
1014     }
1015     close(MAINT);
1016     open(SOURCES,"$gPackageSource") || &quit("pkgsrc open: $!");
1017     while (<SOURCES>) {
1018         next unless m/^(\S+)\s+\S+\s+(\S.*\S)\s*$/;
1019         ($a,$b)=($1,$2);
1020         $a =~ y/A-Z/a-z/;
1021         $pkgsrc{$a} = $b;
1022     }
1023     close(SOURCES);
1024     $anymaintfound=0; $anymaintnotfound=0;
1025     for $p (split(m/[ \t?,()]+/,$data->{package})) {
1026         $p =~ y/A-Z/a-z/;
1027         if (defined $gSubscriptionDomain) {
1028             if (defined($pkgsrc{$p})) {
1029                 push @addsrcaddrs, "$pkgsrc{$p}\@$gSubscriptionDomain";
1030             } else {
1031                 push @addsrcaddrs, "$p\@$gSubscriptionDomain";
1032             }
1033         }
1034         if (defined($maintainerof{$p})) {
1035             print DEBUG "maintainer add >$p|$maintainerof{$p}<\n";
1036             $addmaint= $maintainerof{$p};
1037             push(@maintaddrs,$addmaint) unless
1038                 $addmaint eq $replyto || grep($_ eq $addmaint, @maintaddrs);
1039             $anymaintfound++;
1040         } else {
1041             print DEBUG "maintainer none >$p<\n";
1042             push(@maintaddrs,$gUnknownMaintainerEmail) unless $anymaintnotfound;
1043             $anymaintnotfound++;
1044             last;
1045         }
1046     }
1047 }