2 # $Id: process.in,v 1.109 2006/02/09 22:02:04 don Exp $
7 use POSIX qw(strftime);
10 use Debbugs::MIME qw(decode_rfc1522 create_mime_message);
11 use Debbugs::Mail qw(send_mail_message encode_headers);
12 use Debbugs::Packages qw(getpkgsrc);
13 use Debbugs::User qw(read_usertags write_usertags);
15 use Debbugs::CGI qw(html_escape);
17 use Debbugs::Log qw(:misc);
19 # TODO DLA; needs config reworking and errorlib reworking
23 use Debbugs::Status qw(:versions);
24 use Debbugs::Config qw(:globals);
25 my $lib_path = $gLibPath;
27 require "$lib_path/errorlib";
28 $ENV{'PATH'} = $lib_path.':'.$ENV{'PATH'};
30 chdir( "$gSpoolDir" ) || die "chdir spool: $!\n";
32 #open(DEBUG,"> /tmp/debbugs.debug");
34 open DEBUG, ">/dev/null";
36 my $intdate = time or quit("failed to get time: $!");
39 m/^([BMQFDUL])(\d*)\.\d+$/ or quit("bad argument: $_");
41 my $tryref= length($2) ? $2 : -1;
44 if (!rename("incoming/G$nn","incoming/P$nn"))
46 $_=$!.''; m/no such file or directory/i && exit 0;
47 &quit("renaming to lock: $!");
50 my $baddress= 'submit' if $codeletter eq 'B';
51 $baddress= 'maintonly' if $codeletter eq 'M';
52 $baddress= 'quiet' if $codeletter eq 'Q';
53 $baddress= 'forwarded' if $codeletter eq 'F';
54 $baddress= 'done' if $codeletter eq 'D';
55 $baddress= 'submitter' if $codeletter eq 'U';
56 bug_list_forward($nn) if $codeletter eq 'L';
57 $baddress || &quit("bad codeletter $codeletter");
58 my $baddressroot= $baddress;
59 $baddress= "$tryref-$baddress" if $tryref>=0;
61 open(M,"incoming/P$nn");
68 print DEBUG "###\n",join("##\n",@msg),"\n###\n";
70 my $tdate = strftime "%a, %d %h %Y %T +0000", gmtime;
72 Received: via spool by $baddress\@$gEmailDomain id=$nn
73 (code $codeletter ref $tryref); $tdate
76 # header and decoded body respectively
77 my (@headerlines, @bodylines);
79 my $parser = new MIME::Parser;
80 mkdir "$gSpoolDir/mime.tmp", 0777;
81 $parser->output_under("$gSpoolDir/mime.tmp");
82 my $entity = eval { $parser->parse_data(join('',@log)) };
85 if ($entity and $entity->head->tags) {
86 @headerlines = @{$entity->head->header};
89 my $entity_body = getmailbody($entity);
90 @bodylines = $entity_body ? $entity_body->as_lines() : ();
93 # set $i to beginning of encoded body data, so we can dump it out
96 ++$i while $msg[$i] =~ /./;
98 # Legacy pre-MIME code, kept around in case MIME::Parser fails.
99 for ($i = 0; $i <= $#msg; $i++) {
101 last unless length($_);
102 while ($msg[$i+1] =~ m/^\s/) {
106 push @headerlines, $_;
109 @bodylines = @msg[$i..$#msg];
114 for my $hdr (@headerlines) {
115 $hdr = decode_rfc1522($hdr);
118 &finish if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
119 my $ins = !m/^subject:/i && !m/^reply-to:/i && !m/^return-path:/i
120 && !m/^From / && !m/^X-Debbugs-/i;
121 $fwd .= $hdr."\n" if $ins;
122 # print DEBUG ">$_<\n";
123 if (s/^(\S+):\s*//) {
125 print DEBUG ">$v=$_<\n";
128 print DEBUG "!>$_<\n";
133 shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
135 # Strip off RFC2440-style PGP clearsigning.
136 if (@bodylines and $bodylines[0] =~ /^-----BEGIN PGP SIGNED/) {
137 shift @bodylines while @bodylines and length $bodylines[0];
138 shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
139 for my $findsig (0 .. $#bodylines) {
140 if ($bodylines[$findsig] =~ /^-----BEGIN PGP SIGNATURE/) {
141 $#bodylines = $findsig - 1;
145 map { s/^- // } @bodylines;
148 # extract pseudo-headers
149 for my $phline (@bodylines)
151 last if $phline !~ m/^([\w-]+):\s*(\S.*)/;
152 my ($fn, $fv) = ($1, $2);
154 print DEBUG ">$fn|$fv|\n";
156 # Don't lc owner or forwarded
157 $fv = lc $fv unless $fh =~ /^(?:owner|forwarded|usertags|version|source-version)$/;
159 print DEBUG ">$fn~$fv<\n";
162 # Allow pseudo headers to set x-debbugs- stuff [#179340]
163 for my $key (grep /X-Debbugs-.*/i, keys %pheader) {
164 $header{$key} = $pheader{$key} if not exists $header{$key};
167 $fwd .= join("\n",@msg[$i..$#msg]);
169 print DEBUG "***\n$fwd\n***\n";
171 if (defined $header{'resent-from'} && !defined $header{'from'}) {
172 $header{'from'} = $header{'resent-from'};
174 defined($header{'from'}) || &quit("no From header");
176 my $replyto = $header{'reply-to'};
177 $replyto = '' unless defined $replyto;
180 unless (length $replyto) {
181 $replyto = $header{'from'};
184 my $subject = '(no subject)';
185 if (!defined($header{'subject'}))
189 Your message did not contain a Subject field. They are recommended and
190 useful because the title of a $gBug is determined using this field.
191 Please remember to include a Subject field in your messages in future.
195 $subject= $header{'subject'};
199 $subject =~ s/^Re:\s*//i; $_= $subject."\n";
200 if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) {
206 ($bfound, $data)= &lockreadbugmerge($tryref);
210 &htmllog("Reply","sent", $replyto,"Unknown problem report number <code>$tryref</code>.");
211 my $archivenote = '';
213 $archivenote = <<END;
214 This may be because that $gBug report has been resolved for more than $gRemoveAge
215 days, and the record of it has been archived and made read-only, or
216 because you mistyped the $gBug report number.
220 &sendmessage(<<END, '');
221 From: $gMaintainerEmail ($gProject $gBug Tracking System)
223 Subject: Unknown problem report $gBug#$tryref ($subject)
224 Message-ID: <handler.x.$nn.unknown\@$gEmailDomain>
225 In-Reply-To: $header{'message-id'}
226 References: $header{'message-id'} $data->{msgid}
228 X-$gProject-PR-Message: error
230 You sent a message to the $gBug tracking system which gave (in the
231 Subject line or encoded into the recipient at $gEmailDomain),
232 the number of a nonexistent $gBug report (#$tryref).
234 ${archivenote}Your message was dated $header{'date'} and was sent to
235 $baddress\@$gEmailDomain. It had
236 Message-ID $header{'message-id'}
237 and Subject $subject.
239 It has been filed (under junk) but otherwise ignored.
241 Please consult your records to find the correct $gBug report number, or
242 contact me, the system administrator, for assistance.
245 (administrator, $gProject $gBugs database)
247 (NB: If you are a system administrator and have no idea what I am
248 talking about this indicates a serious mail system misconfiguration
249 somewhere. Please contact me immediately.)
256 &filelock('lock/-1');
259 # Attempt to determine which source package this is
260 my $source_pr_header = '';
261 my $source_package = '';
262 if (defined $pheader{source}) {
263 $source_package = $pheader{source};
265 elsif (defined $data->{package} or defined $pheader{package}) {
266 my $pkg_src = getpkgsrc();
267 $source_package = $pkg_src->{defined $data->{package}?$data->{package}:$pheader{package}};
269 $source_pr_header = "X-$gProject-PR-Source: $source_package\n"
270 if defined $source_package and length $source_package;
272 # Done and Forwarded Bugs
273 if ($codeletter eq 'D' || $codeletter eq 'F')
275 if ($replyto =~ m/$gBounceFroms/o ||
276 $header{'from'} =~ m/$gBounceFroms/o)
278 &quit("bounce detected ! Mwaap! Mwaap!");
280 $markedby= $header{'from'} eq $replyto ? $replyto :
281 "$header{'from'} (reply to $replyto)";
283 if ($codeletter eq 'F') { # Forwarded
284 (&appendlog,&finish) if length($data->{forwarded});
285 $receivedat= "forwarded\@$gEmailDomain";
286 $markaswhat= 'forwarded';
287 $set_forwarded= $header{'to'};
288 # Dissallow forwarded being set to this bug tracking system
289 if (defined $set_forwarded and $set_forwarded =~ /\Q$gEmailDomain\E/) {
290 undef $set_forwarded;
292 if ( length( $gListDomain ) > 0 && length( $gForwardList ) > 0 ) {
293 push @generalcc, "$gForwardList\@$gListDomain";
294 $generalcc= "$gForwardList\@$gListDomain";
299 if (length($data->{done}) and
300 not defined $pheader{'source-version'} and
301 not defined $pheader{'version'}) {
305 $receivedat= "done\@$gEmailDomain";
307 $set_done= $header{'from'};
308 if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) {
309 $generalcc= "$gDoneList\@$gListDomain";
310 push @generalcc, "$gDoneList\@$gListDomain";
315 if (defined $gStrongList and isstrongseverity($data->{severity})) {
316 $generalcc = join ', ', $generalcc, "$gStrongList\@$gListDomain";
317 push @generalcc,"$gStrongList\@$gListDomain";
320 &htmllog("Warning","sent",$replyto,"Message ignored.");
321 &sendmessage(<<END, '');
322 From: $gMaintainerEmail ($gProject $gBug Tracking System)
324 Subject: Message with no $gBug number ignored by $receivedat
326 Message-ID: <header.x.$nn.warnignore\@$gEmailDomain>
327 In-Reply-To: $header{'message-id'}
328 References: $header{'message-id'} $data->{msgid}
330 X-$gProject-PR-Message: error
332 You sent a message to the $gProject $gBug tracking system old-style
333 unified mark as $markaswhat address ($receivedat),
334 without a recognisable $gBug number in the Subject.
335 Your message has been filed under junk but otherwise ignored.
337 If you don't know what I'm talking about then probably either:
339 (a) you unwittingly sent a message to done\@$gEmailDomain
340 because you replied to all recipients of the message a developer used
341 to mark a $gBug as done and you modified the Subject. In this case,
342 please do not be alarmed. To avoid confusion do not do it again, but
343 there is no need to apologise or mail anyone asking for an explanation.
345 (b) you are a system administrator, reading this because the $gBug
346 tracking system is responding to a misdirected bounce message. In this
347 case there is a serious mail system misconfiguration somewhere - please
348 contact me immediately.
350 Your message was dated $header{'date'} and had
351 message-id $header{'message-id'}
352 and subject $subject.
354 If you need any assistance or explanation please contact me.
357 (administrator, $gProject $gBugs database)
366 my @noticecc = grep($_ ne $replyto,@maintaddrs);
367 $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs));
368 $noticeccval =~ s/\s+\n\s+/ /g;
369 $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
371 @process= ($ref,split(/ /,$data->{mergedwith}));
374 for $ref (@process) {
375 if ($ref != $orgref) {
377 $data = &lockreadbug($ref)
378 || die "huh ? $ref from $orgref out of @process";
380 $data->{done}= $set_done if defined($set_done);
381 $data->{forwarded}= $set_forwarded if defined($set_forwarded);
382 if ($codeletter eq 'D') {
383 $data->{keywords} = join ' ', grep $_ ne 'pending',
384 split ' ', $data->{keywords};
385 if (defined $pheader{'source-version'}) {
386 addfixedversions($data, $pheader{source}, $pheader{'source-version'}, '');
387 } elsif (defined $pheader{version}) {
388 addfixedversions($data, $pheader{package}, $pheader{version}, 'binary');
392 # Add bug mailing list to $generalbcc as appropriate
393 # This array is used to specify bcc in the cases where we're using create_mime_message.
394 my @generalbcc = (@generalcc,@addsrcaddrs,"bugs=$ref\@$gListDomain");
395 my $generalbcc = join(', ', $generalcc, @addsrcaddrs,"bugs=$ref\@$gListDomain");
396 $generalbcc =~ s/\s+\n\s+/ /g;
397 $generalbcc =~ s/^\s+/ /; $generalbcc =~ s/\s+$//;
398 if (length $generalbcc) {$generalbcc = "Bcc: $generalbcc\n"};
400 writebug($ref, $data);
402 my $hash = get_hashname($ref);
403 open(O,"db-h/$hash/$ref.report") || &quit("read original report: $!");
404 $x= join('',<O>); close(O);
405 if ($codeletter eq 'F') {
406 &htmllog("Reply","sent",$replyto,"You have marked $gBug as forwarded.");
407 &sendmessage(create_mime_message(
408 ["X-Loop" => "$gMaintainerEmail",
409 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
411 Subject => "$gBug#$ref: marked as forwarded ($data->{subject})",
412 "Message-ID" => "<header.$ref.$nn.ackfwdd\@$gEmailDomain>",
413 "In-Reply-To" => $header{'message-id'},
414 References => "$header{'message-id'} $data->{msgid}",
415 Precedence => 'bulk',
416 "X-$gProject-PR-Message" => "forwarded $ref",
417 "X-$gProject-PR-Package" => $data->{package},
418 "X-$gProject-PR-Keywords" => $data->{keywords},
419 # Only have a X-$gProject-PR-Source when we know the source package
420 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
421 ],<<END ,[join("\n",@msg)]),'',[$replyto,@generalbcc,@noticecc],1);
422 Your message dated $header{'date'}
423 with message-id $header{'message-id'}
424 has caused the $gProject $gBug report #$ref,
425 regarding $data->{subject}
426 to be marked as having been forwarded to the upstream software
427 author(s) $data->{forwarded}.
429 (NB: If you are a system administrator and have no idea what I am
430 talking about this indicates a serious mail system misconfiguration
431 somewhere. Please contact me immediately.)
434 (administrator, $gProject $gBugs database)
439 &htmllog("Reply","sent",$replyto,"You have taken responsibility.");
440 &sendmessage(create_mime_message(
441 ["X-Loop" => "$gMaintainerEmail",
442 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
444 Subject => "$gBug#$ref: marked as done ($data->{subject})",
445 "Message-ID" => "<handler.$ref.$nn.ackdone\@$gEmailDomain>",
446 "In-Reply-To" => $header{'message-id'},
447 References => "$header{'message-id'} $data->{msgid}",
448 Precedence => 'bulk',
449 "X-$gProject-PR-Message" => "closed $ref",
450 "X-$gProject-PR-Package" => $data->{package},
451 "X-$gProject-PR-Keywords" => $data->{keywords},
452 # Only have a X-$gProject-PR-Source when we know the source package
453 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
454 ],<<END ,[$x,join("\n",@msg)]),'',[$replyto,@generalbcc,@noticecc],1);
455 Your message dated $header{'date'}
456 with message-id $header{'message-id'}
457 and subject line $subject
458 has caused the attached $gBug report to be marked as done.
460 This means that you claim that the problem has been dealt with.
461 If this is not the case it is now your responsibility to reopen the
462 $gBug report if necessary, and/or fix the problem forthwith.
464 (NB: If you are a system administrator and have no idea what I am
465 talking about this indicates a serious mail system misconfiguration
466 somewhere. Please contact me immediately.)
469 (administrator, $gProject $gBugs database)
472 &htmllog("Notification","sent",$data->{originator},
473 "$gBug acknowledged by developer.");
474 &sendmessage(create_mime_message(
475 ["X-Loop" => "$gMaintainerEmail",
476 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
477 To => "$data->{originator}",
478 Subject => "$gBug#$ref closed by $markedby ($header{'subject'})",
479 "Message-ID" => "<handler.$ref.$nn.notifdone\@$gEmailDomain>",
480 "In-Reply-To" => "$data->{msgid}",
481 References => "$header{'message-id'} $data->{msgid}",
482 "X-$gProject-PR-Message" => "they-closed $ref",
483 "X-$gProject-PR-Package" => "$data->{package}",
484 "X-$gProject-PR-Keywords" => "$data->{keywords}",
485 # Only have a X-$gProject-PR-Source when we know the source package
486 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
487 "Reply-To" => "$ref\@$gEmailDomain",
488 "Content-Type" => 'text/plain; charset="utf-8"',
489 ],<<END ,[join("\n",@msg)]),'',undef,1);
490 This is an automatic notification regarding your $gBug report
491 which was filed against the $data->{package} package:
493 #$ref: $data->{subject}
495 It has been closed by $markedby.
497 Their explanation is attached below. If this explanation is
498 unsatisfactory and you have not received a better one in a separate
499 message then please contact $markedby by replying
503 (administrator, $gProject $gBugs database)
513 if ($codeletter eq 'U') {
514 &htmllog("Warning","sent",$replyto,"Message not forwarded.");
515 &sendmessage(<<END, '');
516 From: $gMaintainerEmail ($gProject $gBug Tracking System)
518 Subject: Message with no $gBug number cannot be sent to submitter !
520 Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
521 In-Reply-To: $header{'message-id'}
522 References: $header{'message-id'} $data->{msgid}
524 X-$gProject-PR-Message: error
526 You sent a message to the $gProject $gBug tracking system's $gBug
527 report submitter address $baddress\@$gEmailDomain, without a
528 recognisable $gBug number in the Subject. Your message has been filed
529 under junk but otherwise ignored.
531 If you don't know what I'm talking about then probably either:
533 (a) you unwittingly sent a message to $baddress\@$gEmailDomain
534 because you replied to all recipients of the message a developer sent
535 to a $gBug\'s submitter and you modified the Subject. In this case,
536 please do not be alarmed. To avoid confusion do not do it again, but
537 there is no need to apologise or mail anyone asking for an
540 (b) you are a system administrator, reading this because the $gBug
541 tracking system is responding to a misdirected bounce message. In this
542 case there is a serious mail system misconfiguration somewhere - please
543 contact me immediately.
545 Your message was dated $header{'date'} and had
546 message-id $header{'message-id'}
547 and subject $subject.
549 If you need any assistance or explanation please contact me.
552 (administrator, $gProject $gBugs database)
559 $data->{found_versions} = [];
560 $data->{fixed_versions} = [];
562 if (defined $pheader{source}) {
563 $data->{package} = $pheader{source};
564 } elsif (defined $pheader{package}) {
565 $data->{package} = $pheader{package};
567 &htmllog("Warning","sent",$replyto,"Message not forwarded.");
568 &sendmessage(create_mime_message(
569 ["X-Loop" => "$gMaintainerEmail",
570 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
572 Subject => "Message with no Package: tag cannot be processed! ($subject)",
573 "Message-ID" => "<handler.x.$nn.nonumnosub\@$gEmailDomain>",
574 "In-Reply-To" => $header{'message-id'},
575 References => "$header{'message-id'} $data->{msgid}",
576 Precedence => 'bulk',
577 "X-$gProject-PR-Message" => 'error'
578 ],<<END,[join("\n", @msg)]), '',undef,1);
580 Your message didn't have a Package: line at the start (in the
581 pseudo-header following the real mail header), or didn't have a
582 pseudo-header at all. Your message has been filed under junk but
585 This makes it much harder for us to categorise and deal with your
586 problem report. Please _resubmit_ your report to $baddress\@$gEmailDomain
587 and tell us which package the report is on. For help, check out
588 http://$gWebDomain/Reporting$gHTMLSuffix.
590 Your message was dated $header{'date'} and had
591 message-id $header{'message-id'}
592 and subject $subject.
593 The complete text of it is attached to this message.
595 If you need any assistance or explanation please contact me.
598 (administrator, $gProject $gBugs database)
605 $data->{keywords}= '';
606 if (defined($pheader{'keywords'})) {
607 $data->{keywords}= $pheader{'keywords'};
608 } elsif (defined($pheader{'tags'})) {
609 $data->{keywords}= $pheader{'tags'};
611 if (length($data->{keywords})) {
613 my %gkws = map { ($_, 1) } @gTags;
614 foreach my $kw (sort split(/[,\s]+/, lc($data->{keywords}))) {
615 push @kws, $kw if (defined $gkws{$kw});
617 $data->{keywords} = join(" ", @kws);
619 $data->{severity}= '';
620 if (defined($pheader{'severity'}) || defined($pheader{'priority'})) {
621 $data->{severity}= $pheader{'severity'};
622 $data->{severity}= $pheader{'priority'} unless ($data->{severity});
623 $data->{severity} =~ s/^\s*(.+)\s*$/$1/;
625 if (!grep($_ eq $data->{severity}, @severities, "$gDefaultSeverity")) {
628 Your message specified a Severity: in the pseudo-header, but
629 the severity value $data->{severity} was not recognised.
630 The default severity $gDefaultSeverity is being used instead.
631 The recognised values are: $gShowSeverities.
633 # if we use @gSeverityList array in the above line, perl -c gives:
634 # In string, @gSeverityList now must be written as \@gSeverityList at
635 # process line 452, near "$gDefaultSeverity is being used instead.
636 $data->{severity}= '';
639 if (defined($pheader{owner})) {
640 $data->{owner}= $pheader{owner};
642 if (defined($pheader{forwarded})) {
643 $data->{'forwarded-to'} = $pheader{forwarded};
645 &filelock("nextnumber.lock");
646 open(N,"nextnumber") || &quit("nextnumber: read: $!");
647 $v=<N>; $v =~ s/\n$// || &quit("nextnumber bad format");
648 $ref= $v+0; $v += 1; $newref=1;
649 &overwrite('nextnumber', "$v\n");
651 my $hash = get_hashname($ref);
652 &overwrite("db-h/$hash/$ref.log",'');
653 $data->{originator} = $replyto;
654 $data->{date} = $intdate;
655 $data->{subject} = $subject;
656 $data->{msgid} = $header{'message-id'};
657 writebug($ref, $data);
659 if (exists $pheader{usertags}) {
661 $user = $pheader{user} if exists $pheader{user};
663 $user =~ s/^.*<(.*)>.*$/$1/;
664 $user =~ s/[(].*[)]//;
665 $user =~ s/^\s*(\S+)\s+.*$/$1/;
666 if ($user ne '' and Debbugs::User::is_valid_user($user)) {
667 $pheader{usertags} =~ s/(?:^\s+|\s+$)//g;
669 read_usertags(\%user_tags,$user);
670 for my $tag (split /[,\s]+/, $pheader{usertags}) {
671 if ($tag =~ /^[a-zA-Z0-9.+\@-]+/) {
673 @bugs_with_tag{@{$user_tags{$tag}}} = (1) x @{$user_tags{$tag}};
674 $bugs_with_tag{$ref} = 1;
675 $user_tags{$tag} = [keys %bugs_with_tag];
678 write_usertags(\%user_tags,$user);
682 Your message tried to set a usertag, but didn't have a valid
683 user set ('$user' isn't valid)
687 &overwrite("db-h/$hash/$ref.report",
688 join("\n",@msg)."\n");
693 print DEBUG "maintainers >@maintaddrs<\n";
695 $orgsender= defined($header{'sender'}) ? "Original-Sender: $header{'sender'}\n" : '';
696 $newsubject= $subject; $newsubject =~ s/^$gBug#$ref:*\s*//;
698 $xcchdr= $header{ 'x-debbugs-cc' };
699 if ($xcchdr =~ m/\S/) {
700 push(@resentccs,$xcchdr);
701 $resentccexplain.= <<END;
703 As you requested using X-Debbugs-CC, your message was also forwarded to
705 (after having been given a $gBug report number, if it did not have one).
709 if (@maintaddrs && ($codeletter eq 'B' || $codeletter eq 'M')) {
710 push(@resentccs,@maintaddrs);
711 $resentccexplain.= <<END." ".join("\n ",@maintaddrs)."\n";
713 Your message has been sent to the package maintainer(s):
717 @bccs = @addsrcaddrs;
718 if (defined $gStrongList and isstrongseverity($data->{severity})) {
719 push @bccs, "$gStrongList\@$gListDomain";
722 # Send mail to the per bug list subscription too
723 push @bccs, "bugs=$ref\@$gListDomain";
725 if (defined $pheader{source}) {
726 # Prefix source versions with the name of the source package. They
727 # appear that way in version trees so that we can deal with binary
728 # packages moving from one source package to another.
729 if (defined $pheader{'source-version'}) {
730 addfoundversions($data, $pheader{source}, $pheader{'source-version'}, '');
731 } elsif (defined $pheader{version}) {
732 addfoundversions($data, $pheader{source}, $pheader{version}, '');
734 writebug($ref, $data);
735 } elsif (defined $pheader{package}) {
736 # TODO: could handle Source-Version: by looking up the source package?
737 addfoundversions($data, $pheader{package}, $pheader{version}, 'binary');
738 writebug($ref, $data);
741 $veryquiet= $codeletter eq 'Q';
742 if ($codeletter eq 'M' && !@maintaddrs) {
746 You requested that the message be sent to the package maintainer(s)
747 but either the $gBug report is not associated with any package (probably
748 because of a missing Package pseudo-header field in the original $gBug
749 report), or the package(s) specified do not have any maintainer(s).
751 Your message has *not* been sent to any package maintainers; it has
752 merely been filed in the $gBug tracking system. If you require assistance
753 please contact $gMaintainerEmail quoting the $gBug number $ref.
757 $resentccval.= join(', ',@resentccs);
758 $resentccval =~ s/\s+\n\s+/ /g; $resentccval =~ s/^\s+/ /; $resentccval =~ s/\s+$//;
759 if (length($resentccval)) {
760 $resentcc= "Resent-CC: $resentccval\n";
763 if ($codeletter eq 'U') {
764 &htmllog("Message", "sent on", $data->{originator}, "$gBug#$ref.");
765 &sendmessage(<<END,[$data->{originator},@resentccs],[@bccs]);
766 Subject: $gBug#$ref: $newsubject
767 Reply-To: $replyto, $ref-quiet\@$gEmailDomain
768 ${orgsender}Resent-To: $data->{originator}
769 ${resentcc}Resent-Date: $tdate
770 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
771 Resent-Sender: $gMaintainerEmail
772 X-$gProject-PR-Message: report $ref
773 X-$gProject-PR-Package: $data->{package}
774 X-$gProject-PR-Keywords: $data->{keywords}
775 ${source_pr_header}$fwd
777 } elsif ($codeletter eq 'B') { # Sent to submit
778 &htmllog($newref ? "Report" : "Information", "forwarded",
779 join(', ',"$gSubmitList\@$gListDomain",@resentccs),
780 "<code>$gBug#$ref</code>".
781 (length($data->{package})? "; Package <code>".html_escape($data->{package})."</code>" : '').
783 &sendmessage(<<END,["$gSubmitList\@$gListDomain",@resentccs],[@bccs]);
784 Subject: $gBug#$ref: $newsubject
785 Reply-To: $replyto, $ref\@$gEmailDomain
786 Resent-From: $header{'from'}
787 ${orgsender}Resent-To: $gSubmitList\@$gListDomain
788 ${resentcc}Resent-Date: $tdate
789 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
790 Resent-Sender: $gMaintainerEmail
791 X-$gProject-PR-Message: report $ref
792 X-$gProject-PR-Package: $data->{package}
793 X-$gProject-PR-Keywords: $data->{keywords}
794 ${source_pr_header}$fwd
796 } elsif (@resentccs or @bccs) { # Quiet or Maintainer
797 # D and F done far earlier; B just done - so this must be M or Q
798 # We preserve whichever it was in the Reply-To (possibly adding
801 &htmllog($newref ? "Report" : "Information", "forwarded",
803 "<code>$gBug#$ref</code>".
804 (length($data->{package}) ? "; Package <code>".html_escape($data->{package})."</code>" : '').
807 &htmllog($newref ? "Report" : "Information", "stored",
809 "<code>$gBug#$ref</code>".
810 (length($data->{package}) ? "; Package <code>".html_escape($data->{package})."</code>" : '').
813 &sendmessage(<<END,[@resentccs],[@bccs]);
814 Subject: $gBug#$ref: $newsubject
815 Reply-To: $replyto, $ref-$baddressroot\@$gEmailDomain
816 Resent-From: $header{'from'}
817 ${orgsender}Resent-To: $resentccval
819 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
820 Resent-Sender: $gMaintainerEmail
821 X-$gProject-PR-Message: report $ref
822 X-$gProject-PR-Package: $data->{package}
823 X-$gProject-PR-Keywords: $data->{keywords}
824 ${source_pr_header}$fwd
828 $htmlbreak= length($brokenness) ? "<p>\n".html_escape($brokenness)."\n<p>\n" : '';
829 $htmlbreak =~ s/\n\n/\n<P>\n\n/g;
830 if (length($resentccval)) {
831 $htmlbreak = " Copy sent to <code>".html_escape($resentccval)."</code>.".
834 unless (exists $header{'x-debbugs-no-ack'}) {
836 &htmllog("Acknowledgement","sent",$replyto,
838 "New $gBug report received and filed, but not forwarded." :
839 "New $gBug report received and forwarded."). $htmlbreak);
841 &sendmessage(create_mime_message(
842 ["X-Loop" => "$gMaintainerEmail",
843 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
845 Subject => "$gBug#$ref: Acknowledgement of QUIET report ($subject)",
846 "Message-ID" => "<handler.$ref.$nn.ackquiet\@$gEmailDomain>",
847 "In-Reply-To" => $header{'message-id'},
848 References => $header{'message-id'},
849 Precedence => 'bulk',
850 "X-$gProject-PR-Message" => "ack-quiet $ref",
851 "X-$gProject-PR-Package" => $data->{package},
852 "X-$gProject-PR-Keywords" => $data->{keywords},
853 # Only have a X-$gProject-PR-Source when we know the source package
854 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
855 "Reply-To" => "$ref-quiet\@$gEmailDomain",
856 ],<<END,[join("\n", @msg)]), '',undef,1);
857 Thank you for the problem report you have sent regarding $gProject.
858 This is an automatically generated reply, to let you know your message
859 has been received. It has not been forwarded to the package maintainers
860 or other interested parties; you should ensure that the developers are
861 aware of the problem you have entered into the system - preferably
862 quoting the $gBug reference number, #$ref.
864 If you wish to submit further information on your problem, please send it
865 to $ref-$baddressroot\@$gEmailDomain (and *not*
866 to $baddress\@$gEmailDomain).
868 If you have filed this report in error and wish to close it, please
869 send mail to $ref-done\@$gEmailDomain with an explanation
870 why the bug report should be closed.
872 Please do not reply to the address at the top of this message,
873 unless you wish to report a problem with the $gBug-tracking system.
876 (administrator, $gProject $gBugs database)
879 elsif ($codeletter eq 'M') { # Maintonly
880 &sendmessage(create_mime_message(
881 ["X-Loop" => "$gMaintainerEmail",
882 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
884 Subject => "$gBug#$ref: Acknowledgement of maintainer-only report ($subject)",
885 "Message-ID" => "<handler.$ref.$nn.ackmaint\@$gEmailDomain>",
886 "In-Reply-To" => $header{'message-id'},
887 References => $header{'message-id'},
888 Precedence => 'bulk',
889 "X-$gProject-PR-Message" => "ack-maintonly $ref",
890 "X-$gProject-PR-Package" => $data->{package},
891 "X-$gProject-PR-Keywords" => $data->{keywords},
892 # Only have a X-$gProject-PR-Source when we know the source package
893 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
894 "Reply-To" => "$ref-maintonly\@$gEmailDomain",
895 ],<<END,[]), '',undef,1);
896 Thank you for the problem report you have sent regarding $gProject.
897 This is an automatically generated reply, to let you know your message has
898 been received. It is being forwarded to the package maintainers (but not
899 other interested parties, as you requested) for their attention; they will
902 If you wish to submit further information on your problem, please send
903 it to $ref-$baddressroot\@$gEmailDomain (and *not*
904 to $baddress\@$gEmailDomain).
906 If you have filed this report in error and wish to close it, please
907 send mail to $ref-done\@$gEmailDomain with an explanation
908 why the bug report should be closed.
910 Please do not reply to the address at the top of this message,
911 unless you wish to report a problem with the $gBug-tracking system.
914 (administrator, $gProject $gBugs database)
918 &sendmessage(create_mime_message(
919 ["X-Loop" => "$gMaintainerEmail",
920 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
922 Subject => "$gBug#$ref: Acknowledgement ($subject)",
923 "Message-ID" => "<handler.$ref.$nn.ack\@$gEmailDomain>",
924 "In-Reply-To" => $header{'message-id'},
925 References => $header{'message-id'},
926 Precedence => 'bulk',
927 "X-$gProject-PR-Message" => "ack $ref",
928 "X-$gProject-PR-Package" => $data->{package},
929 "X-$gProject-PR-Keywords" => $data->{keywords},
930 # Only have a X-$gProject-PR-Source when we know the source package
931 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
932 "Reply-To" => "$ref\@$gEmailDomain",
933 ],<<END,[]), '',undef,1);
934 Thank you for the problem report you have sent regarding $gProject.
935 This is an automatically generated reply, to let you know your message has
936 been received. It is being forwarded to the package maintainers and other
937 interested parties for their attention; they will reply in due course.
939 If you wish to submit further information on your problem, please send
940 it to $ref\@$gEmailDomain (and *not* to
941 $baddress\@$gEmailDomain).
943 If you have filed this report in error and wish to close it, please
944 send mail to $ref-done\@$gEmailDomain with an explanation
945 why the bug report should be closed.
947 Please do not reply to the address at the top of this message,
948 unless you wish to report a problem with the $gBug-tracking system.
951 (administrator, $gProject $gBugs database)
954 } elsif ($codeletter ne 'U' and
955 $header{'precedence'} !~ /\b(?:bulk|junk|list)\b/) {
956 &htmllog("Acknowledgement","sent",$replyto,
957 ($veryquiet ? "Extra info received and filed, but not forwarded." :
958 $codeletter eq 'M' ? "Extra info received and forwarded to maintainer." :
959 "Extra info received and forwarded to list."). $htmlbreak);
961 &sendmessage(create_mime_message(
962 ["X-Loop" => "$gMaintainerEmail",
963 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
965 Subject => "$gBug#$ref: Info received and FILED only (was $subject)",
966 "Message-ID" => "<handler.$ref.$nn.ackinfoquiet\@$gEmailDomain>",
967 "In-Reply-To" => $header{'message-id'},
968 References => $header{'message-id'},
969 Precedence => 'bulk',
970 "X-$gProject-PR-Message" => "ack-info-quiet $ref",
971 "X-$gProject-PR-Package" => $data->{package},
972 "X-$gProject-PR-Keywords" => $data->{keywords},
973 # Only have a X-$gProject-PR-Source when we know the source package
974 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
975 "Reply-To" => "$ref-maintonly\@$gEmailDomain",
976 ],<<END,[]), '',undef,1);
977 Thank you for the additional information you have supplied regarding
978 this problem report. It has NOT been forwarded to the package
979 maintainers, but will accompany the original report in the $gBug
980 tracking system. Please ensure that you yourself have sent a copy of
981 the additional information to any relevant developers or mailing lists.
983 If you wish to continue to submit further information on this problem,
984 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
986 Please do not reply to the address at the top of this message,
987 unless you wish to report a problem with the $gBug-tracking system.
990 (administrator, $gProject $gBugs database)
993 elsif ($codeletter eq 'M') {
994 &sendmessage(create_mime_message(
995 ["X-Loop" => "$gMaintainerEmail",
996 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
998 Subject => "$gBug#$ref: Info received for maintainer only (was $subject)",
999 "Message-ID" => "<handler.$ref.$nn.ackinfomaint\@$gEmailDomain>",
1000 "In-Reply-To" => $header{'message-id'},
1001 References => "$header{'message-id'} $data->{msgid}",
1002 Precedence => 'bulk',
1003 "X-$gProject-PR-Message" => "ack-info-maintonly $ref",
1004 "X-$gProject-PR-Package" => $data->{package},
1005 "X-$gProject-PR-Keywords" => $data->{keywords},
1006 "Reply-To" => "$ref-maintonly\@$gEmailDomain",
1007 ],<<END,[]), '',undef,1);
1008 Thank you for the additional information you have supplied regarding
1009 this problem report. It has been forwarded to the package maintainer(s)
1010 (but not to other interested parties) to accompany the original report.
1012 If you wish to continue to submit further information on this problem,
1013 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
1015 Please do not reply to the address at the top of this message,
1016 unless you wish to report a problem with the $gBug-tracking system.
1019 (administrator, $gProject $gBugs database)
1023 &sendmessage(create_mime_message(
1024 ["X-Loop" => "$gMaintainerEmail",
1025 From => "$gMaintainerEmail ($gProject $gBug Tracking System)",
1027 Subject => "$gBug#$ref: Info received ($subject)",
1028 "Message-ID" => "<handler.$ref.$nn.ackinfo\@$gEmailDomain>",
1029 "In-Reply-To" => $header{'message-id'},
1030 References => "$header{'message-id'} $data->{msgid}",
1031 Precedence => 'bulk',
1032 "X-$gProject-PR-Message" => "ack-info $ref",
1033 "X-$gProject-PR-Package" => $data->{package},
1034 "X-$gProject-PR-Keywords" => $data->{keywords},
1035 # Only have a X-$gProject-PR-Source when we know the source package
1036 length($source_package)?("X-$gProject-PR-Source" => $source_package):(),
1037 "Reply-To" => "$ref\@$gEmailDomain",
1038 ],<<END,[]), '',undef,1);
1039 Thank you for the additional information you have supplied regarding
1040 this problem report. It has been forwarded to the package maintainer(s)
1041 and to other interested parties to accompany the original report.
1043 If you wish to continue to submit further information on this problem,
1044 please send it to $ref\@$gEmailDomain, as before.
1046 Please do not reply to the address at the top of this message,
1047 unless you wish to report a problem with the $gBug-tracking system.
1050 (administrator, $gProject $gBugs database)
1062 open(NEW,">$f.new") || &quit("$f.new: create: $!");
1063 print(NEW "$v") || &quit("$f.new: write: $!");
1064 close(NEW) || &quit("$f.new: close: $!");
1065 rename("$f.new","$f") || &quit("rename $f.new to $f: $!");
1069 my $hash = get_hashname($ref);
1070 if (!open(AP,">>db-h/$hash/$ref.log")) {
1071 print DEBUG "failed open log<\n";
1072 print DEBUG "failed open log err $!<\n";
1073 &quit("opening db-h/$hash/$ref.log (li): $!");
1075 print(AP "\7\n",escape_log(@log),"\n\3\n") || &quit("writing db-h/$hash/$ref.log (li): $!");
1076 close(AP) || &quit("closing db-h/$hash/$ref.log (li): $!");
1080 utime(time,time,"db");
1082 while ($u= $cleanups[$#cleanups]) { &$u; }
1083 unlink("incoming/P$nn") || &quit("unlinking incoming/P$nn: $!");
1087 &quit("wot no exit");
1090 local ($whatobj,$whatverb,$where,$desc) = @_;
1091 my $hash = get_hashname($ref);
1092 open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lh): $!");
1095 "<strong>$whatobj $whatverb</strong>".
1096 ($where eq '' ? "" : " to <code>".html_escape($where)."</code>").
1098 "\n\3\n") || &quit("writing db-h/$hash/$ref.log (lh): $!");
1099 close(AP) || &quit("closing db-h/$hash/$ref.log (lh): $!");
1106 while ($msg =~ s/(.*\n)//) {
1113 # strip continuation lines too
1128 send_message($the_message,\@recipients,\@bcc,$do_not_encode)
1130 The first argument is the scalar message, the second argument is the
1131 arrayref of recipients, the third is the arrayref of Bcc:'ed
1134 The final argument turns off header encoding and the addition of the
1135 X-Loop header if true, defaults to false.
1141 my ($msg,$recips,$bcc,$no_encode) = @_;
1142 if (not defined $recips or (!ref($recips) && $recips eq '')
1146 # This is suboptimal. The right solution is to send headers
1147 # separately from the rest of the message and encode them rather
1149 $msg = "X-Loop: $gMaintainerEmail\n" . $msg unless $no_encode;
1150 # The original message received is written out in appendlog, so
1151 # before writing out the other messages we've sent out, we need to
1152 # RFC1522 encode the header.
1153 $msg = encode_headers($msg) unless $no_encode;
1155 my $hash = get_hashname($ref);
1156 #save email to the log
1157 open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lo): $!");
1158 print(AP "\2\n",join("\4",@$recips),"\n\5\n",
1159 escape_log(stripbccs($msg)),"\n\3\n") ||
1160 &quit("writing db-h/$hash/$ref.log (lo): $!");
1161 close(AP) || &quit("closing db-h/$hash/$ref.log (lo): $!");
1164 shift @$recips if $recips->[0] eq '-t';
1165 push @$recips, @$bcc;
1168 send_mail_message(message => $msg,
1169 # Because we encode the headers above, we do not want to encode them here
1170 encode_headers => 0,
1171 recipients => $recips);
1174 my $maintainerschecked = 0;
1175 sub checkmaintainers {
1176 return if $maintainerschecked++;
1177 return if !length($data->{package});
1178 open(MAINT,"$gMaintainerFile") || die &quit("maintainers open: $!");
1182 m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers bogus \`$_'");
1183 $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1184 # use the package which is normalized to lower case; we do this because we lc the pseudo headers.
1185 $maintainerof{$a}= $2;
1188 open(MAINT,"$gMaintainerFileOverride") || die &quit("maintainers.override open: $!");
1192 m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers.override bogus \`$_'");
1193 $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1194 # use the package which is normalized to lower case; we do this because we lc the pseudo headers.
1195 $maintainerof{$a}= $2;
1198 open(SOURCES,"$gPackageSource") || &quit("pkgsrc open: $!");
1200 next unless m/^(\S+)\s+\S+\s+(\S.*\S)\s*$/;
1206 $anymaintfound=0; $anymaintnotfound=0;
1207 for $p (split(m/[ \t?,():]+/,$data->{package})) {
1209 $p =~ /([a-z0-9.+-]+)/;
1211 next unless defined $p;
1212 if (defined $gSubscriptionDomain) {
1213 if (defined($pkgsrc{$p})) {
1214 push @addsrcaddrs, "$pkgsrc{$p}\@$gSubscriptionDomain";
1216 push @addsrcaddrs, "$p\@$gSubscriptionDomain";
1219 if (defined($maintainerof{$p})) {
1220 print DEBUG "maintainer add >$p|$maintainerof{$p}<\n";
1221 $addmaint= $maintainerof{$p};
1222 push(@maintaddrs,$addmaint) unless
1223 $addmaint eq $replyto || grep($_ eq $addmaint, @maintaddrs);
1226 print DEBUG "maintainer none >$p<\n";
1227 push(@maintaddrs,$gUnknownMaintainerEmail) unless $anymaintnotfound;
1228 $anymaintnotfound++;
1233 if (length $data->{owner}) {
1234 print DEBUG "owner add >$data->{package}|$data->{owner}<\n";
1235 $addmaint = $data->{owner};
1236 push(@maintaddrs, $addmaint) unless
1237 $addmaint eq $replyto or grep($_ eq $addmaint, @maintaddrs);
1241 =head2 bug_list_forward
1243 bug_list_forward($spool_filename) if $codeletter eq 'L';
1246 Given the spool file, will forward a bug to the per bug mailing list
1247 subscription system.
1251 sub bug_list_forward{
1253 # Read the bug information and package information for passing to
1255 my ($bug_number) = $bug_fn =~ /^L(\d+)\./;
1256 my ($bfound, $data)= lockreadbugmerge($bug_number);
1257 my $bug_fh = new IO::File "incoming/P$bug_fn" or die "Unable to open incoming/P$bug_fn $!";
1260 my $bug_message = <$bug_fh>;
1261 my ($bug_address) = $bug_message =~ /^Received: \(at ([^\)]+)\) by/;
1262 my ($envelope_from) = $bug_message =~ s/\nFrom\s+([^\s]+)[^\n]+\n/\n/;
1263 if (not defined $envelope_from) {
1264 # Try to use the From: header or something to set it
1265 ($envelope_from) = $bug_message =~ /\nFrom:\s+(.+?)\n/;
1266 # Kludgy, and should really be using a full scale header
1267 # parser to do this.
1268 $envelope_from =~ s/^.+?<([^>]+)>.+$/$1/;
1270 my ($header,$body) = split /\n\n/, $bug_message, 2;
1271 # Add X-$gProject-PR-Message: list bug_number, package name, and bug title headers
1272 $header .= qq(\nX-$gProject-PR-Message: list $bug_number\n).
1273 qq(X-$gProject-PR-Package: $data->{package}\n).
1274 qq(X-$gProject-PR-Title: $data->{subject})
1276 print STDERR "Tried to loop me with $envelope_from\n"
1277 and exit 1 if $envelope_from =~ /\Q$gListDomain\E|\Q$gEmailDomain\E/;
1278 print DEBUG $envelope_from,qq(\n);
1279 # If we don't have a bug address, something has gone horribly wrong.
1280 print STDERR "Doesn't match: $bug_address\n" and exit 1 unless defined $bug_address;
1281 $bug_address =~ s/\@.+//;
1282 print DEBUG "Sending message to bugs=$bug_address\@$gListDomain\n";
1283 print DEBUG $header.qq(\n\n).$body;
1284 send_mail_message(message => $header.qq(\n\n).$body,
1285 recipients => ["bugs=$bug_address\@$gListDomain"],
1286 envelope_from => $envelope_from,
1287 encode_headers => 0,
1289 unlink("incoming/P$bug_fn") || &quit("unlinking incoming/P$bug_fn: $!");