]> git.donarmstrong.com Git - debbugs.git/blobdiff - scripts/process.in
merge changes from dla source tree
[debbugs.git] / scripts / process.in
index 64af4c4eeb4beea4727c3cf66ebae870ed9b42b9..baef90c9812f12b0504bf05c7ac0a0bd32e0a9fd 100755 (executable)
@@ -1,14 +1,19 @@
 #!/usr/bin/perl
-# $Id: process.in,v 1.56 2002/11/11 10:19:44 joy Exp $
+# $Id: process.in,v 1.109 2006/02/09 22:02:04 don Exp $
 #
 # Usage: process nn
 # Temps:  incoming/Pnn
 
-use Mail::Address;
+use POSIX qw(strftime tzset);
+$ENV{"TZ"} = 'UTC';
+tzset();
+
 use MIME::Parser;
+use Debbugs::MIME qw(decode_rfc1522 create_mime_message);
+use Debbugs::Mail qw(send_mail_message encode_headers);
 
-$config_path = '/org/bugs.debian.org/etc';
-$lib_path = '/org/bugs.debian.org/scripts';
+$config_path = '/etc/debbugs';
+$lib_path = '/usr/lib/debbugs';
 
 require "$config_path/config";
 require "$lib_path/errorlib";
@@ -23,7 +28,7 @@ open DEBUG, ">/dev/null";
 defined( $intdate= time ) || &quit( "failed to get time: $!" );
 
 $_=shift;
-m/^([BMQFDU])(\d*)\.\d+$/ || &quit("bad argument");
+m/^([BMQFDUL])(\d*)\.\d+$/ || &quit("bad argument");
 $codeletter= $1;
 $tryref= length($2) ? $2+0 : -1;
 $nn= $_;
@@ -40,6 +45,7 @@ $baddress= 'quiet' if $codeletter eq 'Q';
 $baddress= 'forwarded' if $codeletter eq 'F';
 $baddress= 'done' if $codeletter eq 'D';
 $baddress= 'submitter' if $codeletter eq 'U';
+bug_list_forward($nn) if $codeletter eq 'L';
 $baddress || &quit("bad codeletter $codeletter");
 $baddressroot= $baddress;
 $baddress= "$tryref-$baddress" if $tryref>=0;
@@ -53,7 +59,7 @@ chomp @msg;
 
 print DEBUG "###\n",join("##\n",@msg),"\n###\n";
 
-chop($tdate= `date -u '+%a, %d %h %Y %T GMT'`);
+$tdate = strftime "%a, %d %h %Y %T UTC", localtime;
 $fwd= <<END;
 Received: via spool by $baddress\@$gEmailDomain id=$nn
           (code $codeletter ref $tryref); $tdate
