]> git.donarmstrong.com Git - debbugs.git/blobdiff - scripts/process.in
[project @ 2003-08-20 23:33:54 by cjwatson]
[debbugs.git] / scripts / process.in
index cdf30c5c0ffae7b0eded9a5c21000c80ce55c33f..d5b2cf57861cc03b07cda84b35a78a79beb1eb58 100755 (executable)
@@ -1,13 +1,23 @@
 #!/usr/bin/perl
-# $Id: process.in,v 1.34 2001/08/16 07:07:53 doogie Exp $
+# $Id: process.in,v 1.79 2003/08/20 23:33:54 cjwatson Exp $
 #
 # Usage: process nn
 # Temps:  incoming/Pnn
 
-use Mail::Address;
-require( '/etc/debbugs/config' );
-require( '/usr/lib/debbugs/errorlib' );
-chdir( "$gSpoolDir" ) || die 'chdir spool: $!\n';
+use POSIX qw(strftime tzset);
+$ENV{"TZ"} = 'UTC';
+tzset();
+
+use MIME::Parser;
+
+$config_path = '/etc/debbugs';
+$lib_path = '/usr/lib/debbugs';
+
+require "$config_path/config";
+require "$lib_path/errorlib";
+$ENV{'PATH'} = $lib_path.':'.$ENV{'PATH'};
+
+chdir( "$gSpoolDir" ) || die "chdir spool: $!\n";
 
 #open(DEBUG,"> /tmp/debbugs.debug");
 umask(002);
@@ -22,9 +32,10 @@ $tryref= length($2) ? $2+0 : -1;
 $nn= $_;
 
 if (!rename("incoming/G$nn","incoming/P$nn")) 
-{      $_=$!.'';  m/no such file or directory/i && exit 0;
+{
+    $_=$!.'';  m/no such file or directory/i && exit 0;
     &quit("renaming to lock: $!");
-}    
+}
 
 $baddress= 'submit' if $codeletter eq 'B';
 $baddress= 'maintonly' if $codeletter eq 'M';
@@ -41,68 +52,95 @@ open(M,"incoming/P$nn");
 close(M);
 
 @msg=@log;
