2 # $Id: process.in,v 1.108 2006/02/03 03:52:51 don Exp $
7 use POSIX qw(strftime tzset);
12 use Debbugs::MIME qw(decode_rfc1522 create_mime_message);
13 use Debbugs::Mail qw(send_mail_message encode_headers);
15 $config_path = '/etc/debbugs';
16 $lib_path = '/usr/lib/debbugs';
18 require "$config_path/config";
19 require "$lib_path/errorlib";
20 $ENV{'PATH'} = $lib_path.':'.$ENV{'PATH'};
22 chdir( "$gSpoolDir" ) || die "chdir spool: $!\n";
24 #open(DEBUG,"> /tmp/debbugs.debug");
26 open DEBUG, ">/dev/null";
28 defined( $intdate= time ) || &quit( "failed to get time: $!" );
31 m/^([BMQFDUL])(\d*)\.\d+$/ || &quit("bad argument");
33 $tryref= length($2) ? $2+0 : -1;
36 if (!rename("incoming/G$nn","incoming/P$nn"))
38 $_=$!.''; m/no such file or directory/i && exit 0;
39 &quit("renaming to lock: $!");
42 $baddress= 'submit' if $codeletter eq 'B';
43 $baddress= 'maintonly' if $codeletter eq 'M';
44 $baddress= 'quiet' if $codeletter eq 'Q';
45 $baddress= 'forwarded' if $codeletter eq 'F';
46 $baddress= 'done' if $codeletter eq 'D';
47 $baddress= 'submitter' if $codeletter eq 'U';
48 bug_list_forward($nn) if $codeletter eq 'L';
49 $baddress || &quit("bad codeletter $codeletter");
50 $baddressroot= $baddress;
51 $baddress= "$tryref-$baddress" if $tryref>=0;
53 open(M,"incoming/P$nn");
60 print DEBUG "###\n",join("##\n",@msg),"\n###\n";
62 $tdate = strftime "%a, %d %h %Y %T UTC", localtime;
64 Received: via spool by $baddress\@$gEmailDomain id=$nn
65 (code $codeletter ref $tryref); $tdate
68 # header and decoded body respectively
69 my (@headerlines, @bodylines);
71 my $parser = new MIME::Parser;
72 mkdir "$gSpoolDir/mime.tmp", 0777;
73 $parser->output_under("$gSpoolDir/mime.tmp");
74 my $entity = eval { $parser->parse_data(join('',@log)) };
76 if ($entity and $entity->head->tags) {
77 @headerlines = @{$entity->head->header};
80 my $entity_body = getmailbody($entity);
81 @bodylines = $entity_body ? $entity_body->as_lines() : ();
84 # set $i to beginning of encoded body data, so we can dump it out
87 ++$i while $msg[$i] =~ /./;
89 # Legacy pre-MIME code, kept around in case MIME::Parser fails.
90 for ($i = 0; $i <= $#msg; $i++) {
92 last unless length($_);
93 while ($msg[$i+1] =~ m/^\s/) {
97 push @headerlines, $_;
100 @bodylines = @msg[$i..$#msg];
103 for my $hdr (@headerlines) {
104 $hdr = decode_rfc1522($hdr);
107 &finish if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
108 my $ins = !m/^subject:/i && !m/^reply-to:/i && !m/^return-path:/i
109 && !m/^From / && !m/^X-Debbugs-/i;
110 $fwd .= $hdr."\n" if $ins;
111 # print DEBUG ">$_<\n";
112 if (s/^(\S+):\s*//) {
114 print DEBUG ">$v=$_<\n";
117 print DEBUG "!>$_<\n";
122 shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
124 # Strip off RFC2440-style PGP clearsigning.
125 if (@bodylines and $bodylines[0] =~ /^-----BEGIN PGP SIGNED/) {
126 shift @bodylines while @bodylines and length $bodylines[0];
127 shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
128 for my $findsig (0 .. $#bodylines) {
129 if ($bodylines[$findsig] =~ /^-----BEGIN PGP SIGNATURE/) {
130 $#bodylines = $findsig - 1;
134 map { s/^- // } @bodylines;
137 # extract pseudo-headers
138 for my $phline (@bodylines)
140 last if $phline !~ m/^([\w-]+):\s*(\S.*)/;
141 my ($fn, $fv) = ($1, $2);
143 print DEBUG ">$fn|$fv|\n";
147 print DEBUG ">$fn~$fv<\n";
150 # Allow pseudo headers to set x-debbugs- stuff [#179340]
151 for my $key (grep /X-Debbugs-.*/i, keys %pheader) {
152 $header{$key} = $pheader{$key} if not exists $header{$key};
155 $fwd .= join("\n",@msg[$i..$#msg]);
157 print DEBUG "***\n$fwd\n***\n";
159 if (defined $header{'resent-from'} && !defined $header{'from'}) {
160 $header{'from'} = $header{'resent-from'};
162 defined($header{'from'}) || &quit("no From header");
164 $replyto = $header{'reply-to'};
165 $replyto = '' unless defined $replyto;
168 unless (length $replyto) {
169 $replyto = $header{'from'};
173 $_= "$2 <$1>" if m/^([^\<\> \t\n\(\)]+) \(([^\(\)\<\>]+)\)$/;
175 print DEBUG "replytocompare >$replytocompare<\n";
177 if (!defined($header{'subject'}))
181 Your message did not contain a Subject field. They are recommended and
182 useful because the title of a $gBug is determined using this field.
183 Please remember to include a Subject field in your messages in future.
186 # RFC822 actually lists it as an `optional-field'.
188 $subject= '(no subject)';
190 $subject= $header{'subject'};
194 $subject =~ s/^Re:\s*//i; $_= $subject."\n";
195 if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) {
201 ($bfound, $data)= &lockreadbugmerge($tryref);
205 &htmllog("Reply","sent", $replyto,"Unknown problem report number <code>$tryref</code>.");
206 my $archivenote = '';
208 $archivenote = <<END;
209 This may be because that $gBug report has been resolved for more than $gRemoveAge
210 days, and the record of it has been archived and made read-only, or
211 because you mistyped the $gBug report number.
215 &sendmessage(<<END, '');
216 From: $gMaintainerEmail ($gProject $gBug Tracking System)
218 Subject: Unknown problem report $gBug#$tryref ($subject)
219 Message-ID: <handler.x.$nn.unknown\@$gEmailDomain>
220 In-Reply-To: $header{'message-id'}
221 References: $header{'message-id'} $data->{msgid}
223 X-$gProject-PR-Message: error
225 You sent a message to the $gBug tracking system which gave (in the
226 Subject line or encoded into the recipient at $gEmailDomain),
227 the number of a nonexistent $gBug report (#$tryref).
229 ${archivenote}Your message was dated $header{'date'} and was sent to
230 $baddress\@$gEmailDomain. It had
231 Message-ID $header{'message-id'}
232 and Subject $subject.
234 It has been filed (under junk) but otherwise ignored.
236 Please consult your records to find the correct $gBug report number, or
237 contact me, the system administrator, for assistance.
240 (administrator, $gProject $gBugs database)
242 (NB: If you are a system administrator and have no idea what I am
243 talking about this indicates a serious mail system misconfiguration
244 somewhere. Please contact me immediately.)
251 &filelock('lock/-1');
254 if ($codeletter eq 'D' || $codeletter eq 'F')
256 if ($replyto =~ m/$gBounceFroms/o ||
257 $header{'from'} =~ m/$gBounceFroms/o)
259 &quit("bounce detected ! Mwaap! Mwaap!");
261 $markedby= $header{'from'} eq $replyto ? $replyto :
262 "$header{'from'} (reply to $replyto)";
264 if ($codeletter eq 'F') {
265 (&appendlog,&finish) if length($data->{forwarded});
266 $receivedat= "forwarded\@$gEmailDomain";
267 $markaswhat= 'forwarded';
268 $set_forwarded= $header{'to'};
269 if ( length( $gListDomain ) > 0 && length( $gForwardList ) > 0 ) {
270 push @generalcc, "$gForwardList\@$gListDomain";
271 $generalcc= "$gForwardList\@$gListDomain";
276 if (length($data->{done}) and
277 not defined $pheader{'source-version'} and
278 not defined $pheader{'version'}) {
282 $receivedat= "done\@$gEmailDomain";
284 $set_done= $header{'from'};
285 if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) {
286 $generalcc= "$gDoneList\@$gListDomain";
287 push @generalcc, "$gDoneList\@$gListDomain";
292 if (defined $gStrongList and isstrongseverity($data->{severity})) {
293 $generalcc = join ', ', $generalcc, "$gStrongList\@$gListDomain";
294 push @generalcc,"$gStrongList\@$gListDomain";
297 &htmllog("Warning","sent",$replyto,"Message ignored.");
298 &sendmessage(<<END, '');
299 From: $gMaintainerEmail ($gProject $gBug Tracking System)
301 Subject: Message with no $gBug number ignored by $receivedat
303 Message-ID: <header.x.$nn.warnignore\@$gEmailDomain>
304 In-Reply-To: $header{'message-id'}
305 References: $header{'message-id'} $data->{msgid}
307 X-$gProject-PR-Message: error
309 You sent a message to the $gProject $gBug tracking system old-style
310 unified mark as $markaswhat address ($receivedat),
311 without a recognisable $gBug number in the Subject.
312 Your message has been filed under junk but otherwise ignored.
314 If you don't know what I'm talking about then probably either:
316 (a) you unwittingly sent a message to done\@$gEmailDomain
317 because you replied to all recipients of the message a developer used
318 to mark a $gBug as done and you modified the Subject. In this case,
319 please do not be alarmed. To avoid confusion do not do it again, but
320 there is no need to apologise or mail anyone asking for an explanation.
322 (b) you are a system administrator, reading this because the $gBug
323 tracking system is responding to a misdirected bounce message. In this
324 case there is a serious mail system misconfiguration somewhere - please
325 contact me immediately.
327 Your message was dated $header{'date'} and had
328 message-id $header{'message-id'}
329 and subject $subject.
331 If you need any assistance or explanation please contact me.
334 (administrator, $gProject $gBugs database)
343 my @noticecc = grep($_ ne $replyto,@maintaddrs);
344 $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs));
345 $noticeccval =~ s/\s+\n\s+/ /g;
346 $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
347 if (length($noticeccval)) { $noticecc= "Cc: $noticeccval\n"; }
349 @process= ($ref,split(/ /,$data->{mergedwith}));
352 for $ref (@process) {
353 if ($ref != $orgref) {
355 $data = &lockreadbug($ref)
356 || die "huh ? $ref from $orgref out of @process";
358 $data->{done}= $set_done if defined($set_done);
359 $data->{forwarded}= $set_forwarded if defined($set_forwarded);
360 if ($codeletter eq 'D') {
361 $data->{keywords} = join ' ', grep $_ ne 'pending',
362 split ' ', $data->{keywords};
363 if (defined $pheader{'source-version'}) {
364 addfixedversions($data, $pheader{source}, $pheader{'source-version'}, '');
365 } elsif (defined $pheader{version}) {
366 addfixedversions($data, $pheader{package}, $pheader{version}, 'binary');
370 # Add bug mailing list to $generalbcc as appropriate
371 # This array is used to specify bcc in the cases where we're using create_mime_message.
372 my @generalbcc = (@generalcc,@addsrcaddrs,"bugs=$ref\@$gListDomain");
373 my $generalbcc = join(', ', $generalcc, @addsrcaddrs,"bugs=$ref\@$gListDomain");
374 $generalbcc =~ s/\s+\n\s+/ /g;
375 $generalbcc =~ s/^\s+/ /; $generalbcc =~ s/\s+$//;
376 if (length $generalbcc) {$generalbcc = "Bcc: $generalbcc\n"};
378 writebug($ref, $data);
380 my $hash = get_hashname($ref);
381 open(O,"db-h/$hash/$ref.report") || &quit("read original report: $!");
382 $x= join('',<O>); close(O);
383 if ($codeletter eq 'F') {
384 &htmllog("Reply","sent",$replyto,"You have marked $gBug as forwarded.");
385 &sendmessage(create_mime_message(
386 [X-Loop => "$gMaintainerEmail",
387 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
389 Subject => "$gBug#$ref: marked as forwarded ($data->{subject})",
390 Message-ID => "<header.$ref.$nn.ackfwdd\@$gEmailDomain>",
391 In-Reply-To => $header{'message-id'},
392 References => "$header{'message-id'} $data->{msgid}",
393 Precedence => 'bulk',
394 "X-$gProject-PR-Message" => "forwarded $ref",
395 "X-$gProject-PR-Package" => $data->{package},
396 "X-$gProject-PR-Keywords" => $data->{keywords}
397 ],<<END ,[join("\n",@msg)]),'',[@generalbcc,@noticecc],1);
398 Your message dated $header{'date'}
399 with message-id $header{'message-id'}
400 has caused the $gProject $gBug report #$ref,
401 regarding $data->{subject}
402 to be marked as having been forwarded to the upstream software
403 author(s) $data->{forwarded}.
405 (NB: If you are a system administrator and have no idea what I am
406 talking about this indicates a serious mail system misconfiguration
407 somewhere. Please contact me immediately.)
410 (administrator, $gProject $gBugs database)
415 &htmllog("Reply","sent",$replyto,"You have taken responsibility.");
416 &sendmessage(create_mime_message(
417 [X-Loop => "$gMaintainerEmail",
418 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
420 Subject => "$gBug#$ref: marked as done ($data->{subject})",
421 Message-ID => "<handler.$ref.$nn.ackdone\@$gEmailDomain>",
422 In-Reply-To => $header{'message-id'},
423 References => "$header{'message-id'} $data->{msgid}",
424 Precedence => 'bulk',
425 "X-$gProject-PR-Message" => "closed $ref",
426 "X-$gProject-PR-Packag" => $data->{package},
427 "X-$gProject-PR-Keywords" => $data->{keywords}
428 ],<<END ,[$x,join("\n",@msg)]),'',[@generalbcc,@noticecc],1);
429 Your message dated $header{'date'}
430 with message-id $header{'message-id'}
431 and subject line $subject
432 has caused the attached $gBug report to be marked as done.
434 This means that you claim that the problem has been dealt with.
435 If this is not the case it is now your responsibility to reopen the
436 $gBug report if necessary, and/or fix the problem forthwith.
438 (NB: If you are a system administrator and have no idea what I am
439 talking about this indicates a serious mail system misconfiguration
440 somewhere. Please contact me immediately.)
443 (administrator, $gProject $gBugs database)
446 &htmllog("Notification","sent",$data->{originator},
447 "$gBug acknowledged by developer.");
448 &sendmessage(create_mime_message(
449 [X-Loop => "$gMaintainerEmail",
450 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
451 To => "$data->{originator}",
452 Subject => "$gBug#$ref acknowledged by developer ($header{'subject'})",
453 Message-ID => "<handler.$ref.$nn.notifdone\@$gEmailDomain>",
454 In-Reply-To => "$data->{msgid}",
455 References => "$header{'message-id'} $data->{msgid}",
456 X-$gProject-PR-Message => "they-closed $ref",
457 X-$gProject-PR-Package => "$data->{package}",
458 X-$gProject-PR-Keywords => "$data->{keywords}",
459 Reply-To => "$ref\@$gEmailDomain",
460 Content-Type => 'text/plain; charset="utf-8"',
461 ],<<END ,[join("\n",@msg)]),'',undef,1);
462 This is an automatic notification regarding your $gBug report
463 #$ref: $data->{subject},
464 which was filed against the $data->{package} package.
466 It has been closed by one of the developers, namely
469 Their explanation is attached below. If this explanation is
470 unsatisfactory and you have not received a better one in a separate
471 message then please contact the developer, by replying to this email.
474 (administrator, $gProject $gBugs database)
484 if ($codeletter eq 'U') {
485 &htmllog("Warning","sent",$replyto,"Message not forwarded.");
486 &sendmessage(<<END, '');
487 From: $gMaintainerEmail ($gProject $gBug Tracking System)
489 Subject: Message with no $gBug number cannot be sent to submitter !
491 Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
492 In-Reply-To: $header{'message-id'}
493 References: $header{'message-id'} $data->{msgid}
495 X-$gProject-PR-Message: error
497 You sent a message to the $gProject $gBug tracking system's $gBug
498 report submitter address $baddress\@$gEmailDomain, without a
499 recognisable $gBug number in the Subject. Your message has been filed
500 under junk but otherwise ignored.
502 If you don't know what I'm talking about then probably either:
504 (a) you unwittingly sent a message to $baddress\@$gEmailDomain
505 because you replied to all recipients of the message a developer sent
506 to a $gBug\'s submitter and you modified the Subject. In this case,
507 please do not be alarmed. To avoid confusion do not do it again, but
508 there is no need to apologise or mail anyone asking for an
511 (b) you are a system administrator, reading this because the $gBug
512 tracking system is responding to a misdirected bounce message. In this
513 case there is a serious mail system misconfiguration somewhere - please
514 contact me immediately.
516 Your message was dated $header{'date'} and had
517 message-id $header{'message-id'}
518 and subject $subject.
520 If you need any assistance or explanation please contact me.
523 (administrator, $gProject $gBugs database)
530 $data->{found_versions} = [];
531 $data->{fixed_versions} = [];
533 if (defined $pheader{source}) {
534 $data->{package} = $pheader{source};
535 } elsif (defined $pheader{package}) {
536 $data->{package} = $pheader{package};
538 &htmllog("Warning","sent",$replyto,"Message not forwarded.");
539 &sendmessage(create_mime_message(
540 [X-Loop => "$gMaintainerEmail",
541 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
543 Subject => "Message with no Package: tag cannot be processed! ($subject)",
544 Message-ID => "<handler.x.$nn.nonumnosub\@$gEmailDomain>",
545 In-Reply-To => $header{'message-id'},
546 References => "$header{'message-id'} $data->{msgid}",
547 Precedence => 'bulk',
548 "X-$gProject-PR-Message" => 'error'
549 ],<<END,[join("\n", @msg)]), '',undef,1);
551 Your message didn't have a Package: line at the start (in the
552 pseudo-header following the real mail header), or didn't have a
553 pseudo-header at all. Your message has been filed under junk but
556 This makes it much harder for us to categorise and deal with your
557 problem report. Please _resubmit_ your report to $baddress\@$gEmailDomain
558 and tell us which package the report is on. For help, check out
559 http://$gWebDomain/Reporting$gHTMLSuffix.
561 Your message was dated $header{'date'} and had
562 message-id $header{'message-id'}
563 and subject $subject.
564 The complete text of it is attached to this message.
566 If you need any assistance or explanation please contact me.
569 (administrator, $gProject $gBugs database)
576 $data->{keywords}= '';
577 if (defined($pheader{'keywords'})) {
578 $data->{keywords}= $pheader{'keywords'};
579 } elsif (defined($pheader{'tags'})) {
580 $data->{keywords}= $pheader{'tags'};
582 if (length($data->{keywords})) {
584 my %gkws = map { ($_, 1) } @gTags;
585 foreach my $kw (sort split(/[,\s]+/, lc($data->{keywords}))) {
586 push @kws, $kw if (defined $gkws{$kw});
588 $data->{keywords} = join(" ", @kws);
590 $data->{severity}= '';
591 if (defined($pheader{'severity'}) || defined($pheader{'priority'})) {
592 $data->{severity}= $pheader{'severity'};
593 $data->{severity}= $pheader{'priority'} unless ($data->{severity});
594 $data->{severity} =~ s/^\s*(.+)\s*$/$1/;
596 if (!grep($_ eq $data->{severity}, @severities, "$gDefaultSeverity")) {
599 Your message specified a Severity: in the pseudo-header, but
600 the severity value $data->{severity} was not recognised.
601 The default severity $gDefaultSeverity is being used instead.
602 The recognised values are: $gShowSeverities.
604 # if we use @gSeverityList array in the above line, perl -c gives:
605 # In string, @gSeverityList now must be written as \@gSeverityList at
606 # process line 452, near "$gDefaultSeverity is being used instead.
607 $data->{severity}= '';
610 if (defined($pheader{owner})) {
611 $data->{owner}= $pheader{owner};
613 if (defined($pheader{forwarded})) {
614 $data->{'forwarded-to'} = $pheader{forwarded};
616 &filelock("nextnumber.lock");
617 open(N,"nextnumber") || &quit("nextnumber: read: $!");
618 $v=<N>; $v =~ s/\n$// || &quit("nextnumber bad format");
619 $ref= $v+0; $v += 1; $newref=1;
620 &overwrite('nextnumber', "$v\n");
622 my $hash = get_hashname($ref);
623 &overwrite("db-h/$hash/$ref.log",'');
624 $data->{originator} = $replyto;
625 $data->{date} = $intdate;
626 $data->{subject} = $subject;
627 $data->{msgid} = $header{'message-id'};
628 writebug($ref, $data);
629 &overwrite("db-h/$hash/$ref.report",
630 join("\n",@msg)."\n");
635 print DEBUG "maintainers >@maintaddrs<\n";
637 $orgsender= defined($header{'sender'}) ? "Original-Sender: $header{'sender'}\n" : '';
638 $newsubject= $subject; $newsubject =~ s/^$gBug#$ref:*\s*//;
640 $xcchdr= $header{ 'x-debbugs-cc' };
641 if ($xcchdr =~ m/\S/) {
642 push(@resentccs,$xcchdr);
643 $resentccexplain.= <<END;
645 As you requested using X-Debbugs-CC, your message was also forwarded to
647 (after having been given a $gBug report number, if it did not have one).
651 if (@maintaddrs && ($codeletter eq 'B' || $codeletter eq 'M')) {
652 push(@resentccs,@maintaddrs);
653 $resentccexplain.= <<END." ".join("\n ",@maintaddrs)."\n";
655 Your message has been sent to the package maintainer(s):
659 @bccs = @addsrcaddrs;
660 if (defined $gStrongList and isstrongseverity($data->{severity})) {
661 push @bccs, "$gStrongList\@$gListDomain";
664 # Send mail to the per bug list subscription too
665 push @bccs, "bugs=$ref\@$gListDomain";
667 if (defined $pheader{source}) {
668 # Prefix source versions with the name of the source package. They
669 # appear that way in version trees so that we can deal with binary
670 # packages moving from one source package to another.
671 if (defined $pheader{'source-version'}) {
672 addfoundversions($data, $pheader{source}, $pheader{'source-version'}, '');
673 } elsif (defined $pheader{version}) {
674 addfoundversions($data, $pheader{source}, $pheader{version}, '');
676 writebug($ref, $data);
677 } elsif (defined $pheader{package}) {
678 # TODO: could handle Source-Version: by looking up the source package?
679 addfoundversions($data, $pheader{package}, $pheader{version}, 'binary');
680 writebug($ref, $data);
683 $veryquiet= $codeletter eq 'Q';
684 if ($codeletter eq 'M' && !@maintaddrs) {
688 You requested that the message be sent to the package maintainer(s)
689 but either the $gBug report is not associated with any package (probably
690 because of a missing Package pseudo-header field in the original $gBug
691 report), or the package(s) specified do not have any maintainer(s).
693 Your message has *not* been sent to any package maintainers; it has
694 merely been filed in the $gBug tracking system. If you require assistance
695 please contact $gMaintainerEmail quoting the $gBug number $ref.
699 $resentccval.= join(', ',@resentccs);
700 $resentccval =~ s/\s+\n\s+/ /g; $resentccval =~ s/^\s+/ /; $resentccval =~ s/\s+$//;
701 if (length($resentccval)) {
702 $resentcc= "Resent-CC: $resentccval\n";
705 if ($codeletter eq 'U') {
706 &htmllog("Message", "sent on", $data->{originator}, "$gBug#$ref.");
707 &sendmessage(<<END,[$data->{originator},@resentccs],[@bccs]);
708 Subject: $gBug#$ref: $newsubject
709 Reply-To: $replyto, $ref-quiet\@$gEmailDomain
710 ${orgsender}Resent-To: $data->{originator}
711 ${resentcc}Resent-Date: $tdate
712 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
713 Resent-Sender: $gMaintainerEmail
714 X-$gProject-PR-Message: report $ref
715 X-$gProject-PR-Package: $data->{package}
716 X-$gProject-PR-Keywords: $data->{keywords}
719 } elsif ($codeletter eq 'B') {
720 &htmllog($newref ? "Report" : "Information", "forwarded",
721 join(', ',"$gSubmitList\@$gListDomain",@resentccs),
722 "<code>$gBug#$ref</code>".
723 (length($data->{package})? "; Package <code>".&sani($data->{package})."</code>" : '').
725 &sendmessage(<<END,["$gSubmitList\@$gListDomain",@resentccs],[@bccs]);
726 Subject: $gBug#$ref: $newsubject
727 Reply-To: $replyto, $ref\@$gEmailDomain
728 Resent-From: $header{'from'}
729 ${orgsender}Resent-To: $gSubmitList\@$gListDomain
730 ${resentcc}Resent-Date: $tdate
731 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
732 Resent-Sender: $gMaintainerEmail
733 X-$gProject-PR-Message: report $ref
734 X-$gProject-PR-Package: $data->{package}
735 X-$gProject-PR-Keywords: $data->{keywords}
738 } elsif (@resentccs or @bccs) {
739 # D and F done far earlier; B just done - so this must be M or Q
740 # We preserve whichever it was in the Reply-To (possibly adding
743 &htmllog($newref ? "Report" : "Information", "forwarded",
745 "<code>$gBug#$ref</code>".
746 (length($data->{package}) ? "; Package <code>".&sani($data->{package})."</code>" : '').
749 &htmllog($newref ? "Report" : "Information", "stored",
751 "<code>$gBug#$ref</code>".
752 (length($data->{package}) ? "; Package <code>".&sani($data->{package})."</code>" : '').
755 &sendmessage(<<END,[@resentccs],[@bccs]);
756 Subject: $gBug#$ref: $newsubject
757 Reply-To: $replyto, $ref-$baddressroot\@$gEmailDomain
758 Resent-From: $header{'from'}
759 ${orgsender}Resent-To: $resentccval
761 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
762 Resent-Sender: $gMaintainerEmail
763 X-$gProject-PR-Message: report $ref
764 X-$gProject-PR-Package: $data->{package}
765 X-$gProject-PR-Keywords: $data->{keywords}
770 $htmlbreak= length($brokenness) ? "<p>\n".&sani($brokenness)."\n<p>\n" : '';
771 $htmlbreak =~ s/\n\n/\n<P>\n\n/g;
772 if (length($resentccval)) {
773 $htmlbreak = " Copy sent to <code>".&sani($resentccval)."</code>.".
776 unless (exists $header{'x-debbugs-no-ack'}) {
778 &htmllog("Acknowledgement","sent",$replyto,
780 "New $gBug report received and filed, but not forwarded." :
781 "New $gBug report received and forwarded."). $htmlbreak);
782 &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
783 From: $gMaintainerEmail ($gProject $gBug Tracking System)
785 Subject: $gBug#$ref: Acknowledgement of QUIET report
787 Message-ID: <handler.$ref.$nn.ackquiet\@$gEmailDomain>
788 In-Reply-To: $header{'message-id'}
789 References: $header{'message-id'}
791 X-$gProject-PR-Message: ack-quiet $ref
792 X-$gProject-PR-Package: $data->{package}
793 X-$gProject-PR-Keywords: $data->{keywords}
794 Reply-To: $ref-quiet\@$gEmailDomain
796 Thank you for the problem report you have sent regarding $gProject.
797 This is an automatically generated reply, to let you know your message
798 has been received. It has not been forwarded to the package maintainers
799 or other interested parties; you should ensure that the developers are
800 aware of the problem you have entered into the system - preferably
801 quoting the $gBug reference number, #$ref.
803 If you wish to submit further information on your problem, please send it
804 to $ref-$baddressroot\@$gEmailDomain (and *not*
805 to $baddress\@$gEmailDomain).
807 Please do not reply to the address at the top of this message,
808 unless you wish to report a problem with the $gBug-tracking system.
811 (administrator, $gProject $gBugs database)
813 From: $gMaintainerEmail ($gProject $gBug Tracking System)
815 Subject: $gBug#$ref: Acknowledgement of maintainer-only report
817 Message-ID: <handler.$ref.$nn.ackmaint\@$gEmailDomain>
818 In-Reply-To: $header{'message-id'}
819 References: $header{'message-id'}
821 X-$gProject-PR-Message: ack-maintonly $ref
822 X-$gProject-PR-Package: $data->{package}
823 X-$gProject-PR-Keywords: $data->{keywords}
824 Reply-To: $ref-maintonly\@$gEmailDomain
826 Thank you for the problem report you have sent regarding $gProject.
827 This is an automatically generated reply, to let you know your message has
828 been received. It is being forwarded to the package maintainers (but not
829 other interested parties, as you requested) for their attention; they will
832 If you wish to submit further information on your problem, please send
833 it to $ref-$baddressroot\@$gEmailDomain (and *not*
834 to $baddress\@$gEmailDomain).
836 Please do not reply to the address at the top of this message,
837 unless you wish to report a problem with the $gBug-tracking system.
840 (administrator, $gProject $gBugs database)
842 From: $gMaintainerEmail ($gProject $gBug Tracking System)
844 Subject: $gBug#$ref: Acknowledgement ($subject)
845 Message-ID: <handler.$ref.$nn.ack\@$gEmailDomain>
846 In-Reply-To: $header{'message-id'}
847 References: $header{'message-id'}
849 X-$gProject-PR-Message: ack $ref
850 X-$gProject-PR-Package: $data->{package}
851 X-$gProject-PR-Keywords: $data->{keywords}
852 Reply-To: $ref\@$gEmailDomain
854 Thank you for the problem report you have sent regarding $gProject.
855 This is an automatically generated reply, to let you know your message has
856 been received. It is being forwarded to the package maintainers and other
857 interested parties for their attention; they will reply in due course.
859 If you wish to submit further information on your problem, please send
860 it to $ref\@$gEmailDomain (and *not* to
861 $baddress\@$gEmailDomain).
863 Please do not reply to the address at the top of this message,
864 unless you wish to report a problem with the $gBug-tracking system.
867 (administrator, $gProject $gBugs database)
869 } elsif ($codeletter ne 'U' and
870 $header{'precedence'} !~ /\b(?:bulk|junk|list)\b/) {
871 &htmllog("Acknowledgement","sent",$replyto,
872 ($veryquiet ? "Extra info received and filed, but not forwarded." :
873 $codeletter eq 'M' ? "Extra info received and forwarded to maintainer." :
874 "Extra info received and forwarded to list."). $htmlbreak);
875 &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
876 From: $gMaintainerEmail ($gProject $gBug Tracking System)
878 Subject: $gBug#$ref: Info received and FILED only
880 Message-ID: <handler.$ref.$nn.ackinfoquiet\@$gEmailDomain>
881 In-Reply-To: $header{'message-id'}
882 References: $header{'message-id'}
884 X-$gProject-PR-Message: ack-info-quiet $ref
885 X-$gProject-PR-Package: $data->{package}
886 X-$gProject-PR-Keywords: $data->{keywords}
887 Reply-To: $ref-quiet\@$gEmailDomain
889 Thank you for the additional information you have supplied regarding
890 this problem report. It has NOT been forwarded to the package
891 maintainers, but will accompany the original report in the $gBug
892 tracking system. Please ensure that you yourself have sent a copy of
893 the additional information to any relevant developers or mailing lists.
895 If you wish to continue to submit further information on your problem,
896 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
898 Please do not reply to the address at the top of this message,
899 unless you wish to report a problem with the $gBug-tracking system.
902 (administrator, $gProject $gBugs database)
904 From: $gMaintainerEmail ($gProject $gBug Tracking System)
906 Subject: $gBug#$ref: Info received for maintainer only
908 Message-ID: <handler.$ref.$nn.ackinfomaint\@$gEmailDomain>
909 In-Reply-To: $header{'message-id'}
910 References: $header{'message-id'}
912 X-$gProject-PR-Message: ack-info-maintonly $ref
913 X-$gProject-PR-Package: $data->{package}
914 X-$gProject-PR-Keywords: $data->{keywords}
915 Reply-To: $ref-maintonly\@$gEmailDomain
917 Thank you for the additional information you have supplied regarding
918 this problem report. It has been forwarded to the package maintainer(s)
919 (but not to other interested parties) to accompany the original report.
921 If you wish to continue to submit further information on your problem,
922 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
924 Please do not reply to the address at the top of this message,
925 unless you wish to report a problem with the $gBug-tracking system.
928 (administrator, $gProject $gBugs database)
930 From: $gMaintainerEmail ($gProject $gBug Tracking System)
932 Subject: $gBug#$ref: Info received (was $subject)
933 Message-ID: <handler.$ref.$nn.ackinfo\@$gEmailDomain>
934 In-Reply-To: $header{'message-id'}
935 References: $header{'message-id'}
937 X-$gProject-PR-Message: ack-info $ref
938 X-$gProject-PR-Package: $data->{package}
939 X-$gProject-PR-Keywords: $data->{keywords}
941 Thank you for the additional information you have supplied regarding
942 this problem report. It has been forwarded to the package maintainer(s)
943 and to other interested parties to accompany the original report.
945 If you wish to continue to submit further information on your problem,
946 please send it to $ref\@$gEmailDomain, as before.
948 Please do not reply to the address at the top of this message,
949 unless you wish to report a problem with the $gBug-tracking system.
952 (administrator, $gProject $gBugs database)
954 # Reply-To: in previous ack disabled by doogie due to mail loops.
955 # Are these still a concern?
956 # Reply-To: $ref\@$gEmailDomain
965 open(NEW,">$f.new") || &quit("$f.new: create: $!");
966 print(NEW "$v") || &quit("$f.new: write: $!");
967 close(NEW) || &quit("$f.new: close: $!");
968 rename("$f.new","$f") || &quit("rename $f.new to $f: $!");
972 my $hash = get_hashname($ref);
973 if (!open(AP,">>db-h/$hash/$ref.log")) {
974 print DEBUG "failed open log<\n";
975 print DEBUG "failed open log err $!<\n";
976 &quit("opening db-h/$hash/$ref.log (li): $!");
978 print(AP "\7\n",@{escapelog(@log)},"\n\3\n") || &quit("writing db-h/$hash/$ref.log (li): $!");
979 close(AP) || &quit("closing db-h/$hash/$ref.log (li): $!");
983 utime(time,time,"db");
985 while ($u= $cleanups[$#cleanups]) { &$u; }
986 unlink("incoming/P$nn") || &quit("unlinking incoming/P$nn: $!");
990 &quit("wot no exit");
992 sub chldhandle { $chldexit = 'yes'; }
995 local ($whatobj,$whatverb,$where,$desc) = @_;
996 my $hash = get_hashname($ref);
997 open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lh): $!");
1000 "<strong>$whatobj $whatverb</strong>".
1001 ($where eq '' ? "" : " to <code>".&sani($where)."</code>").
1003 "\n\3\n") || &quit("writing db-h/$hash/$ref.log (lh): $!");
1004 close(AP) || &quit("closing db-h/$hash/$ref.log (lh): $!");
1011 while ($msg =~ s/(.*\n)//) {
1018 # strip continuation lines too
1033 send_message($the_message,\@recipients,\@bcc,$do_not_encode)
1035 The first argument is the scalar message, the second argument is the
1036 arrayref of recipients, the third is the arrayref of Bcc:'ed
1039 The final argument turns off header encoding and the addition of the
1040 X-Loop header if true, defaults to false.
1046 my ($msg,$recips,$bcc,$no_encode) = @_;
1047 if (not defined $recips or (!ref($recips) && $recips eq '')
1051 # This is suboptimal. The right solution is to send headers
1052 # separately from the rest of the message and encode them rather
1054 $msg = "X-Loop: $gMaintainerEmail\n" . $msg unless $no_encode;
1055 # The original message received is written out in appendlog, so
1056 # before writing out the other messages we've sent out, we need to
1057 # RFC1522 encode the header.
1058 $msg = encode_headers($msg) unless $no_encode;
1060 my $hash = get_hashname($ref);
1061 #save email to the log
1062 open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lo): $!");
1063 print(AP "\2\n",join("\4",@$recips),"\n\5\n",
1064 @{escapelog(stripbccs($msg))},"\n\3\n") ||
1065 &quit("writing db-h/$hash/$ref.log (lo): $!");
1066 close(AP) || &quit("closing db-h/$hash/$ref.log (lo): $!");
1069 shift @$recips if $recips->[0] eq '-t';
1070 push @$recips, @$bcc;
1073 send_mail_message(message => $msg,
1074 # Because we encode the headers above, we do not want to encode them here
1075 encode_headers => 0,
1076 recipients => $recips);
1079 sub checkmaintainers {
1080 return if $maintainerschecked++;
1081 return if !length($data->{package});
1082 open(MAINT,"$gMaintainerFile") || die &quit("maintainers open: $!");
1086 m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers bogus \`$_'");
1087 $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1088 $maintainerof{$1}= $2;
1091 open(MAINT,"$gMaintainerFileOverride") || die &quit("maintainers.override open: $!");
1095 m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers.override bogus \`$_'");
1096 $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1097 $maintainerof{$1}= $2;
1100 open(SOURCES,"$gPackageSource") || &quit("pkgsrc open: $!");
1102 next unless m/^(\S+)\s+\S+\s+(\S.*\S)\s*$/;
1108 $anymaintfound=0; $anymaintnotfound=0;
1109 for $p (split(m/[ \t?,():]+/,$data->{package})) {
1111 $p =~ /([a-z0-9.+-]+)/;
1113 next unless defined $p;
1114 if (defined $gSubscriptionDomain) {
1115 if (defined($pkgsrc{$p})) {
1116 push @addsrcaddrs, "$pkgsrc{$p}\@$gSubscriptionDomain";
1118 push @addsrcaddrs, "$p\@$gSubscriptionDomain";
1121 if (defined($maintainerof{$p})) {
1122 print DEBUG "maintainer add >$p|$maintainerof{$p}<\n";
1123 $addmaint= $maintainerof{$p};
1124 push(@maintaddrs,$addmaint) unless
1125 $addmaint eq $replyto || grep($_ eq $addmaint, @maintaddrs);
1128 print DEBUG "maintainer none >$p<\n";
1129 push(@maintaddrs,$gUnknownMaintainerEmail) unless $anymaintnotfound;
1130 $anymaintnotfound++;
1135 if (length $data->{owner}) {
1136 print DEBUG "owner add >$data->{package}|$data->{owner}<\n";
1137 $addmaint = $data->{owner};
1138 push(@maintaddrs, $addmaint) unless
1139 $addmaint eq $replyto or grep($_ eq $addmaint, @maintaddrs);
1143 =head2 bug_list_forward
1145 bug_list_forward($spool_filename) if $codeletter eq 'L';
1148 Given the spool file, will forward a bug to the per bug mailing list
1149 subscription system.
1153 sub bug_list_forward{
1155 # Read the bug information and package information for passing to
1157 my ($bug_number) = $bug_fn =~ /^L(\d+)\./;
1158 my ($bfound, $data)= lockreadbugmerge($bug_number);
1159 my $bug_fh = new IO::File "incoming/P$bug_fn" or die "Unable to open incoming/P$bug_fn $!";
1162 my $bug_message = <$bug_fh>;
1163 my ($bug_address) = $bug_message =~ /^Received: \(at ([^\)]+)\) by/;
1164 my ($envelope_from) = $bug_message =~ s/\nFrom\s+([^\s]+)[^\n]+\n/\n/;
1165 if (not defined $envelope_from) {
1166 # Try to use the From: header or something to set it
1167 ($envelope_from) = $bug_message =~ /\nFrom:\s+(.+?)\n/;
1168 # Kludgy, and should really be using a full scale header
1169 # parser to do this.
1170 $envelope_from =~ s/^.+?<([^>]+)>.+$/$1/;
1172 my ($header,$body) = split /\n\n/, $bug_message, 2;
1173 # Add X-$gProject-PR-Message: list bug_number, package name, and bug title headers
1174 $header .= qq(\nX-$gProject-PR-Message: list $bug_number\n).
1175 qq(X-$gProject-PR-Package: $data->{package}\n).
1176 qq(X-$gProject-PR-Title: $data->{subject})
1178 print STDERR "Tried to loop me with $envelope_from\n"
1179 and exit 1 if $envelope_from =~ /\Q$gListDomain\E|\Q$gEmailDomain\E/;
1180 print DEBUG $envelope_from,qq(\n);
1181 # If we don't have a bug address, something has gone horribly wrong.
1182 print STDERR "Doesn't match: $bug_address\n" and exit 1 unless defined $bug_address;
1183 $bug_address =~ s/\@.+//;
1184 print DEBUG "Sending message to bugs=$bug_address\@$gListDomain\n";
1185 print DEBUG $header.qq(\n\n).$body;
1186 send_mail_message(message => $header.qq(\n\n).$body,
1187 recipients => ["bugs=$bug_address\@$gListDomain"],
1188 envelope_from => $envelope_from,
1189 encode_headers => 0,
1191 unlink("incoming/P$bug_fn") || &quit("unlinking incoming/P$bug_fn: $!");