@@ -94,13 +100,15 @@ if ($entity and $entity->head->tags) {
     @bodylines = @msg[$i..$#msg];
 }
 
+my %header;
+
 for my $hdr (@headerlines) {
+    $hdr = decode_rfc1522($hdr);
     $_ = $hdr;
     s/\n\s/ /g;
-    &quit("looping detected")
-       if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
+    &finish if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
     my $ins = !m/^subject:/i && !m/^reply-to:/i && !m/^return-path:/i
-           && !m/^From / && !m/^X-Debbugs-CC:/i && !m/^received:/i;
+           && !m/^From / && !m/^X-Debbugs-/i;
     $fwd .= $hdr."\n" if $ins;
     # print DEBUG ">$_<\n";
     if (s/^(\S+):\s*//) {
@@ -131,8 +139,9 @@ if (@bodylines and $bodylines[0] =~ /^-----BEGIN PGP SIGNED/) {
 # extract pseudo-headers
 for my $phline (@bodylines)
 {
-    last if $phline !~ m/^([\w]+):\s*(\S.*)/;
+    last if $phline !~ m/^([\w-]+):\s*(\S.*)/;
     my ($fn, $fv) = ($1, $2);
+    $fv =~ s/\s*$//;
     print DEBUG ">$fn|$fv|\n";
     $fn = lc $fn;
     $fv = lc $fv;
@@ -140,6 +149,10 @@ for my $phline (@bodylines)
     print DEBUG ">$fn~$fv<\n";
 }
 
+# Allow pseudo headers to set x-debbugs- stuff [#179340]
+for my $key (grep /X-Debbugs-.*/i, keys %pheader) {
+     $header{$key} = $pheader{$key} if not exists $header{$key};
+}
 
 $fwd .= join("\n",@msg[$i..$#msg]);
 
@@ -149,7 +162,14 @@ if (defined $header{'resent-from'} && !defined $header{'from'}) {
     $header{'from'} = $header{'resent-from'};
 }
 defined($header{'from'}) || &quit("no From header");
-$replyto= defined($header{'reply-to'}) ? $header{'reply-to'} : $header{'from'};
+
+$replyto = $header{'reply-to'};
+$replyto = '' unless defined $replyto;
+$replyto =~ s/^ +//;
+$replyto =~ s/ +$//;
+unless (length $replyto) {
+    $replyto = $header{'from'};
+}
 
 $_= $replyto;
 $_= "$2 <$1>" if m/^([^\<\> \t\n\(\)]+) \(([^\(\)\<\>]+)\)$/;
@@ -180,29 +200,35 @@ if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) {
 
 if ($tryref >= 0) 
 {
-    $bfound= &lockreadbugmerge($tryref);
+    ($bfound, $data)= &lockreadbugmerge($tryref);
     if ($bfound) { 
         $ref= $tryref; 
     } else {
         &htmllog("Reply","sent", $replyto,"Unknown problem report number <code>$tryref</code>.");
+        my $archivenote = '';
+        if ($gRemoveAge) {
+            $archivenote = <<END;
+This may be because that $gBug report has been resolved for more than $gRemoveAge
+days, and the record of it has been archived and made read-only, or
+because you mistyped the $gBug report number.
+
+END
+        }
         &sendmessage(<<END, '');
 From: $gMaintainerEmail ($gProject $gBug Tracking System)
 To: $replyto
 Subject: Unknown problem report $gBug#$tryref ($subject)
 Message-ID: <handler.x.$nn.unknown\@$gEmailDomain>
 In-Reply-To: $header{'message-id'}
-References: $header{'message-id'} $s_msgid
+References: $header{'message-id'} $data->{msgid}
+Precedence: bulk
 X-$gProject-PR-Message: error
 
 You sent a message to the $gBug tracking system which gave (in the
 Subject line or encoded into the recipient at $gEmailDomain),
 the number of a nonexistent $gBug report (#$tryref).
 
-This may be because that $gBug report has been resolved for more than $gRemoveAge
-days, and the record of it has been expunged, or because you mistyped
-the $gBug report number.
-
-Your message was dated $header{'date'} and was sent to
+${archivenote}Your message was dated $header{'date'} and was sent to
 $baddress\@$gEmailDomain.  It had
 Message-ID $header{'message-id'}
 and Subject $subject.
@@ -236,27 +262,39 @@ if ($codeletter eq 'D' || $codeletter eq 'F')
     }
     $markedby= $header{'from'} eq $replyto ? $replyto :
                "$header{'from'} (reply to $replyto)";
+    my @generalcc;
     if ($codeletter eq 'F') {
-        (&appendlog,&finish) if length($s_forwarded);
+        (&appendlog,&finish) if length($data->{forwarded});
         $receivedat= "forwarded\@$gEmailDomain";
         $markaswhat= 'forwarded';
         $set_forwarded= $header{'to'};
-       if ( length( $gListDomain ) > 0 && length( $gFowardList ) > 0 ) {
-           $generalcc= "$gFowardList\@$gListDomain";
+       if ( length( $gListDomain ) > 0 && length( $gForwardList ) > 0 ) {
+           push @generalcc, "$gForwardList\@$gListDomain";
+           $generalcc= "$gForwardList\@$gListDomain";
        } else { 
            $generalcc=''; 
         }
     } else {
-       (&appendlog,&finish) if length($s_done);
+        if (length($data->{done}) and
+                not defined $pheader{'source-version'} and
+                not defined $pheader{'version'}) {
+            &appendlog;
+            &finish;
+        }
         $receivedat= "done\@$gEmailDomain";
         $markaswhat= 'done';
         $set_done= $header{'from'};
        if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) {
             $generalcc= "$gDoneList\@$gListDomain";
+           push @generalcc, "$gDoneList\@$gListDomain";
        } else { 
            $generalcc=''; 
        }
     }
+    if (defined $gStrongList and isstrongseverity($data->{severity})) {
+        $generalcc = join ', ', $generalcc, "$gStrongList\@$gListDomain";
+       push @generalcc,"$gStrongList\@$gListDomain";
+    }
     if ($ref<0) {
        &htmllog("Warning","sent",$replyto,"Message ignored.");
         &sendmessage(<<END, '');
@@ -266,7 +304,8 @@ Subject: Message with no $gBug number ignored by $receivedat
          ($subject)
 Message-ID: <header.x.$nn.warnignore\@$gEmailDomain>
 In-Reply-To: $header{'message-id'}
-References: $header{'message-id'} $s_msgid
+References: $header{'message-id'} $data->{msgid}
+Precedence: bulk
 X-$gProject-PR-Message: error
 
 You sent a message to the $gProject $gBug tracking system old-style
@@ -303,50 +342,67 @@ END
 
     &checkmaintainers;
 
-    $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs,@addsrcaddrs));
+    my @noticecc = grep($_ ne $replyto,@maintaddrs);
+    $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs));
     $noticeccval =~ s/\s+\n\s+/ /g; 
     $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
-
     if (length($noticeccval)) { $noticecc= "Cc: $noticeccval\n"; }
-    if (length($generalcc)) { $noticecc.= "Bcc: $generalcc\n"; }
 
-    @process= ($ref,split(/ /,$s_mergedwith));
+    @process= ($ref,split(/ /,$data->{mergedwith}));
     $orgref= $ref;
 
     for $ref (@process) {
        if ($ref != $orgref) {
            &unfilelock;
-           &lockreadbug($ref) || die "huh ? $ref from $orgref out of @process";
+           $data = &lockreadbug($ref)
+               || die "huh ? $ref from $orgref out of @process";
        }
-        $s_done= $set_done if defined($set_done);
-        $s_forwarded= $set_forwarded if defined($set_forwarded);
-       my $hash = get_hashname($ref);
-       &overwrite("db-h/$hash/$ref.status",
-                  "$s_originator\n$s_date\n$s_subject\n$s_msgid\n".
-           "$s_package\n$s_keywords\n$s_done\n$s_forwarded\n$s_mergedwith\n$s_severity\n");
-       &bughook('change',$ref,
-                  "$s_originator\n$s_date\n$s_subject\n$s_msgid\n".
-           "$s_package\n$s_keywords\n$s_done\n$s_forwarded\n$s_mergedwith\n$s_severity\n");
+        $data->{done}= $set_done if defined($set_done);
+        $data->{forwarded}= $set_forwarded if defined($set_forwarded);
+        if ($codeletter eq 'D') {
+            $data->{keywords} = join ' ', grep $_ ne 'pending',
+                                     split ' ', $data->{keywords};
+            if (defined $pheader{'source-version'}) {
+                addfixedversions($data, $pheader{source}, $pheader{'source-version'}, '');
+            } elsif (defined $pheader{version}) {
+                addfixedversions($data, $pheader{package}, $pheader{version}, 'binary');
+            }
+        }
+
+       # Add bug mailing list to $generalbcc as appropriate
+       # This array is used to specify bcc in the cases where we're using create_mime_message.
+       my @generalbcc = (@generalcc,@addsrcaddrs,"bugs=$ref\@$gListDomain");
+       my $generalbcc = join(', ', $generalcc, @addsrcaddrs,"bugs=$ref\@$gListDomain");
+       $generalbcc =~ s/\s+\n\s+/ /g;
+       $generalbcc =~ s/^\s+/ /; $generalbcc =~ s/\s+$//;
+       if (length $generalbcc) {$generalbcc = "Bcc: $generalbcc\n"};
+
+       writebug($ref, $data);
 
+       my $hash = get_hashname($ref);
         open(O,"db-h/$hash/$ref.report") || &quit("read original report: $!");
         $x= join('',<O>); close(O);
         if ($codeletter eq 'F') {
            &htmllog("Reply","sent",$replyto,"You have marked $gBug as forwarded.");
-            &sendmessage(<<END."---------------------------------------\n".join( "\n", @msg ), '');
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-${noticecc}Subject: $gBug#$ref: marked as forwarded ($s_subject)
-Message-ID: <header.$ref.$nn.ackfwdd\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'} $s_msgid
-X-$gProject-PR-Message: forwarded $ref
-
+            &sendmessage(create_mime_message(
+            ["X-Loop"      => "$gMaintainerEmail",
+             From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+              To            => "$replyto",
+              Subject       => "$gBug#$ref: marked as forwarded ($data->{subject})",
+              "Message-ID"  => "<header.$ref.$nn.ackfwdd\@$gEmailDomain>",
+              "In-Reply-To" => $header{'message-id'},
+              References    => "$header{'message-id'} $data->{msgid}",
+              Precedence    => 'bulk',
+              "X-$gProject-PR-Message"  => "forwarded $ref",
+              "X-$gProject-PR-Package"  => $data->{package},
+              "X-$gProject-PR-Keywords" => $data->{keywords}
+             ],<<END ,[join("\n",@msg)]),'',[$replyto,@generalbcc,@noticecc],1);
 Your message dated $header{'date'}
 with message-id $header{'message-id'}
 has caused the $gProject $gBug report #$ref,
-regarding $s_subject
+regarding $data->{subject}
 to be marked as having been forwarded to the upstream software
-author(s) $s_forwarded.
+author(s) $data->{forwarded}.
 
 (NB: If you are a system administrator and have no idea what I am
 talking about this indicates a serious mail system misconfiguration
@@ -359,15 +415,19 @@ END
 
         } else {
            &htmllog("Reply","sent",$replyto,"You have taken responsibility.");
-            &sendmessage(<<END."--------------------------------------\n".$x."---------------------------------------\n".join( "\n", @msg ), '');
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-${noticecc}Subject: $gBug#$ref: marked as done ($s_subject)
-Message-ID: <handler.$ref.$nn.ackdone\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'} $s_msgid
-X-$gProject-PR-Message: closed $ref
-
+            &sendmessage(create_mime_message(
+            ["X-Loop"      => "$gMaintainerEmail",
+             From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+              To            => $replyto,
+              Subject       => "$gBug#$ref: marked as done ($data->{subject})",
+              "Message-ID"  => "<handler.$ref.$nn.ackdone\@$gEmailDomain>",
+              "In-Reply-To" => $header{'message-id'},
+              References    => "$header{'message-id'} $data->{msgid}",
+              Precedence    => 'bulk',
+              "X-$gProject-PR-Message"  => "closed $ref",
+              "X-$gProject-PR-Package"  => $data->{package},
+              "X-$gProject-PR-Keywords" => $data->{keywords}
+             ],<<END ,[$x,join("\n",@msg)]),'',[$replyto,@generalbcc,@noticecc],1);
 Your message dated $header{'date'}
 with message-id $header{'message-id'}
 and subject line $subject
@@ -385,29 +445,32 @@ $gMaintainer
 (administrator, $gProject $gBugs database)
 
 END
-            &htmllog("Notification","sent",$s_originator
+            &htmllog("Notification","sent",$data->{originator}
                "$gBug acknowledged by developer.");
-            &sendmessage(<<END.join("\n",@msg),'');
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $s_originator
-Subject: $gBug#$ref acknowledged by developer
-         ($header{'subject'})
-Message-ID: <handler.$ref.$nn.notifdone\@$gEmailDomain>
-In-Reply-To: $s_msgid
-References: $header{'message-id'} $s_msgid
-X-$gProject-PR-Message: they-closed $ref
-Reply-To: $ref\@$gEmailDomain
-
+            &sendmessage(create_mime_message(
+            ["X-Loop"      => "$gMaintainerEmail",
+             From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+              To            => "$data->{originator}",
+              Subject       => "$gBug#$ref closed by $markedby ($header{'subject'})",
+              "Message-ID"  => "<handler.$ref.$nn.notifdone\@$gEmailDomain>",
+              "In-Reply-To" => "$data->{msgid}",
+              References    => "$header{'message-id'} $data->{msgid}",
+              "X-$gProject-PR-Message"  => "they-closed $ref",
+              "X-$gProject-PR-Package"  => "$data->{package}",
+              "X-$gProject-PR-Keywords" => "$data->{keywords}",
+              "Reply-To"                => "$ref\@$gEmailDomain",
+              "Content-Type"            => 'text/plain; charset="utf-8"',
+             ],<<END ,[join("\n",@msg)]),'',undef,1);
 This is an automatic notification regarding your $gBug report
-#$ref: $s_subject,
-which was filed against the $s_package package.
+#$ref: $data->{subject},
+which was filed against the $data->{package} package.
 
-It has been closed by one of the developers, namely
-$markedby.
+It has been closed by $markedby.
 
 Their explanation is attached below.  If this explanation is
 unsatisfactory and you have not received a better one in a separate
-message then please contact the developer, by replying to this email.
+message then please contact $markedby by replying
+to this email.
 
 $gMaintainer
 (administrator, $gProject $gBugs database)
@@ -429,10 +492,11 @@ Subject: Message with no $gBug number cannot be sent to submitter !
          ($subject)
 Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
 In-Reply-To: $header{'message-id'}
-References: $header{'message-id'} $s_msgid
+References: $header{'message-id'} $data->{msgid}
+Precedence: bulk
 X-$gProject-PR-Message: error
 
-You sent a message to the $gProject $gBug tracking system send to $gBug 
+You sent a message to the $gProject $gBug tracking system's $gBug 
 report submitter address $baddress\@$gEmailDomain, without a
 recognisable $gBug number in the Subject.  Your message has been filed
 under junk but otherwise ignored.
@@ -441,7 +505,7 @@ If you don't know what I'm talking about then probably either:
 
 (a) you unwittingly sent a message to $baddress\@$gEmailDomain
 because you replied to all recipients of the message a developer sent
-to a $gBug's submitter and you modified the Subject.  In this case,
+to a $gBug\'s submitter and you modified the Subject.  In this case,
 please do not be alarmed.  To avoid confusion do not do it again, but
 there is no need to apologise or mail anyone asking for an
 explanation.
@@ -464,25 +528,37 @@ END
        &appendlog;
        &finish;
     }
-    if (!defined($pheader{'package'})) {
+
+    $data->{found_versions} = [];
+    $data->{fixed_versions} = [];
+
+    if (defined $pheader{source}) {
+        $data->{package} = $pheader{source};
+    } elsif (defined $pheader{package}) {
+        $data->{package} = $pheader{package};
+    } else {
        &htmllog("Warning","sent",$replyto,"Message not forwarded.");
-        &sendmessage(<<END."---------------------------------------------------------------------------\n".join("\n", @msg), '');
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-Subject: Message with no Package: tag cannot be processed!
-         ($subject)
-Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'} $s_msgid
-X-$gProject-PR-Message: error
+        &sendmessage(create_mime_message(
+                       ["X-Loop"      => "$gMaintainerEmail",
+                       From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+                        To            => $replyto,
+                        Subject       => "Message with no Package: tag cannot be processed! ($subject)",
+                        "Message-ID"  => "<handler.x.$nn.nonumnosub\@$gEmailDomain>",
+                        "In-Reply-To" => $header{'message-id'},
+                        References    => "$header{'message-id'} $data->{msgid}",
+                        Precedence    => 'bulk',
+                        "X-$gProject-PR-Message" => 'error'
+                      ],<<END,[join("\n", @msg)]), '',undef,1);
 
 Your message didn't have a Package: line at the start (in the
 pseudo-header following the real mail header), or didn't have a
-pseudo-header at all.
+pseudo-header at all.  Your message has been filed under junk but
+otherwise ignored.
 
 This makes it much harder for us to categorise and deal with your
-problem report. Please _resubmit_ your report and tell us which package
-the report is on. For help, check out http://$gWebDomain/Reporting.html.
+problem report. Please _resubmit_ your report to $baddress\@$gEmailDomain
+and tell us which package the report is on. For help, check out
+http://$gWebDomain/Reporting$gHTMLSuffix.
 
 Your message was dated $header{'date'} and had
 message-id $header{'message-id'}
@@ -497,57 +573,48 @@ $gMaintainer
 END
        &appendlog;
        &finish;
-    } else {
-       $s_package= $pheader{'package'}; 
-    }
-
-    $s_versions= '';
-    if (defined($pheader{'version'})) {
-        $s_versions = $pheader{'version'};
-        $s_versions ~= s/\s+/ /;
-       # BUG: need to bounce unknown versions back to submitter here
-    }
-
-    $s_fixed_versions= '';
-    if (defined($pheader{'fixed-in-version'})) {
-        $s_fixed_versions = $pheader{'fixed-in-version'};
-        $s_fixed_versions ~= s/\s+/ /;
     }
 
-    $s_keywords= '';
+    $data->{keywords}= '';
     if (defined($pheader{'keywords'})) {
-        $s_keywords= $pheader{'keywords'};
+        $data->{keywords}= $pheader{'keywords'};
     } elsif (defined($pheader{'tags'})) {
-        $s_keywords= $pheader{'tags'};
+        $data->{keywords}= $pheader{'tags'};
     }
-    if (length($s_keywords)) {
+    if (length($data->{keywords})) {
         my @kws;
         my %gkws = map { ($_, 1) } @gTags;
-        foreach my $kw (sort split(/[,\s]+/, lc($s_keywords))) {
+        foreach my $kw (sort split(/[,\s]+/, lc($data->{keywords}))) {
             push @kws, $kw if (defined $gkws{$kw});
         }
-        $s_keywords = join(" ", @kws);
+        $data->{keywords} = join(" ", @kws);
     }
-    $s_severity= '';
+    $data->{severity}= '';
     if (defined($pheader{'severity'}) || defined($pheader{'priority'})) {
-       $s_severity= $pheader{'severity'};
-       $s_severity= $pheader{'priority'} unless ($s_severity);
-       $s_severity =~ s/^\s*(.+)\s*$/$1/;
+       $data->{severity}= $pheader{'severity'};
+       $data->{severity}= $pheader{'priority'} unless ($data->{severity});
+       $data->{severity} =~ s/^\s*(.+)\s*$/$1/;
 
-       if (!grep($_ eq $s_severity, @severities, "$gDefaultSeverity")) {
+       if (!grep($_ eq $data->{severity}, @severities, "$gDefaultSeverity")) {
             $brokenness.= <<END;
 
 Your message specified a Severity: in the pseudo-header, but
-the severity value $s_severity was not recognised.
+the severity value $data->{severity} was not recognised.
 The default severity $gDefaultSeverity is being used instead.
 The recognised values are: $gShowSeverities.
 END
 # if we use @gSeverityList array in the above line, perl -c gives:
 # In string, @gSeverityList now must be written as \@gSeverityList at
 #          process line 452, near "$gDefaultSeverity is being used instead.
-            $s_severity= '';
+            $data->{severity}= '';
         }
     }
+    if (defined($pheader{owner})) {
+        $data->{owner}= $pheader{owner};
+    }
+    if (defined($pheader{forwarded})) {
+       $data->{'forwarded-to'} = $pheader{forwarded};
+    }
     &filelock("nextnumber.lock");
     open(N,"nextnumber") || &quit("nextnumber: read: $!");
     $v=<N>; $v =~ s/\n$// || &quit("nextnumber bad format");
@@ -556,14 +623,11 @@ END
     &unfilelock;
     my $hash = get_hashname($ref);
     &overwrite("db-h/$hash/$ref.log",'');
-    &overwrite("db-h/$hash/$ref.status",
-               "$replyto\n$intdate\n$subject\n$header{'message-id'}\n".
-               "$s_package\n$s_keywords\n\n\n\n$s_severity\n$s_versions\n".
-               "$s_fixed_versions\n");
-    &bughook('new',$ref,
-               "$replyto\n$intdate\n$subject\n$header{'message-id'}\n".
-               "$s_package\n$s_keywords\n\n\n\n$s_severity\n$s_versions\n".
-               "$s_fixed_versions\n");
+    $data->{originator} = $replyto;
+    $data->{date} = $intdate;
+    $data->{subject} = $subject;
+    $data->{msgid} = $header{'message-id'};
+    writebug($ref, $data);
     &overwrite("db-h/$hash/$ref.report",
                join("\n",@msg)."\n");
 }
@@ -594,7 +658,29 @@ Your message has been sent to the package maintainer(s):
 END
 }
 
-push(@resentccs, @addsrcaddrs);
+@bccs = @addsrcaddrs;
+if (defined $gStrongList and isstrongseverity($data->{severity})) {
+    push @bccs, "$gStrongList\@$gListDomain";
+}
+
+# Send mail to the per bug list subscription too
+push @bccs, "bugs=$ref\@$gListDomain";
+
+if (defined $pheader{source}) {
+    # Prefix source versions with the name of the source package. They
+    # appear that way in version trees so that we can deal with binary
+    # packages moving from one source package to another.
+    if (defined $pheader{'source-version'}) {
+        addfoundversions($data, $pheader{source}, $pheader{'source-version'}, '');
+    } elsif (defined $pheader{version}) {
+        addfoundversions($data, $pheader{source}, $pheader{version}, '');
+    }
+    writebug($ref, $data);
+} elsif (defined $pheader{package}) {
+    # TODO: could handle Source-Version: by looking up the source package?
+    addfoundversions($data, $pheader{package}, $pheader{version}, 'binary');
+    writebug($ref, $data);
+}
 
 $veryquiet= $codeletter eq 'Q';
 if ($codeletter eq 'M' && !@maintaddrs) {
@@ -619,26 +705,26 @@ if (length($resentccval)) {
 }
 
 if ($codeletter eq 'U') {
-    &htmllog("Message", "sent on", $s_originator, "$gBug#$ref.");
-    &sendmessage(<<END,$s_originator,@resentccs);
+    &htmllog("Message", "sent on", $data->{originator}, "$gBug#$ref.");
+    &sendmessage(<<END,[$data->{originator},@resentccs],[@bccs]);
 Subject: $gBug#$ref: $newsubject
 Reply-To: $replyto, $ref-quiet\@$gEmailDomain
-${orgsender}Resent-To: $s_originator
+${orgsender}Resent-To: $data->{originator}
 ${resentcc}Resent-Date: $tdate
 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
 Resent-Sender: $gMaintainerEmail
 X-$gProject-PR-Message: report $ref
-X-$gProject-PR-Package: $s_package
-X-$gProject-PR-Keywords: $s_keywords
+X-$gProject-PR-Package: $data->{package}
+X-$gProject-PR-Keywords: $data->{keywords}
 $fwd
 END
 } elsif ($codeletter eq 'B') {
     &htmllog($newref ? "Report" : "Information", "forwarded",
              join(', ',"$gSubmitList\@$gListDomain",@resentccs),
              "<code>$gBug#$ref</code>".
-             (length($s_package)? "; Package <code>".&sani($s_package)."</code>" : '').
+             (length($data->{package})? "; Package <code>".&sani($data->{package})."</code>" : '').
              ".");
-    &sendmessage(<<END,"$gSubmitList\@$gListDomain",@resentccs);
+    &sendmessage(<<END,["$gSubmitList\@$gListDomain",@resentccs],[@bccs]);
 Subject: $gBug#$ref: $newsubject
 Reply-To: $replyto, $ref\@$gEmailDomain
 Resent-From: $header{'from'}
@@ -647,20 +733,28 @@ ${resentcc}Resent-Date: $tdate
 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
 Resent-Sender: $gMaintainerEmail
 X-$gProject-PR-Message: report $ref
-X-$gProject-PR-Package: $s_package
-X-$gProject-PR-Keywords: $s_keywords
+X-$gProject-PR-Package: $data->{package}
+X-$gProject-PR-Keywords: $data->{keywords}
 $fwd
 END
-} elsif (@resentccs) {
+} elsif (@resentccs or @bccs) {
     # D and F done far earlier; B just done - so this must be M or Q
     # We preserve whichever it was in the Reply-To (possibly adding
     # the $gBug#).
-    &htmllog($newref ? "Report" : "Information", "forwarded",
-             $resentccval,
-             "<code>$gBug#$ref</code>".
-             (length($s_package)? "; Package <code>".&sani($s_package)."</code>" : '').
-             ".");
-    &sendmessage(<<END,@resentccs);
+    if (@resentccs) {
+        &htmllog($newref ? "Report" : "Information", "forwarded",
+                 $resentccval,
+                 "<code>$gBug#$ref</code>".
+                 (length($data->{package}) ? "; Package <code>".&sani($data->{package})."</code>" : '').
+                 ".");
+    } else {
+        &htmllog($newref ? "Report" : "Information", "stored",
+                 "",
+                 "<code>$gBug#$ref</code>".
+                 (length($data->{package}) ? "; Package <code>".&sani($data->{package})."</code>" : '').
+                 ".");
+    }
+    &sendmessage(<<END,[@resentccs],[@bccs]);
 Subject: $gBug#$ref: $newsubject
 Reply-To: $replyto, $ref-$baddressroot\@$gEmailDomain
 Resent-From: $header{'from'}
@@ -669,8 +763,8 @@ Resent-Date: $tdate
 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
 Resent-Sender: $gMaintainerEmail
 X-$gProject-PR-Message: report $ref
-X-$gProject-PR-Package: $s_package
-X-$gProject-PR-Keywords: $s_keywords
+X-$gProject-PR-Package: $data->{package}
+X-$gProject-PR-Keywords: $data->{keywords}
 $fwd
 END
 }
@@ -681,28 +775,33 @@ if (length($resentccval)) {
     $htmlbreak = "  Copy sent to <code>".&sani($resentccval)."</code>.".
         $htmlbreak;
 }
-if ($newref) {
-    &htmllog("Acknowledgement","sent",$replyto,
-             ($veryquiet ?
-              "New $gBug report received and filed, but not forwarded." :
-              "New $gBug report received and forwarded."). $htmlbreak);
-    &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-Subject: $gBug#$ref: Acknowledgement of QUIET report
-         ($subject)
-Message-ID: <handler.$ref.$nn.ackquiet\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'}
-X-$gProject-PR-Message: ack-quiet $ref
-Reply-To: $ref-quiet\@$gEmailDomain
-
+unless (exists $header{'x-debbugs-no-ack'}) {
+    if ($newref) {
+        &htmllog("Acknowledgement","sent",$replyto,
+                 ($veryquiet ?
+                  "New $gBug report received and filed, but not forwarded." :
+                  "New $gBug report received and forwarded."). $htmlbreak);
+       if ($veryquiet) {
+            &sendmessage(create_mime_message(
+                      ["X-Loop"      => "$gMaintainerEmail",
+                       From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+                       To            => $replyto,
+                        Subject       => "$gBug#$ref: Acknowledgement of QUIET report ($subject)",
+                        "Message-ID"  => "<handler.$ref.$nn.ackquiet\@$gEmailDomain>",
+                        "In-Reply-To" => $header{'message-id'},
+                        References    => $header{'message-id'},
+                        Precedence    => 'bulk',
+                       "X-$gProject-PR-Message"  => "ack-quiet $ref",
+                       "X-$gProject-PR-Package"  => $data->{package},
+                       "X-$gProject-PR-Keywords" => $data->{keywords},
+                       "Reply-To"                => "$ref-quiet\@$gEmailDomain",
+                      ],<<END,[join("\n", @msg)]), '',undef,1);
 Thank you for the problem report you have sent regarding $gProject.
 This is an automatically generated reply, to let you know your message
-has been received.  It has not been forwarded to the developers or
-their mailing list; you should ensure that the developers are aware of
-the problem you have entered into the system - preferably quoting the
-$gBug reference number, #$ref.
+has been received.  It has not been forwarded to the package maintainers
+or other interested parties; you should ensure that the developers are
+aware of the problem you have entered into the system - preferably
+quoting the $gBug reference number, #$ref.
 $resentccexplain
 If you wish to submit further information on your problem, please send it
 to $ref-$baddressroot\@$gEmailDomain (and *not*
@@ -714,20 +813,27 @@ $brokenness
 $gMaintainer
 (administrator, $gProject $gBugs database)
 END
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-Subject: $gBug#$ref: Acknowledgement of maintainer-only report
-         ($subject)
-Message-ID: <handler.$ref.$nn.ackmaint\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'}
-X-$gProject-PR-Message: ack-maintonly $ref
-Reply-To: $ref-maintonly\@$gEmailDomain
-
+       }
+       elsif ($codeletter eq 'M') {
+            &sendmessage(create_mime_message(
+                      ["X-Loop"      => "$gMaintainerEmail",
+                       From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+                       To            => $replyto,
+                        Subject       => "$gBug#$ref: Acknowledgement of maintainer-only report ($subject)",
+                        "Message-ID"  => "<handler.$ref.$nn.ackmaint\@$gEmailDomain>",
+                        "In-Reply-To" => $header{'message-id'},
+                        References    => $header{'message-id'},
+                        Precedence    => 'bulk',
+                       "X-$gProject-PR-Message" => "ack-maintonly $ref",
+                       "X-$gProject-PR-Package"  => $data->{package},
+                       "X-$gProject-PR-Keywords" => $data->{keywords},
+                       "Reply-To"               => "$ref-maintonly\@$gEmailDomain",
+                      ],<<END,[]), '',undef,1);
 Thank you for the problem report you have sent regarding $gProject.
 This is an automatically generated reply, to let you know your message has
-been received.  It is being forwarded to the developers (but not the mailing
-list, as you requested) for their attention; they will reply in due course.
+been received.  It is being forwarded to the package maintainers (but not
+other interested parties, as you requested) for their attention; they will
+reply in due course.
 $resentccexplain
 If you wish to submit further information on your problem, please send
 it to $ref-$baddressroot\@$gEmailDomain (and *not*
@@ -739,19 +845,26 @@ $brokenness
 $gMaintainer
 (administrator, $gProject $gBugs database)
 END
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-Subject: $gBug#$ref: Acknowledgement ($subject)
-Message-ID: <handler.$ref.$nn.ack\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'}
-X-$gProject-PR-Message: ack $ref
-Reply-To: $ref\@$gEmailDomain
-
+                  }
+       else {
+            &sendmessage(create_mime_message(
+                      ["X-Loop"      => "$gMaintainerEmail",
+                       From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+                       To            => $replyto,
+                        Subject       => "$gBug#$ref: Acknowledgement ($subject)",
+                        "Message-ID"  => "<handler.$ref.$nn.ack\@$gEmailDomain>",
+                        "In-Reply-To" => $header{'message-id'},
+                        References    => $header{'message-id'},
+                        Precedence    => 'bulk',
+                       "X-$gProject-PR-Message"  => "ack $ref",
+                       "X-$gProject-PR-Package"  => $data->{package},
+                       "X-$gProject-PR-Keywords" => $data->{keywords},
+                       "Reply-To"                => "$ref\@$gEmailDomain",
+                      ],<<END,[]), '',undef,1);
 Thank you for the problem report you have sent regarding $gProject.
 This is an automatically generated reply, to let you know your message has
-been received.  It is being forwarded to the developers mailing list for
-their attention; they will reply in due course.
+been received.  It is being forwarded to the package maintainers and other
+interested parties for their attention; they will reply in due course.
 $resentccexplain
 If you wish to submit further information on your problem, please send
 it to $ref\@$gEmailDomain (and *not* to
@@ -763,27 +876,36 @@ $brokenness
 $gMaintainer
 (administrator, $gProject $gBugs database)
 END
-} elsif ($codeletter ne 'U') {
-    &htmllog("Acknowledgement","sent",$replyto,
-             ($veryquiet ? "Extra info received and filed, but not forwarded." :
-              $codeletter eq 'M' ? "Extra info received and forwarded to maintainer." :
-              "Extra info received and forwarded to list."). $htmlbreak);
-    &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-Subject: $gBug#$ref: Info received and FILED only
-         (was $subject)
-Message-ID: <handler.$ref.$nn.ackinfoquiet\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'}
-X-$gProject-PR-Message: ack-info-quiet $ref
-Reply-To: $ref-quiet\@$gEmailDomain
-
+                  }
+    } elsif ($codeletter ne 'U' and
+             $header{'precedence'} !~ /\b(?:bulk|junk|list)\b/ and
+            # Workaround for gcc mail loops; bugzilla should do Precedence:
+            # instead. Deliberately not in CVS. - cjwatson
+            not exists $header{'x-bugzilla-reason'}) {
+        &htmllog("Acknowledgement","sent",$replyto,
+                 ($veryquiet ? "Extra info received and filed, but not forwarded." :
+                  $codeletter eq 'M' ? "Extra info received and forwarded to maintainer." :
+                  "Extra info received and forwarded to list."). $htmlbreak);
+       if ($veryquiet) {
+            &sendmessage(create_mime_message(
+                      ["X-Loop"      => "$gMaintainerEmail",
+                       From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+                       To            => $replyto,
+                        Subject       => "$gBug#$ref: Info received and FILED only (was $subject)",
+                        "Message-ID"  => "<handler.$ref.$nn.ackinfoquiet\@$gEmailDomain>",
+                        "In-Reply-To" => $header{'message-id'},
+                        References    => $header{'message-id'},
+                        Precedence    => 'bulk',
+                       "X-$gProject-PR-Message" => "ack-info-quiet $ref",
+                       "X-$gProject-PR-Package"  => $data->{package},
+                       "X-$gProject-PR-Keywords" => $data->{keywords},
+                       "Reply-To"               => "$ref-maintonly\@$gEmailDomain",
+                      ],<<END,[]), '',undef,1);
 Thank you for the additional information you have supplied regarding
-this problem report.  It has NOT been forwarded to the developers, but
-will accompany the original report in the $gBug tracking system.  Please
-ensure that you yourself have sent a copy of the additional
-information to any relevant developers or mailing lists.
+this problem report.  It has NOT been forwarded to the package
+maintainers, but will accompany the original report in the $gBug
+tracking system.  Please ensure that you yourself have sent a copy of
+the additional information to any relevant developers or mailing lists.
 $resentccexplain
 If you wish to continue to submit further information on your problem,
 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
@@ -794,19 +916,25 @@ $brokenness
 $gMaintainer
 (administrator, $gProject $gBugs database)
 END
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-Subject: $gBug#$ref: Info received for maintainer only
-         (was $subject)
-Message-ID: <handler.$ref.$nn.ackinfomaint\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'}
-X-$gProject-PR-Message: ack-info-maintonly $ref
-Reply-To: $ref-maintonly\@$gEmailDomain
-
+                }
+       elsif ($codeletter eq 'M') {
+            &sendmessage(create_mime_message(
+                      ["X-Loop"      => "$gMaintainerEmail",
+                       From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+                       To            => $replyto,
+                        Subject       => "$gBug#$ref: Info received for maintainer only (was $subject)",
+                        "Message-ID"  => "<handler.$ref.$nn.ackinfomaint\@$gEmailDomain>",
+                        "In-Reply-To" => $header{'message-id'},
+                        References    => "$header{'message-id'} $data->{msgid}",
+                        Precedence    => 'bulk',
+                       "X-$gProject-PR-Message" => "ack-info-maintonly $ref",
+                       "X-$gProject-PR-Package"  => $data->{package},
+                       "X-$gProject-PR-Keywords" => $data->{keywords},
+                       "Reply-To"               => "$ref-maintonly\@$gEmailDomain",
+                      ],<<END,[]), '',undef,1);
 Thank you for the additional information you have supplied regarding
-this problem report.  It has been forwarded to the developer(s) (but
-not to the mailing list) to accompany the original report.
+this problem report.  It has been forwarded to the package maintainer(s)
+(but not to other interested parties) to accompany the original report.
 $resentccexplain
 If you wish to continue to submit further information on your problem,
 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
@@ -817,18 +945,25 @@ $brokenness
 $gMaintainer
 (administrator, $gProject $gBugs database)
 END
-From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $replyto
-Subject: $gBug#$ref: Info received (was $subject)
-Message-ID: <handler.$ref.$nn.ackinfo\@$gEmailDomain>
-In-Reply-To: $header{'message-id'}
-References: $header{'message-id'}
-X-$gProject-PR-Message: ack-info $ref
-Disabled-Doogie-Reply-To: $ref\@$gEmailDomain
-
+                  }
+       else {
+            &sendmessage(create_mime_message(
+                      ["X-Loop"      => "$gMaintainerEmail",
+                       From          => "$gMaintainerEmail ($gProject $gBug Tracking System)",
+                       To            => $replyto,
+                        Subject       => "$gBug#$ref: Info received ($subject)",
+                        "Message-ID"  => "<handler.$ref.$nn.ackinfo\@$gEmailDomain>",
+                        "In-Reply-To" => $header{'message-id'},
+                        References    => "$header{'message-id'} $data->{msgid}",
+                        Precedence    => 'bulk',
+                       "X-$gProject-PR-Message"  => "ack-info $ref",
+                       "X-$gProject-PR-Package"  => $data->{package},
+                       "X-$gProject-PR-Keywords" => $data->{keywords},
+                       "Reply-To"                => "$ref\@$gEmailDomain",
+                      ],<<END,[]), '',undef,1);
 Thank you for the additional information you have supplied regarding
-this problem report.  It has been forwarded to the developer(s) and
-to the developers mailing list to accompany the original report.
+this problem report.  It has been forwarded to the package maintainer(s)
+and to other interested parties to accompany the original report.
 $resentccexplain
 If you wish to continue to submit further information on your problem,
 please send it to $ref\@$gEmailDomain, as before.
@@ -839,6 +974,9 @@ $brokenness
 $gMaintainer
 (administrator, $gProject $gBugs database)
 END
+
+                  }
+   }
 }
 
 &appendlog;
@@ -881,103 +1019,96 @@ sub htmllog {
     open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lh): $!");
     print(AP
           "\6\n".
-          "<strong>$whatobj $whatverb</strong> to <code>".&sani($where).
-          "</code>:<br>\n". $desc.
+          "<strong>$whatobj $whatverb</strong>".
+          ($where eq '' ? "" : " to <code>".&sani($where)."</code>").
+          ":<br>\n". $desc.
           "\n\3\n") || &quit("writing db-h/$hash/$ref.log (lh): $!");
     close(AP) || &quit("closing db-h/$hash/$ref.log (lh): $!");
 }    
 
-sub get_addresses {
-       return
-               map { $_->address() }
-               map { Mail::Address->parse($_) } @_;
+sub stripbccs {
+    my $msg = shift;
+    my $ret = '';
+    my $bcc = 0;
+    while ($msg =~ s/(.*\n)//) {
+       local $_ = $1;
+       if (/^$/) {
+           $ret .= $_;
+           last;
+       }
+       if ($bcc) {
+           # strip continuation lines too
+           next if /^\s/;
+           $bcc = 0;
+       }
+       if (/^Bcc:/i) {
+           $bcc = 1;
+       } else {
+           $ret .= $_;
+       }
+    }
+    return $ret . $msg;
 }
 
+=head2 send_message
+
+     send_message($the_message,\@recipients,\@bcc,$do_not_encode)
+
+The first argument is the scalar message, the second argument is the
+arrayref of recipients, the third is the arrayref of Bcc:'ed
+recipients.
+
+The final argument turns off header encoding and the addition of the
+X-Loop header if true, defaults to false.
+
+=cut
+
+
 sub sendmessage {
-    local ($msg,@recips) = @_;
-    if ($recips[0] eq '' && $#recips == 0) { @recips= ('-t'); }
-    $msg = "X-Loop: $gMaintainerEmail\n" . $msg;
+    my ($msg,$recips,$bcc,$no_encode) = @_;
+    if (not defined $recips or (!ref($recips) && $recips eq '')
+       or @$recips == 0) {
+       $recips = ['-t'];
+    }
+    # This is suboptimal. The right solution is to send headers
+    # separately from the rest of the message and encode them rather
+    # than doing this.
+    $msg = "X-Loop: $gMaintainerEmail\n" . $msg unless $no_encode;
+    # The original message received is written out in appendlog, so
+    # before writing out the other messages we've sent out, we need to
+    # RFC1522 encode the header.
+    $msg = encode_headers($msg) unless $no_encode;
 
     my $hash = get_hashname($ref);
     #save email to the log
     open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lo): $!");
-    print(AP "\2\n",join("\4",@recips),"\n\5\n",@{escapelog($msg)},"\n\3\n") ||
+    print(AP "\2\n",join("\4",@$recips),"\n\5\n",
+          @{escapelog(stripbccs($msg))},"\n\3\n") ||
         &quit("writing db-h/$hash/$ref.log (lo): $!");
     close(AP) || &quit("closing db-h/$hash/$ref.log (lo): $!");
-    
-#if debbuging.. save email to a log
-#    open AP, ">>debug";
-#    print AP join( '|', @recips )."\n>>";
-#    print AP get_addresses( @recips );
-#    print AP "<<\n".$msg;
-#    print AP "\n--------------------------------------------------------\n";
-#    close AP;
-
-    #start mailing
-    $_ = '';
-    $SIG{'CHLD'}='chldhandle';
-    #print DEBUG "mailing sigchild set up<\n";
-    $chldexit = 'no';
-    $c= open(U,"-|");
-    #print DEBUG "mailing opened pipe fork<\n";
-    defined($c) || die $!;
-    #print DEBUG "mailing opened pipe fork ok $c<\n";
-    if (!$c) { # ie, we are in the child process
-       #print DEBUG "mailing child<\n";
-        unless (open(STDERR,">&STDOUT")) {
-           #print DEBUG "mailing child opened stderr<\n";
-            print STDOUT "redirect stderr: $!\n";
-           #print DEBUG "mailing child opened stderr fail<\n";
-            exit 1;
-           #print DEBUG "mailing child opened stderr fail exit !?<\n";
-        }
-       #print DEBUG "mailing child opened stderr ok<\n";
-        $c= open(D,"|-");
-       #print DEBUG "mailing child forked again<\n";
-        defined($c) || die $!;
-       #print DEBUG "mailing child forked again ok $c<\n";
-        if (!$c) { # ie, we are the child process
-           #print DEBUG "mailing grandchild<\n";
-            exec '/usr/lib/sendmail','-f'."$gMaintainerEmail",'-odq','-oem','-oi',get_addresses(@recips);
-           #print DEBUG "mailing grandchild exec failed<\n";
-            die $!;
-           #print DEBUG "mailing grandchild died !?<\n";
-        }
-       #print DEBUG "mailing child not grandchild<\n";
-        print(D $msg) || die $!;
-       #print DEBUG "mailing child printed msg<\n";
-        close(D);
-       #print DEBUG "mailing child closed pipe<\n";
-        die "\n*** command returned exit status $?\n" if $?;
-       #print DEBUG "mailing child exit status ok<\n";
-        exit 0;
-       #print DEBUG "mailing child exited ?!<\n";
+
+    if (ref($bcc)) {
+        shift @$recips if $recips->[0] eq '-t';
+        push @$recips, @$bcc;
     }
-    #print DEBUG "mailing parent<\n";
-    $results='';
-    #print DEBUG "mailing parent results emptied<\n";
-    while( $chldexit eq 'no' ) { $results.= $_; }
-    #print DEBUG "mailing parent results read >$results<\n";
-    close(U);
-    #print DEBUG "mailing parent results closed<\n";
-    $results.= "\n*** child returned exit status $?\n" if $?;
-    #print DEBUG "mailing parent exit status ok<\n";
-    $SIG{'CHLD'}='DEFAULT';
-    #print DEBUG "mailing parent sigchild default<\n";
-    if (length($results)) { &quit("running sendmail: $results"); }
-    #print DEBUG "mailing parent results ok<\n";
+
+    send_mail_message(message        => $msg,
+                     # Because we encode the headers above, we do not want to encode them here
+                     encode_headers => 0,
+                     recipients     => $recips);
 }
 
 sub checkmaintainers {
     return if $maintainerschecked++;
-    return if !length($s_package);
+    return if !length($data->{package});
     open(MAINT,"$gMaintainerFile") || die &quit("maintainers open: $!");
     while (<MAINT>) {
        m/^\n$/ && next;
        m/^\s*$/ && next;
         m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers bogus \`$_'");
         $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
-        $maintainerof{$1}= $2;
+       # use the package which is normalized to lower case; we do this because we lc the pseudo headers.
+        $maintainerof{$a}= $2;
     }
     close(MAINT);
     open(MAINT,"$gMaintainerFileOverride") || die &quit("maintainers.override open: $!");
@@ -986,7 +1117,8 @@ sub checkmaintainers {
        m/^\s*$/ && next;
         m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers.override bogus \`$_'");
         $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
-        $maintainerof{$1}= $2;
+       # use the package which is normalized to lower case; we do this because we lc the pseudo headers.
+        $maintainerof{$a}= $2;
     }
     close(MAINT);
     open(SOURCES,"$gPackageSource") || &quit("pkgsrc open: $!");
@@ -998,12 +1130,17 @@ sub checkmaintainers {
     }
     close(SOURCES);
     $anymaintfound=0; $anymaintnotfound=0;
-    for $p (split(m/[ \t?,()]+/,$s_package)) {
+    for $p (split(m/[ \t?,():]+/,$data->{package})) {
         $p =~ y/A-Z/a-z/;
-       if (defined($pkgsrc{$p})) {
-           push @addsrcaddrs, "$pkgsrc{$p}\@packages.qa.debian.org";
-       } else {
-           push @addsrcaddrs, "$p\@packages.qa.debian.org";
+       $p =~ /([a-z0-9.+-]+)/;
+       $p = $1;
+       next unless defined $p;
+       if (defined $gSubscriptionDomain) {
+           if (defined($pkgsrc{$p})) {
+               push @addsrcaddrs, "$pkgsrc{$p}\@$gSubscriptionDomain";
+           } else {
+               push @addsrcaddrs, "$p\@$gSubscriptionDomain";
+           }
        }
         if (defined($maintainerof{$p})) {
            print DEBUG "maintainer add >$p|$maintainerof{$p}<\n";
@@ -1018,4 +1155,63 @@ sub checkmaintainers {
             last;
         }
     }
+
+    if (length $data->{owner}) {
+        print DEBUG "owner add >$data->{package}|$data->{owner}<\n";
+        $addmaint = $data->{owner};
+        push(@maintaddrs, $addmaint) unless
+            $addmaint eq $replyto or grep($_ eq $addmaint, @maintaddrs);
+    }
+}
+
+=head2 bug_list_forward
+
+     bug_list_forward($spool_filename) if $codeletter eq 'L';
+
+
+Given the spool file, will forward a bug to the per bug mailing list
+subscription system.
+
+=cut
+
+sub bug_list_forward{
+     my ($bug_fn) = @_;
+     # Read the bug information and package information for passing to
+     # the mailing list
+     my ($bug_number) = $bug_fn =~ /^L(\d+)\./;
+     my ($bfound, $data)= lockreadbugmerge($bug_number);
+     my $bug_fh = new IO::File "incoming/P$bug_fn" or die "Unable to open incoming/P$bug_fn $!";
+
+     local $/ = undef;
+     my $bug_message = <$bug_fh>;
+     my ($bug_address) = $bug_message =~ /^Received: \(at ([^\)]+)\) by/;
+     my ($envelope_from) = $bug_message =~ s/\nFrom\s+([^\s]+)[^\n]+\n/\n/;
+     if (not defined $envelope_from) {
+         # Try to use the From: header or something to set it 
+          ($envelope_from) = $bug_message =~ /\nFrom:\s+(.+?)\n/;
+         # Kludgy, and should really be using a full scale header
+         # parser to do this.
+         $envelope_from =~ s/^.+?<([^>]+)>.+$/$1/;
+     }
+     my ($header,$body) = split /\n\n/, $bug_message, 2;
+     # Add X-$gProject-PR-Message: list bug_number, package name, and bug title headers
+     $header .= qq(\nX-$gProject-PR-Message: list $bug_number\n).
+         qq(X-$gProject-PR-Package: $data->{package}\n).
+              qq(X-$gProject-PR-Title: $data->{subject})
+              if defined $data;
+     print STDERR "Tried to loop me with $envelope_from\n"
+         and exit 1 if $envelope_from =~ /\Q$gListDomain\E|\Q$gEmailDomain\E/;
+     print DEBUG $envelope_from,qq(\n);
+     # If we don't have a bug address, something has gone horribly wrong.
+     print STDERR "Doesn't match: $bug_address\n" and exit 1 unless defined $bug_address;
+     $bug_address =~ s/\@.+//;
+     print DEBUG "Sending message to bugs=$bug_address\@$gListDomain\n";
+     print DEBUG $header.qq(\n\n).$body;
+     send_mail_message(message        => $header.qq(\n\n).$body,
+                      recipients     => ["bugs=$bug_address\@$gListDomain"],
+                      envelope_from  => $envelope_from,
+                      encode_headers => 0,
+                     );
+     unlink("incoming/P$bug_fn") || &quit("unlinking incoming/P$bug_fn: $!");
+     exit 0;
 }