-grep(s/\n+$//,@msg);
+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;
-X-Loop: $gMaintainerEmail
 Received: via spool by $baddress\@$gEmailDomain id=$nn
           (code $codeletter ref $tryref); $tdate
 END
 
-# Process the message's mail headers
-for ($i=0; $i<=$#msg; $i++) {
-    $_ = $msg[$i];
-    last unless length($_);
-    &quit("looping detected") if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
-    $ins= !m/^subject:/i && !m/^reply-to:/i && !m/^return-path:/i
-       && !m/^From / && !m/^X-Debbugs-CC:/i && !m/^received:/i;
-    $fwd .= $_."\n" if $ins;
-    while ($msg[$i+1] =~ m/^\s/) {
-        $i++;
-        $fwd .= $msg[$i]."\n" if $ins;
-        $_ .= ' '.$msg[$i];
+# header and decoded body respectively
+my (@headerlines, @bodylines);
+
+my $parser = new MIME::Parser;
+mkdir "$gSpoolDir/mime.tmp", 0777;
+$parser->output_under("$gSpoolDir/mime.tmp");
+my $entity = eval { $parser->parse_data(join('',@log)) };
+
+if ($entity and $entity->head->tags) {
+    @headerlines = @{$entity->head->header};
+    chomp @headerlines;
+
+    my $entity_body = getmailbody($entity);
+    @bodylines = $entity_body ? $entity_body->as_lines() : ();
+    chomp @bodylines;
+
+    # set $i to beginning of encoded body data, so we can dump it out
+    # verbatim later
+    $i = 0;
+    ++$i while $msg[$i] =~ /./;
+} else {
+    # Legacy pre-MIME code, kept around in case MIME::Parser fails.
+    for ($i = 0; $i <= $#msg; $i++) {
+       $_ = $msg[$i];
+       last unless length($_);
+       while ($msg[$i+1] =~ m/^\s/) {
+           $i++;
+           $_ .= "\n".$msg[$i];
+       }
+       push @headerlines, $_;
     }
-# print DEBUG ">$_<\n";
+
+    @bodylines = @msg[$i..$#msg];
+}
+
+for my $hdr (@headerlines) {
+    $_ = $hdr;
+    s/\n\s/ /g;
+    &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-/i;
+    $fwd .= $hdr."\n" if $ins;
+    # print DEBUG ">$_<\n";
     if (s/^(\S+):\s*//) {
-        $v= $1; $v =~ y/A-Z/a-z/;
-               print DEBUG ">$v=$_<\n";
-        $header{$v}= $_;
+       my $v = lc $1;
+       print DEBUG ">$v=$_<\n";
+       $header{$v} = $_;
     } else {
        print DEBUG "!>$_<\n";
     }
 }
 
-#remove blank lines
-while ($i <= $#msg && !length($msg[$i])) { $fwd .= "\n"; $i++; }
-
-#skips the "this is mime" message and any blank space after it
-if ( $msg[$i] =~ /^This is a multi-part message in MIME format./ )
-{
-       while ( $i <= $#msg && length( $msg[$i] ) ) { $fwd .= $msg[$i] . "\n"; $i++; }
-       while ( $i <= $#msg && !length( $msg[$i] ) ) { $fwd .= "\n"; $i++; }
+# remove blank lines
+shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
+
+# Strip off RFC2440-style PGP clearsigning.
+if (@bodylines and $bodylines[0] =~ /^-----BEGIN PGP SIGNED/) {
+    shift @bodylines while @bodylines and length $bodylines[0];
+    shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
+    for my $findsig (0 .. $#bodylines) {
+       if ($bodylines[$findsig] =~ /^-----BEGIN PGP SIGNATURE/) {
+           $#bodylines = $findsig - 1;
+           last;
+       }
+    }
+    map { s/^- // } @bodylines;
 }
-#if the lines starts with -- or is nothing but blank space...
-#skip to the next blank line(s) then skip past the blank line(s)
-if ( $msg[$i] =~ /^--/ || $msg[$i] =~ /^\s*$/ )
-{
-       while ( $i <= $#msg && length( $msg[$i] ) ) { $fwd .= $msg[$i] . "\n"; $i++; }
-       while ( $i <= $#msg && !length( $msg[$i] ) ) { $fwd .= "\n"; $i++; }
-}              
 
-while (defined ($msg[$i] ) )
+# extract pseudo-headers
+for my $phline (@bodylines)
 {
-       last if ( $msg[$i] !~ m/^([\w]+):\s*(\S.*)/ );
-       $i++;
-       $fn = $1; $fv = $2;
-       print DEBUG ">$fn|$'|\n";
-    $fwd .= $fn.': '.$fv."\n";
-    $fn =~ y/A-Z/a-z/;
-    $fv =~ y/A-Z/a-z/;
-    $pheader{$fn}= $fv;
-       print DEBUG ">$fn~$fv<\n";
+    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;
+    $pheader{$fn} = $fv;
+    print DEBUG ">$fn~$fv<\n";
 }
 
 
@@ -122,44 +160,58 @@ $replytocompare= $_;
 print DEBUG "replytocompare >$replytocompare<\n";
     
 if (!defined($header{'subject'})) 
-{      $brokenness.= <<END;
+{
+       $brokenness.= <<END;
 
-Your message did not contain a Subject field.  This is broken, I am
-afraid - the Subject: line is a Required Header according to RFC822.
+Your message did not contain a Subject field. They are recommended and
+useful because the title of a $gBug is determined using this field.
 Please remember to include a Subject field in your messages in future.
-If you did so the fact that it got lost probably indicates a poorly
-configured mail system at your site or an intervening one.
 END
+
+# RFC822 actually lists it as an `optional-field'.
+
     $subject= '(no subject)';
-} else { $subject= $header{'subject'}; }
+} else { 
+    $subject= $header{'subject'}; 
+}
 
 $ref=-1;
 $subject =~ s/^Re:\s*//i; $_= $subject."\n";
-if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) { $tryref= $1+0; }
+if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) {
+    $tryref= $1+0; 
+}
 
 if ($tryref >= 0) 
-{      $bfound= &lockreadbugmerge($tryref);
-    if ($bfound) { $ref= $tryref; } 
-       else 
-       {       &htmllog("Reply","sent", $replyto,"Unknown problem report number <code>$tryref</code>.");
+{
+    ($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 expunged, 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.
@@ -177,36 +229,49 @@ talking about this indicates a serious mail system misconfiguration
 somewhere.  Please contact me immediately.)
 
 END
-               &appendlog;
+        &appendlog;
         &finish;
     }
-} else { &filelock('lock/-1'); }
+} else { 
+    &filelock('lock/-1'); 
+}
 
 if ($codeletter eq 'D' || $codeletter eq 'F') 
-{      if ($replyto =~ m/$gBounceFroms/o ||
-               $header{'from'} =~ m/$gBounceFroms/o) 
-               { &quit("bounce detected !  Mwaap! Mwaap!"); }
+{
+    if ($replyto =~ m/$gBounceFroms/o ||
+        $header{'from'} =~ m/$gBounceFroms/o)
+    { 
+        &quit("bounce detected !  Mwaap! Mwaap!"); 
+    }
     $markedby= $header{'from'} eq $replyto ? $replyto :
                "$header{'from'} (reply to $replyto)";
-    if ($codeletter eq 'F') 
-       {       (&appendlog,&finish) if length($s_forwarded);
+    if ($codeletter eq 'F') {
+        (&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"; } 
-               else { $generalcc=''; }
-    } else 
-       {       (&appendlog,&finish) if length($s_done);
+       if ( length( $gListDomain ) > 0 && length( $gFowardList ) > 0 ) {
+           $generalcc= "$gFowardList\@$gListDomain";
+       } else { 
+           $generalcc=''; 
+        }
+    } else {
+       (&appendlog,&finish) if length($data->{done});
         $receivedat= "done\@$gEmailDomain";
         $markaswhat= 'done';
         $set_done= $header{'from'};
-               if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) 
-                       { $generalcc= "$gDoneList\@$gListDomain"; } 
-               else { $generalcc=''; }
+       if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) {
+            $generalcc= "$gDoneList\@$gListDomain";
+       } else { 
+           $generalcc=''; 
+       }
+    }
+    if (grep { $_ eq $data->{severity} } @strongseverities and
+            defined $gStrongList) {
+        $generalcc = join ', ', $generalcc, "$gStrongList\@$gListDomain";
     }
-    if ($ref<0) 
-       {       &htmllog("Warning","sent",$replyto,"Message ignored.");
+    if ($ref<0) {
+       &htmllog("Warning","sent",$replyto,"Message ignored.");
         &sendmessage(<<END, '');
 From: $gMaintainerEmail ($gProject $gBug Tracking System)
 To: $replyto
@@ -214,7 +279,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
@@ -245,48 +311,64 @@ $gMaintainer
 (administrator, $gProject $gBugs database)
 
 END
-               &appendlog;
-               &finish;
+       &appendlog;
+       &finish;
     }
+
     &checkmaintainers;
+
     $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs));
-    $noticeccval =~ s/\s+\n\s+/ /g; $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
+    $noticeccval =~ s/\s+\n\s+/ /g; 
+    $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
+
+    $generalcc = join(', ', $generalcc, @addsrcaddrs);
+    $generalcc =~ s/\s+\n\s+/ /g; 
+    $generalcc =~ s/^\s+/ /; $generalcc =~ s/\s+$//;
+
     if (length($noticeccval)) { $noticecc= "Cc: $noticeccval\n"; }
-       if (length($generalcc)) { $noticecc.= "Bcc: $generalcc\n"; }
-    @process= ($ref,split(/ /,$s_mergedwith));
+    if (length($generalcc)) { $noticecc.= "Bcc: $generalcc\n"; }
+
+    @process= ($ref,split(/ /,$data->{mergedwith}));
     $orgref= $ref;
-    for $ref (@process) 
-       {       if ($ref != $orgref) 
-               {       &unfilelock;
-               &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);
-               &overwrite("db/$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");
-        open(O,"db/$ref.report") || &quit("read original report: $!");
+
+    for $ref (@process) {
+       if ($ref != $orgref) {
+           &unfilelock;
+           $data = &lockreadbug($ref)
+               || die "huh ? $ref from $orgref out of @process";
+       }
+        $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};
+        }
+
+       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, '');
+        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)
+${noticecc}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'} $s_msgid
+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}
 
 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
@@ -296,16 +378,20 @@ $gMaintainer
 (administrator, $gProject $gBugs database)
 
 END
-        } else 
-               {   &htmllog("Reply","sent",$replyto,"You have taken responsibility.");
+
+        } 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)
+${noticecc}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'} $s_msgid
+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}
 
 Your message dated $header{'date'}
 with message-id $header{'message-id'}
@@ -324,43 +410,45 @@ $gMaintainer
 (administrator, $gProject $gBugs database)
 
 END
-            &htmllog("Notification","sent",$s_originator
-                               "$gBug acknowledged by developer.");
+            &htmllog("Notification","sent",$data->{originator}
+               "$gBug acknowledged by developer.");
             &sendmessage(<<END.join("\n",@msg),'');
 From: $gMaintainerEmail ($gProject $gBug Tracking System)
-To: $s_originator
+To: $data->{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
+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
 
 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.
 
 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 directly, or email
-$ref\@$gEmailDomain or me.
+message then please contact the developer, by replying to this email.
 
 $gMaintainer
 (administrator, $gProject $gBugs database)
 
 END
         }
-               &appendlog;
+       &appendlog;
     }
     &finish;
 }
 
-if ($ref<0) 
-{      if ($codeletter eq 'U') 
-       {       &htmllog("Warning","sent",$replyto,"Message not forwarded.");
+if ($ref<0) {
+    if ($codeletter eq 'U') {
+        &htmllog("Warning","sent",$replyto,"Message not forwarded.");
         &sendmessage(<<END, '');
 From: $gMaintainerEmail ($gProject $gBug Tracking System)
 To: $replyto
@@ -368,7 +456,8 @@ 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 
@@ -403,8 +492,8 @@ END
        &appendlog;
        &finish;
     }
-    if (!defined($pheader{'package'}))
-       {       &htmllog("Warning","sent",$replyto,"Message not forwarded.");
+    if (!defined($pheader{'package'})) {
+       &htmllog("Warning","sent",$replyto,"Message not forwarded.");
         &sendmessage(<<END."---------------------------------------------------------------------------\n".join("\n", @msg), '');
 From: $gMaintainerEmail ($gProject $gBug Tracking System)
 To: $replyto
@@ -412,7 +501,8 @@ 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
+References: $header{'message-id'} $data->{msgid}
+Precedence: bulk
 X-$gProject-PR-Message: error
 
 Your message didn't have a Package: line at the start (in the
@@ -420,8 +510,9 @@ pseudo-header following the real mail header), or didn't have a
 pseudo-header at all.
 
 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'}
@@ -436,38 +527,55 @@ $gMaintainer
 END
        &appendlog;
        &finish;
-    } else { $s_package= $pheader{'package'}; }
-    $s_keywords= '';
+    } else {
+       $data->{package}= $pheader{'package'}; 
+    }
+
+    $data->{versions}= '';
+    if (defined($pheader{'version'})) {
+        $data->{versions} = $pheader{'version'};
+        $data->{versions} =~ s/\s+/ /;
+       # BUG: need to bounce unknown versions back to submitter here
+    }
+
+    $data->{fixed_versions}= '';
+    if (defined($pheader{'fixed-in-version'})) {
+        $data->{fixed_versions} = $pheader{'fixed-in-version'};
+        $data->{fixed_versions} =~ s/\s+/ /;
+    }
+
+    $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= '';
-       if (defined($pheader{'severity'}) || defined($pheader{'priority'})) 
-       {       $s_severity= $pheader{'severity'};
-           $s_severity= $pheader{'priority'} unless ($s_severity);
+    $data->{severity}= '';
+    if (defined($pheader{'severity'}) || defined($pheader{'priority'})) {
+       $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}= '';
         }
     }
     &filelock("nextnumber.lock");
@@ -476,14 +584,14 @@ END
     $ref= $v+0;  $v += 1;  $newref=1;
     &overwrite('nextnumber', "$v\n");
     &unfilelock;
-    &overwrite("db/$ref.log",'');
-    &overwrite("db/$ref.status",
-               "$replyto\n$intdate\n$subject\n$header{'message-id'}\n".
-               "$s_package\n$s_keywords\n\n\n\n$s_severity\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");
-    &overwrite("db/$ref.report",
+    my $hash = get_hashname($ref);
+    &overwrite("db-h/$hash/$ref.log",'');
+    $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");
 }
 
@@ -491,8 +599,8 @@ END
 
 print DEBUG "maintainers >@maintaddrs<\n";
 
-$orgsender= defined($header{'sender'}) ? "Orignal-Sender: $header{'sender'}\n" : '';
-$newsubject= $subject;  $newsubject =~ s/^$gBug#$ref\W*\s*//;
+$orgsender= defined($header{'sender'}) ? "Original-Sender: $header{'sender'}\n" : '';
+$newsubject= $subject;  $newsubject =~ s/^$gBug#$ref:*\s*//;
 
 $xcchdr= $header{ 'x-debbugs-cc' };
 if ($xcchdr =~ m/\S/) {
@@ -513,6 +621,12 @@ Your message has been sent to the package maintainer(s):
 END
 }
 
+@bccs = @addsrcaddrs;
+if (grep { $_ eq $data->{severity} } @gStrongSeverities and
+        defined $gStrongList) {
+    push @bccs, "$gStrongList\@$gListDomain";
+}
+
 $veryquiet= $codeletter eq 'Q';
 if ($codeletter eq 'M' && !@maintaddrs) {
     $veryquiet= 1;
@@ -531,29 +645,31 @@ END
 
 $resentccval.= join(', ',@resentccs);
 $resentccval =~ s/\s+\n\s+/ /g; $resentccval =~ s/^\s+/ /; $resentccval =~ s/\s+$//;
-if (length($resentccval)) { $resentcc= "Resent-CC: $resentccval\n"; }
+if (length($resentccval)) { 
+    $resentcc= "Resent-CC: $resentccval\n"; 
+}
 
 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'}
@@ -562,20 +678,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'}
@@ -584,8 +708,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
 }
@@ -593,16 +717,16 @@ END
 $htmlbreak= length($brokenness) ? "<p>\n".&sani($brokenness)."\n<p>\n" : '';
 $htmlbreak =~ s/\n\n/\n<P>\n\n/g;
 if (length($resentccval)) {
-    $htmlbreak =
-        "  Copy sent to <code>".&sani($resentccval)."</code>.".
+    $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,'');
+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);
+        &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
 From: $gMaintainerEmail ($gProject $gBug Tracking System)
 To: $replyto
 Subject: $gBug#$ref: Acknowledgement of QUIET report
@@ -610,14 +734,18 @@ Subject: $gBug#$ref: Acknowledgement of QUIET report
 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
 
 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*
@@ -636,12 +764,17 @@ Subject: $gBug#$ref: Acknowledgement of maintainer-only report
 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
 
 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*
@@ -659,12 +792,16 @@ 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
 
 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
@@ -676,12 +813,13 @@ $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,'');
+    } elsif ($codeletter ne 'U' and
+             $header{'precedence'} !~ /\b(?:bulk|junk|list)\b/) {
+        &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
@@ -689,13 +827,17 @@ Subject: $gBug#$ref: Info received and FILED only
 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-quiet\@$gEmailDomain
 
 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.
@@ -713,11 +855,15 @@ Subject: $gBug#$ref: Info received for maintainer only
 Message-ID: <handler.$ref.$nn.ackinfomaint\@$gEmailDomain>
 In-Reply-To: $header{'message-id'}
 References: $header{'message-id'}
-X-$gProject-PR-Message: ack-info $ref
+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
 
 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.
@@ -734,11 +880,14 @@ 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-maintonly $ref
+Precedence: bulk
+X-$gProject-PR-Message: ack-info $ref
+X-$gProject-PR-Package: $data->{package}
+X-$gProject-PR-Keywords: $data->{keywords}
 
 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.
@@ -749,6 +898,10 @@ $brokenness
 $gMaintainer
 (administrator, $gProject $gBugs database)
 END
+# Reply-To: in previous ack disabled by doogie due to mail loops.
+# Are these still a concern?
+# Reply-To: $ref\@$gEmailDomain
+    }
 }
 
 &appendlog;
@@ -763,13 +916,14 @@ sub overwrite {
 }
 
 sub appendlog {
-    if (!open(AP,">>db/$ref.log")) {
+    my $hash = get_hashname($ref);
+    if (!open(AP,">>db-h/$hash/$ref.log")) {
         print DEBUG "failed open log<\n";
         print DEBUG "failed open log err $!<\n";
-        &quit("opening db/$ref.log (li): $!");
+        &quit("opening db-h/$hash/$ref.log (li): $!");
     }
-    print(AP "\7\n",@log,"\n\3\n") || &quit("writing db/$ref.log (li): $!");
-    close(AP) || &quit("closing db/$ref.log (li): $!");
+    print(AP "\7\n",@{escapelog(@log)},"\n\3\n") || &quit("writing db-h/$hash/$ref.log (li): $!");
+    close(AP) || &quit("closing db-h/$hash/$ref.log (li): $!");
 }
 
 sub finish {
@@ -786,98 +940,127 @@ sub chldhandle { $chldexit = 'yes'; }
 
 sub htmllog {
     local ($whatobj,$whatverb,$where,$desc) = @_;
-    open(AP,">>db/$ref.log") || &quit("opening db/$ref.log (lh): $!");
+    my $hash = get_hashname($ref);
+    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.
-          "\n\3\n") || &quit("writing db/$ref.log (lh): $!");
-    close(AP) || &quit("closing db/$ref.log (lh): $!");
+          "<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;
 }
 
-
 sub sendmessage {
-    local ($msg,@recips) = @_;
-    if ($recips[0] eq '' && $#recips == 0) { @recips= ('-t'); }
-
-       #save email to the log
-    open(AP,">>db/$ref.log") || &quit("opening db/$ref.log (lo): $!");
-    print(AP "\2\n",join("\4",@recips),"\n\5\n$msg\n\3\n") ||
-        &quit("writing db/$ref.log (lo): $!");
-    close(AP) || &quit("closing db/$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
-       $_ = '';
+    local ($msg,$recips,$bcc) = @_;
+    if ((!ref($recips) && $recips eq '') || @$recips == 0) {
+        $recips = ['-t'];
+    }
+    $msg = "X-Loop: $gMaintainerEmail\n" . $msg;
+
+    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(stripbccs($msg))},"\n\3\n") ||
+        &quit("writing db-h/$hash/$ref.log (lo): $!");
+    close(AP) || &quit("closing db-h/$hash/$ref.log (lo): $!");
+
+    if (ref($bcc)) {
+        shift @$recips if $recips->[0] eq '-t';
+        push @$recips, @$bcc;
+    }
+
+#if debugging.. 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';
+    #print DEBUG "mailing sigchild set up<\n";
+    $chldexit = 'no';
     $c= open(U,"-|");
-       #print DEBUG "mailing opened pipe fork<\n";
+    #print DEBUG "mailing opened pipe fork<\n";
     defined($c) || die $!;
-       #print DEBUG "mailing opened pipe fork ok $c<\n";
+    #print DEBUG "mailing opened pipe fork ok $c<\n";
     if (!$c) { # ie, we are in the child process
-               #print DEBUG "mailing child<\n";
+       #print DEBUG "mailing child<\n";
         unless (open(STDERR,">&STDOUT")) {
-                       #print DEBUG "mailing child opened stderr<\n";
+           #print DEBUG "mailing child opened stderr<\n";
             print STDOUT "redirect stderr: $!\n";
-                       #print DEBUG "mailing child opened stderr fail<\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 fail exit !?<\n";
         }
-               #print DEBUG "mailing child opened stderr ok<\n";
+       #print DEBUG "mailing child opened stderr ok<\n";
         $c= open(D,"|-");
-               #print DEBUG "mailing child forked again<\n";
+       #print DEBUG "mailing child forked again<\n";
         defined($c) || die $!;
-               #print DEBUG "mailing child forked again ok $c<\n";
+       #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";
+           #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 grandchild died !?<\n";
         }
-               #print DEBUG "mailing child not grandchild<\n";
+       #print DEBUG "mailing child not grandchild<\n";
         print(D $msg) || die $!;
-               #print DEBUG "mailing child printed msg<\n";
+       #print DEBUG "mailing child printed msg<\n";
         close(D);
-               #print DEBUG "mailing child closed pipe<\n";
+       #print DEBUG "mailing child closed pipe<\n";
         die "\n*** command returned exit status $?\n" if $?;
-               #print DEBUG "mailing child exit status ok<\n";
+       #print DEBUG "mailing child exit status ok<\n";
         exit 0;
-               #print DEBUG "mailing child exited ?!<\n";
+       #print DEBUG "mailing child exited ?!<\n";
     }
-       #print DEBUG "mailing parent<\n";
+    #print DEBUG "mailing parent<\n";
     $results='';
-       #print DEBUG "mailing parent results emptied<\n";
+    #print DEBUG "mailing parent results emptied<\n";
     while( $chldexit eq 'no' ) { $results.= $_; }
-       #print DEBUG "mailing parent results read >$results<\n";
+    #print DEBUG "mailing parent results read >$results<\n";
     close(U);
-       #print DEBUG "mailing parent results closed<\n";
+    #print DEBUG "mailing parent results closed<\n";
     $results.= "\n*** child returned exit status $?\n" if $?;
-       #print DEBUG "mailing parent exit status ok<\n";
+    #print DEBUG "mailing parent exit status ok<\n";
     $SIG{'CHLD'}='DEFAULT';
-       #print DEBUG "mailing parent sigchild default<\n";
+    #print DEBUG "mailing parent sigchild default<\n";
     if (length($results)) { &quit("running sendmail: $results"); }
-       #print DEBUG "mailing parent results ok<\n";
+    #print DEBUG "mailing parent results ok<\n";
 }
 
 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;
@@ -896,17 +1079,32 @@ sub checkmaintainers {
         $maintainerof{$1}= $2;
     }
     close(MAINT);
+    open(SOURCES,"$gPackageSource") || &quit("pkgsrc open: $!");
+    while (<SOURCES>) {
+        next unless m/^(\S+)\s+\S+\s+(\S.*\S)\s*$/;
+       ($a,$b)=($1,$2);
+       $a =~ y/A-Z/a-z/;
+       $pkgsrc{$a} = $b;
+    }
+    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 $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";
+           print DEBUG "maintainer add >$p|$maintainerof{$p}<\n";
             $addmaint= $maintainerof{$p};
             push(@maintaddrs,$addmaint) unless
                 $addmaint eq $replyto || grep($_ eq $addmaint, @maintaddrs);
             $anymaintfound++;
         } else {
-print DEBUG "maintainer none >$p<\n";
+           print DEBUG "maintainer none >$p<\n";
            push(@maintaddrs,$gUnknownMaintainerEmail) unless $anymaintnotfound;
             $anymaintnotfound++;
             last;