Commit 88458a65 authored by dmose%mozilla.org's avatar dmose%mozilla.org

patch from bug 17464 to give user some control over what sorts of bug mail get…

patch from bug 17464 to give user some control over what sorts of bug mail get sent to an account. Original patch by al_raetz@yahoo.com and lots of additional hacking by me; r=donm@bluemartini.com
parent 63ececeb
...@@ -748,6 +748,7 @@ $table{profiles} = ...@@ -748,6 +748,7 @@ $table{profiles} =
newemailtech tinyint not null, newemailtech tinyint not null,
mybugslink tinyint not null default 1, mybugslink tinyint not null default 1,
blessgroupset bigint not null, blessgroupset bigint not null,
emailflags mediumtext,
unique(login_name)'; unique(login_name)';
...@@ -1868,6 +1869,13 @@ unless (-d 'graphs') { ...@@ -1868,6 +1869,13 @@ unless (-d 'graphs') {
} }
} }
#
# 2000-12-18. Added an 'emailflags' field for storing preferences about
# when email gets sent on a per-user basis.
#
if (!GetFieldDef('profiles', 'emailflags')) {
AddField('profiles', 'emailflags', 'mediumtext');
}
# #
# If you had to change the --TABLE-- definition in any way, then add your # If you had to change the --TABLE-- definition in any way, then add your
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
# Contributor(s): Holger Schurig <holgerschurig@nikocity.de> # Contributor(s): Holger Schurig <holgerschurig@nikocity.de>
# Dave Miller <dave@intrec.com> # Dave Miller <dave@intrec.com>
# Joe Robins <jmrobins@tgix.com> # Joe Robins <jmrobins@tgix.com>
# Dan Mosedale <dmose@mozilla.org>
# #
# Direct any questions on this source code to # Direct any questions on this source code to
# #
...@@ -38,6 +39,7 @@ require "globals.pl"; ...@@ -38,6 +39,7 @@ require "globals.pl";
sub sillyness { sub sillyness {
my $zz; my $zz;
$zz = $::userid; $zz = $::userid;
$zz = $::superusergroupset;
} }
my $editall; my $editall;
...@@ -95,10 +97,10 @@ sub EmitElement ($$) ...@@ -95,10 +97,10 @@ sub EmitElement ($$)
# Displays the form to edit a user parameters # Displays the form to edit a user parameters
# #
sub EmitFormElements ($$$$$$$) sub EmitFormElements ($$$$$$$$)
{ {
my ($user, $password, $realname, $groupset, $blessgroupset, my ($user, $password, $realname, $groupset, $blessgroupset,
$emailnotification, $disabledtext) = @_; $emailnotification, $disabledtext, $newemailtech) = @_;
print " <TH ALIGN=\"right\">Login name:</TH>\n"; print " <TH ALIGN=\"right\">Login name:</TH>\n";
EmitElement("user", $user); EmitElement("user", $user);
...@@ -116,20 +118,26 @@ sub EmitFormElements ($$$$$$$) ...@@ -116,20 +118,26 @@ sub EmitFormElements ($$$$$$$)
print " <TD><INPUT TYPE=\"PASSWORD\" SIZE=16 MAXLENGTH=16 NAME=\"password\" VALUE=\"$password\"></TD>\n"; print " <TD><INPUT TYPE=\"PASSWORD\" SIZE=16 MAXLENGTH=16 NAME=\"password\" VALUE=\"$password\"></TD>\n";
} }
print "</TR><TR>\n"; print "</TR><TR>\n";
print " <TH ALIGN=\"right\">Email notification:</TH>\n";
print qq{<TD><SELECT NAME="emailnotification">}; if (!$newemailtech) {
foreach my $i (["ExcludeSelfChanges", "All qualifying bugs except those which I change"], print " <TH ALIGN=\"right\">Email notification:</TH>\n";
["CConly", "Only those bugs which I am listed on the CC line"], print qq{<TD><SELECT NAME="emailnotification">};
["All", "All qualifying bugs"]) { foreach my $i (["ExcludeSelfChanges",
my ($tag, $desc) = (@$i); "All qualifying bugs except those which I change"],
my $selectpart = ""; ["CConly",
if ($tag eq $emailnotification) { "Only those bugs which I am listed on the CC line"],
$selectpart = " SELECTED"; ["All", "All qualifying bugs"]) {
my ($tag, $desc) = (@$i);
my $selectpart = "";
if ($tag eq $emailnotification) {
$selectpart = " SELECTED";
}
print qq{<OPTION$selectpart VALUE="$tag">$desc\n};
} }
print qq{<OPTION$selectpart VALUE="$tag">$desc\n}; print "</SELECT></TD>\n";
print "</TR><TR>\n";
} }
print "</SELECT></TD>\n";
print "</TR><TR>\n";
print " <TH ALIGN=\"right\">Disable text:</TH>\n"; print " <TH ALIGN=\"right\">Disable text:</TH>\n";
print " <TD ROWSPAN=2><TEXTAREA NAME=\"disabledtext\" ROWS=10 COLS=60>" . print " <TD ROWSPAN=2><TEXTAREA NAME=\"disabledtext\" ROWS=10 COLS=60>" .
value_quote($disabledtext) . "</TEXTAREA>\n"; value_quote($disabledtext) . "</TEXTAREA>\n";
...@@ -389,7 +397,7 @@ if ($action eq 'add') { ...@@ -389,7 +397,7 @@ if ($action eq 'add') {
print "<FORM METHOD=POST ACTION=editusers.cgi>\n"; print "<FORM METHOD=POST ACTION=editusers.cgi>\n";
print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n"; print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n";
EmitFormElements('', '', '', 0, 0, 'ExcludeSelfChanges', ''); EmitFormElements('', '', '', 0, 0, 'ExcludeSelfChanges', '', 1);
print "</TR></TABLE>\n<HR>\n"; print "</TR></TABLE>\n<HR>\n";
print "<INPUT TYPE=SUBMIT VALUE=\"Add\">\n"; print "<INPUT TYPE=SUBMIT VALUE=\"Add\">\n";
...@@ -507,10 +515,11 @@ if ($action eq 'del') { ...@@ -507,10 +515,11 @@ if ($action eq 'del') {
CheckUser($user); CheckUser($user);
# display some data about the user # display some data about the user
SendSQL("SELECT realname, groupset, emailnotification SendSQL("SELECT realname, groupset, emailnotification, newemailtech
FROM profiles FROM profiles
WHERE login_name=" . SqlQuote($user)); WHERE login_name=" . SqlQuote($user));
my ($realname, $groupset, $emailnotification) = FetchSQLData(); my ($realname, $groupset, $emailnotification, $newemailtech) =
FetchSQLData();
$realname ||= "<FONT COLOR=\"red\">missing</FONT>"; $realname ||= "<FONT COLOR=\"red\">missing</FONT>";
print "<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0>\n"; print "<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0>\n";
...@@ -526,9 +535,11 @@ if ($action eq 'del') { ...@@ -526,9 +535,11 @@ if ($action eq 'del') {
print " <TD VALIGN=\"top\">Real name:</TD>\n"; print " <TD VALIGN=\"top\">Real name:</TD>\n";
print " <TD VALIGN=\"top\">$realname</TD>\n"; print " <TD VALIGN=\"top\">$realname</TD>\n";
print "</TR><TR>\n"; if ( !$newemailtech ) {
print " <TD VALIGN=\"top\">E-Mail notification:</TD>\n"; print "</TR><TR>\n";
print " <TD VALIGN=\"top\">$emailnotification</TD>\n"; print " <TD VALIGN=\"top\">E-Mail notification:</TD>\n";
print " <TD VALIGN=\"top\">$emailnotification</TD>\n";
}
print "</TR><TR>\n"; print "</TR><TR>\n";
print " <TD VALIGN=\"top\">Group set:</TD>\n"; print " <TD VALIGN=\"top\">Group set:</TD>\n";
...@@ -670,17 +681,17 @@ if ($action eq 'edit') { ...@@ -670,17 +681,17 @@ if ($action eq 'edit') {
# get data of user # get data of user
SendSQL("SELECT password, realname, groupset, blessgroupset, SendSQL("SELECT password, realname, groupset, blessgroupset,
emailnotification, disabledtext emailnotification, disabledtext, newemailtech
FROM profiles FROM profiles
WHERE login_name=" . SqlQuote($user)); WHERE login_name=" . SqlQuote($user));
my ($password, $realname, $groupset, $blessgroupset, $emailnotification, my ($password, $realname, $groupset, $blessgroupset, $emailnotification,
$disabledtext) = FetchSQLData(); $disabledtext, $newemailtech) = FetchSQLData();
print "<FORM METHOD=POST ACTION=editusers.cgi>\n"; print "<FORM METHOD=POST ACTION=editusers.cgi>\n";
print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n"; print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n";
EmitFormElements($user, $password, $realname, $groupset, $blessgroupset, EmitFormElements($user, $password, $realname, $groupset, $blessgroupset,
$emailnotification, $disabledtext); $emailnotification, $disabledtext, $newemailtech);
print "</TR></TABLE>\n"; print "</TR></TABLE>\n";
...@@ -691,7 +702,10 @@ if ($action eq 'edit') { ...@@ -691,7 +702,10 @@ if ($action eq 'edit') {
print "<INPUT TYPE=HIDDEN NAME=\"realnameold\" VALUE=\"$realname\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"realnameold\" VALUE=\"$realname\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"groupsetold\" VALUE=\"$groupset\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"groupsetold\" VALUE=\"$groupset\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"blessgroupsetold\" VALUE=\"$blessgroupset\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"blessgroupsetold\" VALUE=\"$blessgroupset\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"emailnotificationold\" VALUE=\"$emailnotification\">\n"; if (!$newemailtech) {
print "<INPUT TYPE=HIDDEN NAME=\"emailnotificationold\" " .
"VALUE=\"$emailnotification\">\n";
}
print "<INPUT TYPE=HIDDEN NAME=\"disabledtextold\" VALUE=\"" . print "<INPUT TYPE=HIDDEN NAME=\"disabledtextold\" VALUE=\"" .
value_quote($disabledtext) . "\">\n"; value_quote($disabledtext) . "\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"update\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"update\">\n";
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
# Contributor(s): Terry Weissman <terry@mozilla.org>, # Contributor(s): Terry Weissman <terry@mozilla.org>,
# Bryce Nesbitt <bryce-mozilla@nextbus.com> # Bryce Nesbitt <bryce-mozilla@nextbus.com>
# Dan Mosedale <dmose@mozilla.org> # Dan Mosedale <dmose@mozilla.org>
# Alan Raetz <al_raetz@yahoo.com>
#
# To recreate the shadow database, run "processmail regenerate" . # To recreate the shadow database, run "processmail regenerate" .
...@@ -39,6 +41,11 @@ $::lockcount = 0; ...@@ -39,6 +41,11 @@ $::lockcount = 0;
my $regenerate = 0; my $regenerate = 0;
my $nametoexclude = ""; my $nametoexclude = "";
my @excludedAddresses = ();
# disable email flag for offline debugging work
my $enableSendMail = 1;
my @forcecc; my @forcecc;
sub Lock { sub Lock {
...@@ -267,7 +274,6 @@ $::bug{'long_desc'} ...@@ -267,7 +274,6 @@ $::bug{'long_desc'}
} }
my $didexclude = 0;
my %seen; my %seen;
my @sentlist; my @sentlist;
sub fixaddresses { sub fixaddresses {
...@@ -290,7 +296,7 @@ sub fixaddresses { ...@@ -290,7 +296,7 @@ sub fixaddresses {
} }
if ($emailnotification eq "ExcludeSelfChanges" && if ($emailnotification eq "ExcludeSelfChanges" &&
(lc($i) eq $nametoexclude)) { (lc($i) eq $nametoexclude)) {
$didexclude = 1; push @excludedAddresses, $nametoexclude;
next; next;
} }
...@@ -462,6 +468,86 @@ sub NewProcessOneBug { ...@@ -462,6 +468,86 @@ sub NewProcessOneBug {
my $newcomments = GetLongDescriptionAsText($id, $start, $end); my $newcomments = GetLongDescriptionAsText($id, $start, $end);
if (Param('newemailtech')) {
#
# Start of email filtering code
#
# Even if the user sending the email has not enabled #
# 'newEmailTech', we still want to filter the email
# based on other user's email preferences if the global Param
# 'newemailtech' is enabled.
#
# Note: users who have not enabled newEmailTech will default
# to no filtering (they will get all email Bugzilla sends).
my $count = 0;
my @currentEmailAttributes = getEmailAttributes($newcomments,
@diffs);
my (@assigned_toList,@reporterList,@qa_contactList,@ccList) =
();
#open(LOG, ">>/tmp/maillog");
#print LOG "\nBug ID: $id CurrentEmailAttributes:";
#print LOG join(',', @currentEmailAttributes) . "\n";
@excludedAddresses = (); # zero out global list
@assigned_toList = filterEmailGroup('Owner',
\@currentEmailAttributes,
$values{'assigned_to'});
@reporterList = filterEmailGroup('Reporter',
\@currentEmailAttributes,
$values{'reporter'});
if (Param('useqacontact') && $values{'qa_contact'}) {
@qa_contactList = filterEmailGroup('QAcontact',
\@currentEmailAttributes,
$values{'qa_contact'});
} else {
@qa_contactList = ();
}
@ccList = filterEmailGroup('CClist', \@currentEmailAttributes,
$values{'cc'});
my @emailList = (@assigned_toList, @reporterList,
@qa_contactList, @ccList);
# only need one entry per person
my @allEmail = ();
my %AlreadySeen = ();
foreach my $person (@emailList) {
if ( !($AlreadySeen{$person}) ) {
push(@allEmail,$person);
$AlreadySeen{$person}++;
}
}
#print LOG "\nbug $id email sent: " . join(',', @allEmail) . "\n";
@excludedAddresses = filterExcludeList(\@excludedAddresses,
\@allEmail);
# print LOG "excluded: " . join(',',@excludedAddresses) . "\n\n";
foreach my $person ( @allEmail ) {
$count++;
if ( !defined(NewProcessOnePerson($person, $count, \@headerlist,
\%values, \%defmailhead,
\%fielddescription, $difftext,
$newcomments, $start, $id, 1))) {
# if a value is not returned, this means that the person
# was not sent mail. add them to the excludedAddresses list.
# it will be filtered later for dups.
#
push @excludedAddresses, $person;
}
}
} else {
my $count = 0; my $count = 0;
my @personlist = ($values{'assigned_to'}, $values{'reporter'}, my @personlist = ($values{'assigned_to'}, $values{'reporter'},
split(/,/, $values{'cc'}), split(/,/, $values{'cc'}),
...@@ -476,16 +562,252 @@ sub NewProcessOneBug { ...@@ -476,16 +562,252 @@ sub NewProcessOneBug {
$person = $person . Param('emailsuffix'); $person = $person . Param('emailsuffix');
} }
&NewProcessOnePerson($person, $count, \@headerlist, \%values, if ( !defined(NewProcessOnePerson($person, $count, \@headerlist,
\%defmailhead, \%fielddescription, $difftext, \%values, \%defmailhead,
$newcomments, $start, $id, 1); \%fielddescription, $difftext,
$newcomments, $start, $id, 1))) {
# if a value is not returned, this means that the person
# was not sent mail. add them to the excludedAddresses list.
# it will be filtered later for dups.
#
push @excludedAddresses, $person;
}
}
} }
SendSQL("UPDATE bugs SET lastdiffed = '$end', delta_ts = delta_ts " . SendSQL("UPDATE bugs SET lastdiffed = '$end', delta_ts = delta_ts " .
"WHERE bug_id = $id"); "WHERE bug_id = $id");
} }
sub NewProcessOnePerson ($$\@\%\%\%$$$$) { # When one person is in different fields on one bug, they may be
# excluded from email because of one relationship to the bug (eg
# they're the QA contact) but included because of another (eg they
# also reported the bug). Inclusion takes precedence, so this
# function looks for and removes any users from the exclude list who
# are also on the include list. Additionally, it removes duplicate
# entries from the exclude list.
#
# Arguments are the exclude list and the include list; the cleaned up
# exclude list is returned.
#
sub filterExcludeList ($$) {
if ($#_ != 1) {
die ("filterExcludeList called with wrong number of args");
}
my ($refExcluded, $refAll) = @_;
my @excludedAddrs = @$refExcluded;
my @allEmail = @$refAll;
my @tmpList = @excludedAddrs;
my (@result,@uniqueResult) = ();
my %alreadySeen;
foreach my $excluded (@tmpList) {
push (@result,$excluded);
foreach my $included (@allEmail) {
# match found, so we remove the entry
if ($included eq $excluded) {
pop(@result);
}
}
}
# only need one entry per person
foreach my $person (@result) {
if ( !($alreadySeen{$person}) ) {
push(@uniqueResult,$person);
$alreadySeen{$person}++;
}
}
return @uniqueResult;
}
# if the Status was changed to Resolved or Verified
# set the Resolved flag
#
# else if Severity, Status OR Priority fields have any change
# set the Status flag
#
# else if Keywords has changed
# set the Keywords flag
#
# else if CC has changed
# set the CC flag
#
# if the Comments field shows an attachment
# set the Attachment flag
#
# else if Comments exist
# set the Comments flag
#
# if no flags are set and there was some other field change
# set the Status flag
#
sub getEmailAttributes ($@) {
my ($commentField,@fieldDiffs) = @_;
my (@flags,@uniqueFlags,%alreadySeen) = ();
my $Status = 0;
foreach my $ref (@fieldDiffs) {
my ($who, $fieldName, $when, $old, $new) = (@$ref);
#print qq{field: $fieldName $new<br>};
# the STATUS will be flagged for Severity, Status and
# Priority changes
#
if ( $fieldName eq 'Status') {
if ($new eq 'RESOLVED' || $new eq 'VERIFIED') {
push (@flags, 'Resolved');
}
$Status = 1;
}
elsif ( $fieldName eq 'Severity' || $fieldName eq 'Status' ||
$fieldName eq 'Priority' ) {
push (@flags, 'Status');
} elsif ( $fieldName eq 'Keywords') {
push (@flags, 'Keywords');
} elsif ( $fieldName eq 'CC') {
push (@flags, 'CC');
}
}
if ( $commentField =~ /Created an attachment \(/ ) {
push (@flags, 'Attachments');
}
elsif ( $commentField ne '' && !($Status)) {
push (@flags, 'Comments');
}
# default fallthrough for any unflagged change is 'Other'
if ( @flags == 0 && @fieldDiffs != 0 ) {
push (@flags, 'Other');
}
# only need one flag per attribute type
foreach my $flag (@flags) {
if ( !($alreadySeen{$flag}) ) {
push(@uniqueFlags,$flag);
$alreadySeen{$flag}++;
}
}
#print "\nEmail Attributes: ", join(' ,',@uniqueFlags), "<br>\n";
# catch-all default, just in case the above logic is faulty
if ( @uniqueFlags == 0) {
push (@uniqueFlags, 'Comments');
}
return @uniqueFlags;
}
sub filterEmailGroup ($$$) {
my ($emailGroup,$refAttributes,$emailList) = @_;
my @emailAttributes = @$refAttributes;
my @emailList = split(/,/,$emailList);
my @filteredList = ();
foreach my $person (@emailList) {
my $userid;
my $lastCount = @filteredList;
if ( $person eq '' ) { next; }
SendSQL("SELECT userid FROM profiles WHERE login_name = "
. SqlQuote($person) );
if ( !($userid = FetchSQLData()) ) {
push(@filteredList,$person);
next;
}
SendSQL("SELECT emailflags, newemailtech FROM profiles WHERE " .
"userid = $userid" );
my ($userFlagString, $newemailtech) = FetchSQLData();
# people who are not using newemailtech get skipped; they will
# be dealt with later by the old email tech code in
# ProcessOneBug().
#
if (!defined($newemailtech) || $newemailtech == 0) {
next;
}
# If the sender doesn't want email, exclude them from list
if (lc($person) eq $nametoexclude) {
if ( defined ($userFlagString) &&
$userFlagString =~ /ExcludeSelf\~on/ ) {
push (@excludedAddresses,$person);
next;
}
}
# if the users database entry is empty, send them all email
# by default (they have not accessed userprefs.cgi recently).
if ( !defined($userFlagString) || !($userFlagString =~ /email/) ) {
push(@filteredList,$person);
}
else {
# The default condition is to send each person email.
# If we match the email attribute with the user flag, and
# they do not want email, then remove them from the list.
push(@filteredList,$person);
foreach my $attribute (@emailAttributes) {
my $matchName = 'email' . $emailGroup . $attribute;
# the 255 param is here, because without a third param,
# split will trim any trailing null fields, which causes perl
# to eject lots of warnings. any suitably large number would
# do.
my %userFlags = split(/~/, $userFlagString, 255);
while ((my $flagName, my $flagValue) = each %userFlags) {
if ($flagName !~ /$emailGroup/) { next; }
if ( $flagName eq $matchName
&& $flagValue ne 'on') {
pop(@filteredList);
}
} # for each userFlag
} # for each email attribute
} # if $userFlagString is valid
# If email was not sent to the person, then put on excluded
# addresses list.
if (@filteredList == $lastCount) {
push (@excludedAddresses,$person);
}
} # for each person
return @filteredList;
}
sub NewProcessOnePerson ($$$$$$$$$$$) {
my ($person, $count, $hlRef, $valueRef, $dmhRef, $fdRef, $difftext, my ($person, $count, $hlRef, $valueRef, $dmhRef, $fdRef, $difftext,
$newcomments, $start, $id, $checkWatchers) = @_; $newcomments, $start, $id, $checkWatchers) = @_;
...@@ -542,7 +864,7 @@ sub NewProcessOnePerson ($$\@\%\%\%$$$$) { ...@@ -542,7 +864,7 @@ sub NewProcessOnePerson ($$\@\%\%\%$$$$) {
} }
if ($emailnotification eq "ExcludeSelfChanges" && if ($emailnotification eq "ExcludeSelfChanges" &&
lc($person) eq $nametoexclude) { lc($person) eq $nametoexclude) {
$didexclude = 1; push @excludedAddresses, $nametoexclude;
return; return;
} }
# "$count < 3" means "this person is either assigned_to or reporter" # "$count < 3" means "this person is either assigned_to or reporter"
...@@ -601,19 +923,36 @@ sub NewProcessOnePerson ($$\@\%\%\%$$$$) { ...@@ -601,19 +923,36 @@ sub NewProcessOnePerson ($$\@\%\%\%$$$$) {
if (Param("sendmailnow")) { if (Param("sendmailnow")) {
$sendmailparam = ""; $sendmailparam = "";
} }
if ($enableSendMail == 1) {
open(SENDMAIL, "|/usr/lib/sendmail $sendmailparam -t") || open(SENDMAIL, "|/usr/lib/sendmail $sendmailparam -t") ||
die "Can't open sendmail"; die "Can't open sendmail";
print SENDMAIL trim($msg) . "\n"; print SENDMAIL trim($msg) . "\n";
close SENDMAIL; close SENDMAIL;
}
push(@sentlist, $person); push(@sentlist, $person);
return 1;
} }
sub ProcessOneBug { sub ProcessOneBug {
my $i = $_[0]; my $i = $_[0];
NewProcessOneBug($i); NewProcessOneBug($i);
# Make sure that everyone who was excluded because of the advanced
# filtering options (and thus are using new email tech) has the
# corresponding element in %seen set. This is so that they won't
# also be processed by the old email tech code, which follows.
#
# It's necessary because people who are excluded by the advanced
# filtering code never make it into NewProcessOnePerson(), which is
# where %seen would have otherwise been touched for them.
#
foreach my $person (@excludedAddresses) {
$seen{$person} = 1;
}
my $old = "shadow/$i"; my $old = "shadow/$i";
my $new = "shadow/$i.tmp.$$"; my $new = "shadow/$i.tmp.$$";
my $diffs = "shadow/$i.diffs.$$"; my $diffs = "shadow/$i.diffs.$$";
...@@ -668,12 +1007,14 @@ sub ProcessOneBug { ...@@ -668,12 +1007,14 @@ sub ProcessOneBug {
if (Param("sendmailnow")) { if (Param("sendmailnow")) {
$sendmailparam = ""; $sendmailparam = "";
} }
if ($enableSendMail==1) {
open(SENDMAIL, open(SENDMAIL,
"|/usr/lib/sendmail $sendmailparam -t") || "|/usr/lib/sendmail $sendmailparam -t") ||
die "Can't open sendmail"; die "Can't open sendmail";
print SENDMAIL $msg; print SENDMAIL $msg;
close SENDMAIL; close SENDMAIL;
}
foreach my $n (split(/[, ]+/, "$tolist,$cclist")) { foreach my $n (split(/[, ]+/, "$tolist,$cclist")) {
if ($n ne "") { if ($n ne "") {
push(@sentlist, $n); push(@sentlist, $n);
...@@ -686,11 +1027,29 @@ sub ProcessOneBug { ...@@ -686,11 +1027,29 @@ sub ProcessOneBug {
unlink($diffs); unlink($diffs);
Log($logstr); Log($logstr);
} }
# on the off chance that there are duplicate addresses in the exclude list,
# we filter it for dups one more time. They could have gotten there in
# fixaddresses(), NewProcessOnePerson(), or NewProcessOneBug.
#
@excludedAddresses = filterExcludeList(\@excludedAddresses,
\@sentlist);
if (!$regenerate) {
if (@sentlist) { if (@sentlist) {
print "<B>Email sent to:</B> " . join(", ", @sentlist) . "\n"; print "<B>Email sent to:</B> " . join(", ", @sentlist) . "<br>\n";
if ($didexclude) { } else {
print qq{<B>Excluding:</B> $nametoexclude (<a href="userprefs.cgi?bank=diffs">change your preferences</a> if you wish not to be excluded)\n}; print "<B>Email sent to:</B> no one<br>\n";
} }
if ( @excludedAddresses ) {
print "<br><B>Excluding: </B>" . join(", ", @excludedAddresses) .
"\n";
}
print "<br><br><center>New: <a href=\"userprefs.cgi\?bank=diffs\">" .
"change your email preferences<\/a> if you wish to tweak the " .
"kinds of Bugzilla email you get.<\/center>\n";
} }
rename($new, $old) || die "Can't rename $new to $old"; rename($new, $old) || die "Can't rename $new to $old";
chmod 0666, $old; chmod 0666, $old;
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
# #
# Contributor(s): Terry Weissman <terry@mozilla.org> # Contributor(s): Terry Weissman <terry@mozilla.org>
# Dan Mosedale <dmose@mozilla.org> # Dan Mosedale <dmose@mozilla.org>
# Alan Raetz <al_raetz@yahoo.com>
# David Miller <dave@intrec.com>
#
use diagnostics; use diagnostics;
use strict; use strict;
...@@ -33,6 +36,62 @@ sub sillyness { ...@@ -33,6 +36,62 @@ sub sillyness {
my $userid; my $userid;
my $showNewEmailTech;
# Note the use of arrays instead of hashes: we want the items
# displayed in the same order as they appear in the array.
my @emailGroups = (
'Owner', 'the Bug Owner',
'Reporter', 'the Reporter',
'QAcontact', 'the QA contact',
'CClist', 'on the CC list'
);
my @emailFlags = (
'Comments', 'New Comments',
'Attachments', 'New Attachments',
'Status', 'Priority, status, severity, and milestone changes',
'Resolved', 'When the bug is resolved or verified',
'Keywords', 'Keywords field changes',
'CC', 'CC field changes',
'Other', 'Any field not mentioned above changes'
);
my $defaultEmailFlagString =
'emailOwnerComments~' . 'on~' .
'emailOwnerAttachments~' . 'on~' .
'emailOwnerStatus~' . 'on~' .
'emailOwnerResolved~' . 'on~' .
'emailOwnerKeywords~' . 'on~' .
'emailOwnerCC~' . 'on~' .
'emailOwnerOther~' . 'on~' .
'emailReporterComments~' . 'on~' .
'emailReporterAttachments~' . 'on~' .
'emailReporterStatus~' . 'on~' .
'emailReporterResolved~' . 'on~' .
'emailReporterKeywords~' . 'on~' .
'emailReporterCC~' . 'on~' .
'emailReporterOther~' . 'on~' .
'emailQAcontactComments~' . 'on~' .
'emailQAcontactAttachments~' . 'on~' .
'emailQAcontactStatus~' . 'on~' .
'emailQAcontactResolved~' . 'on~' .
'emailQAcontactKeywords~' . 'on~' .
'emailQAcontactCC~' . 'on~' .
'emailQAcontactOther~' . 'on~' .
'emailCClistComments~' . 'on~' .
'emailCClistAttachments~' . 'on~' .
'emailCClistStatus~' . 'on~' .
'emailCClistResolved~' . 'on~' .
'emailCClistKeywords~' . 'on~' .
'emailCClistCC~' . 'on~' .
'emailCClistOther~' . 'on' ;
sub EmitEntry { sub EmitEntry {
my ($description, $entry) = (@_); my ($description, $entry) = (@_);
...@@ -93,22 +152,52 @@ sub SaveAccount { ...@@ -93,22 +152,52 @@ sub SaveAccount {
" WHERE userid = $userid"); " WHERE userid = $userid");
} }
#
# Set email flags in database based on the parameter string.
#
sub setEmailFlags ($) {
my $emailFlagString = $_[0];
SendSQL("UPDATE profiles SET emailflags = " .
SqlQuote($emailFlagString) . " WHERE userid = $userid");
}
sub ShowEmailOptions () {
sub ShowDiffs {
SendSQL("SELECT emailnotification, newemailtech FROM profiles " . SendSQL("SELECT emailnotification, newemailtech FROM profiles " .
"WHERE userid = $userid"); "WHERE userid = $userid");
my ($emailnotification, $newemailtech) = (FetchSQLData()); my ($emailnotification, $dbNewEmailTech) = (FetchSQLData());
# Override the database value with the current form value
# if the disable/enable button has been pressed.
if ( defined $::FORM{'newEmailTech'} ) {
# If the user has clicked on 'Disable New Email Tech',
# clear out their email flag preferences.
if ($dbNewEmailTech == 1) {
setEmailFlags('');
}
$showNewEmailTech = $::FORM{'newEmailTech'};
} else {
$showNewEmailTech = $dbNewEmailTech;
}
#print "<BR>database newemailtech = $showNewEmailTech<br>";
my $qacontactpart = ""; my $qacontactpart = "";
if (Param('useqacontact')) { if (Param('useqacontact')) {
$qacontactpart = ", the current QA Contact"; $qacontactpart = ", the current QA Contact";
} }
if ($showNewEmailTech==0) {
print qq{ print qq{
<TR><TD COLSPAN="2"> <TR><TD COLSPAN="2">
Bugzilla will send out email notification of changed bugs to Bugzilla will send out email notification of changed bugs to
the current owner, the submitter of the bug$qacontactpart, anyone on the the current owner, the Reporter of the bug$qacontactpart, and anyone on the
CC list and anyone who has voted for the bug. However, you can suppress CC list. However, you can suppress some of those email notifications.
some of those email notifications.
On which of these bugs would you like email notification of changes? On which of these bugs would you like email notification of changes?
</TD></TR> </TD></TR>
}; };
...@@ -122,64 +211,269 @@ On which of these bugs would you like email notification of changes? ...@@ -122,64 +211,269 @@ On which of these bugs would you like email notification of changes?
"All qualifying bugs"]], "All qualifying bugs"]],
$emailnotification); $emailnotification);
EmitEntry("Notify me of changes to", $entry); EmitEntry("Notify me of changes to", $entry);
}
if (Param("newemailtech")) { if (Param("newemailtech")) {
my $checkedpart = $newemailtech ? "CHECKED" : "";
print qq{ print qq{
<TR><TD COLSPAN="2"><HR></TD></TR> <TR><TD COLSPAN="2"><HR></TD></TR>
<TR><TD COLSPAN="2"><FONT COLOR="red">Updated!</FONT> <TR><TD COLSPAN="2"><FONT COLOR="red">Updated!</FONT>
Bugzilla's new standard email notification scheme allows for the use of Bugzilla's new standard email notification scheme allows for the use of
features such as watching other users and selecting which bug changes you get features such as watching other users and selecting which bug changes you get
mail about. You can revert to the old notification scheme by unchecking this mail about. Although it's still possible to use the old notification scheme,
box, but this isn't recommended, because the old scheme is no longer this isn't recommended, because the old scheme is no longer
supported and will be going away in an upcoming version of Bugzilla. supported and will be going away in an upcoming version of Bugzilla.
</TD></TR> <FONT COLOR="red">Note that after clicking the link below, you must still click
}; on the <B>Submit Changes</B> button in order for your email tech change to be saved.</FONT>
EmitEntry("Uncheck here to revert", </TD></TR>};
qq{<INPUT TYPE="checkbox" NAME="newemailtech" $checkedpart>New email tech});
if ($showNewEmailTech == 1) {
print qq{
<tr><td colspan=2><center>
<A HREF="userprefs.cgi?bank=diffs&amp;newEmailTech=0">Disable New Email Tech</A>
</center></td></tr>};
} else {
print qq{<tr><td colspan=2><center><A HREF="userprefs.cgi?bank=diffs&amp;newEmailTech=1">Enable New Email Tech</A></center></td></tr>};
} }
if (Param("supportwatchers")) { if (Param("supportwatchers") && $showNewEmailTech == 1) {
my $watcheduserSet = new RelationSet; my $watcheduserSet = new RelationSet;
$watcheduserSet->mergeFromDB("SELECT watched FROM watch WHERE" . $watcheduserSet->mergeFromDB("SELECT watched FROM watch WHERE" .
" watcher=$userid"); " watcher=$userid");
my $watchedusers = $watcheduserSet->toString(); my $watchedusers = $watcheduserSet->toString();
print qq{ print qq{
<TR><TD COLSPAN="2"><HR></TD></TR> <TR><TD COLSPAN="4"><HR></TD></TR>
<TR><TD COLSPAN="2"><FONT COLOR="red">New!</FONT> <TR><TD COLSPAN="4">
If you want to help cover for someone when they're on vacation, or if <FONT COLOR="red">New Email Tech Feature: </FONT>If you want to help cover for someone when they're on vacation, or if
you need to do the QA related to all of their bugs, you can tell bugzilla you need to do the QA related to all of their bugs, you can tell bugzilla
to send mail related to their bugs to you also. List the email addresses to send mail related to their bugs to you also. List the email addresses
of any users you wish to watch here, separated by commas. of any users you wish to watch here, separated by commas.
<FONT COLOR="red">Note that you MUST have the above "New email tech" </TD></TR>};
button selected in order to use this feature.</FONT>
</TD></TR>
};
EmitEntry("Users to watch", EmitEntry("Users to watch",
qq{<INPUT SIZE=35 NAME="watchedusers" VALUE="$watchedusers">}); qq{<INPUT SIZE=35 NAME="watchedusers" VALUE="$watchedusers">});
}
print qq{<TR><TD COLSPAN="2"><HR></TD></TR>};
if ($showNewEmailTech == 1) {
showAdvancedEmailFilterOptions();
}
} }
print qq {
<TABLE CELLSPACING="0" CELLPADDING="10" BORDER=0 WIDTH="100%">
<TR><TD>};
} }
sub SaveDiffs { sub showAdvancedEmailFilterOptions () {
my $newemailtech = 0;
if (exists $::FORM{'newemailtech'}) { my $flags;
$newemailtech = 1; my $notify;
my %userEmailFlags = ();
print qq{
<TR><TD COLSPAN="2"><center>
<font size=+1>Advanced Email Filtering Options</font>
</center>
</TD></TR><tr><td colspan="2">
<p>
<center><FONT COLOR="red">New Email Tech Feature:</FONT>
Filter email notifications for <b>modified</b>
bugs (does not effect new bug email notices).
</center></td></tr></table>
<hr width=800 align=center>
};
SendSQL("SELECT emailflags, emailnotification FROM profiles WHERE " .
"userid = $userid");
($flags, $notify) = FetchSQLData();
# if the emailflags haven't been set before, that means that this user
# hasn't been to (the email pane of?) userprefs.cgi since the change to
# use emailflags. create a default flagset for them, mostly based on
# static defaults, but setting ExcludeSelf based on the old
# emailnotification column.
#
if ( !$flags ) {
if ( !$notify ) {
confess("neither \$flags nor \$notify was set");
}
my $notifyString;
if ( $notify eq 'ExcludeSelfChanges' ) {
$notifyString = "ExcludeSelf~on~";
} else {
$notifyString = "ExcludeSelf~~";
}
$flags = $notifyString . $defaultEmailFlagString;
setEmailFlags($flags);
} }
SendSQL("UPDATE profiles " .
"SET emailnotification = " . SqlQuote($::FORM{'emailnotification'})
. ", newemailtech = $newemailtech WHERE userid = $userid");
# deal with any watchers # the 255 param is here, because without a third param, split will
# trim any trailing null fields, which causes perl to eject lots of
# warnings. any suitably large number would do.
# #
%userEmailFlags = split(/~/ , $flags, 255);
showExcludeSelf(\%userEmailFlags);
# print STDERR "$flags\n";
print qq{
<hr width=800 align=left>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<b>Field/recipient specific options:</b><br><br>
};
my @tmpGroups = @emailGroups;
while ((my $groupName,my $groupText) = splice(@tmpGroups,0,2) ) {
printEmailPrefGroup($groupName,$groupText,\%userEmailFlags);
}
}
sub showExcludeSelf (\%) {
my %CurrentFlags = %{$_[0]};
my $excludeSelf = " ";
while ( my ($key,$value) = each (%CurrentFlags) ) {
# print qq{flag name: $key value: $value<br>};
if ( $key eq 'ExcludeSelf' ) {
if ( $value eq 'on' ) {
$excludeSelf = "CHECKED";
}
}
}
print qq {
<table><tr><td colspan=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<b>Global options:</b></tr>
<tr><td width=150></td><td>
Do not email me bugs that I change
<input type="checkbox" name="ExcludeSelf" VALUE="on" $excludeSelf>
<br>
</td>
</tr>
</table>
};
}
sub printEmailPrefGroup ($$\%) {
my ($groupName,$textName,$refCurrentFlags) = @_[0,1,2];
my @tmpFlags = @emailFlags;
print qq {<table cellspacing=0 cellpadding=6> };
print qq {<tr><td colspan=2> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
When I\'m $textName, email me:</td></tr> };
while ((my $flagName,my $flagText) = splice(@tmpFlags,0,2)) {
printEmailOption($groupName . $flagName, $flagText, $refCurrentFlags);
}
print qq { </table> };
print qq { <hr WIDTH=320 ALIGN=left> };
}
sub printEmailOption ($$\%) {
my $value= '';
my ($optionName,$description,$refCurrentFlags) = @_[0,1,2];
#print qq{ email$optionName: $$refCurrentFlags{"email$optionName"} <br>};
# if the db value is 'on', then mark that checkbox
if ($$refCurrentFlags{"email$optionName"} eq 'on'){
$value = 'CHECKED';
}
print qq{
<tr><td width=320></td>
<td><input type="checkbox" name="email$optionName" VALUE="on" $value>
$description</td>
</tr>
};
}
sub SaveEmailOptions () {
# I don't understand: global variables and %FORM variables are
# not preserved between ShowEmailOptions() and SaveEmailOptions()
# The form value here is from a hidden variable just before the SUBMIT.
my $useNewEmailTech = $::FORM{'savedEmailTech'};
my $updateString;
if ($useNewEmailTech == 0) {
# we force the NEW email filter entry to allow all email
# (empty string defaults to allowing all email).
$updateString = '';
} else {
if ( defined $::FORM{'ExcludeSelf'}) {
$updateString .= 'ExcludeSelf~on';
} else {
$updateString .= 'ExcludeSelf~';
}
my @tmpGroups = @emailGroups;
while ((my $groupName,my $groupText) = splice(@tmpGroups,0,2) ) {
my @tmpFlags = @emailFlags;
while ((my $flagName,my $flagText) = splice(@tmpFlags,0,2) ) {
my $entry = 'email' . $groupName . $flagName;
my $entryValue;
if (!defined $::FORM{$entry} ) {
$entryValue = "";
} else {
$entryValue = $::FORM{$entry};
}
$updateString .= '~' . $entry . '~' . $entryValue;
}
}
# we force the OLD email tech flag to allow all email
$::FORM{'emailnotification'} = "All";
}
#open(FID,">updateString");
#print qq{UPDATE STRING: $updateString <br>};
#close(FID);
SendSQL("UPDATE profiles SET emailnotification = "
. SqlQuote($::FORM{'emailnotification'})
. ", newemailtech = $useNewEmailTech "
. "WHERE userid = $userid" );
SendSQL("UPDATE profiles SET emailflags = " .
SqlQuote($updateString) . " WHERE userid = $userid");
if (Param("supportwatchers") ) { if (Param("supportwatchers") ) {
if (exists $::FORM{'watchedusers'}) { if (exists $::FORM{'watchedusers'}) {
Error ('You must have "New email tech" set to watch someone') Error ('You must have "New email tech" set to watch someone')
if ( $::FORM{'watchedusers'} ne "" && $newemailtech == 0); if ( $::FORM{'watchedusers'} ne "" && $useNewEmailTech == 0);
# Just in case. Note that this much locking is actually overkill: # Just in case. Note that this much locking is actually overkill:
# we don't really care if anyone reads the watch table. So # we don't really care if anyone reads the watch table. So
...@@ -247,7 +541,7 @@ sub ShowFooter { ...@@ -247,7 +541,7 @@ sub ShowFooter {
print qq{<INPUT TYPE=HIDDEN NAME="numqueries" VALUE="$count">\n}; print qq{<INPUT TYPE=HIDDEN NAME="numqueries" VALUE="$count">\n};
if (!$count) { if (!$count) {
print qq{ print qq{
<TR><TD COLSPAN="2"> <TR><TD COLSPAN="4">
If you go create remembered queries in the <A HREF="query.cgi">query page</A>, If you go create remembered queries in the <A HREF="query.cgi">query page</A>,
you can then come to this page and choose to have some of them appear in the you can then come to this page and choose to have some of them appear in the
footer of each Bugzilla page. footer of each Bugzilla page.
...@@ -285,7 +579,7 @@ sub SaveFooter { ...@@ -285,7 +579,7 @@ sub SaveFooter {
sub ShowPermissions { sub ShowPermissions {
print "<TR><TD>You have the following permission bits set on your account:\n"; print "You have the following permission bits set on your account:\n";
print "<P><UL>\n"; print "<P><UL>\n";
my $found = 0; my $found = 0;
SendSQL("SELECT description FROM groups " . SendSQL("SELECT description FROM groups " .
...@@ -313,7 +607,7 @@ sub ShowPermissions { ...@@ -313,7 +607,7 @@ sub ShowPermissions {
my ($description) = (FetchSQLData()); my ($description) = (FetchSQLData());
print "<LI>$description\n"; print "<LI>$description\n";
} }
print "</UL></TD></TR>\n"; print "</UL>\n";
} }
} }
...@@ -330,7 +624,7 @@ print "Content-type: text/html\n\n"; ...@@ -330,7 +624,7 @@ print "Content-type: text/html\n\n";
GetVersionTable(); GetVersionTable();
PutHeader("Preferences", "Preferences", $::COOKIE{'Bugzilla_login'}); PutHeader("User Preferences", "User Preferences", $::COOKIE{'Bugzilla_login'});
# foreach my $k (sort(keys(%::FORM))) { # foreach my $k (sort(keys(%::FORM))) {
# print "<pre>" . value_quote($k) . ": " . value_quote($::FORM{$k}) . "\n</pre>"; # print "<pre>" . value_quote($k) . ": " . value_quote($::FORM{$k}) . "\n</pre>";
...@@ -342,7 +636,7 @@ my @banklist = ( ...@@ -342,7 +636,7 @@ my @banklist = (
["account", "Account settings", ["account", "Account settings",
\&ShowAccount, \&SaveAccount], \&ShowAccount, \&SaveAccount],
["diffs", "Email settings", ["diffs", "Email settings",
\&ShowDiffs, \&SaveDiffs], \&ShowEmailOptions, \&SaveEmailOptions],
["footer", "Page footer", ["footer", "Page footer",
\&ShowFooter, \&SaveFooter], \&ShowFooter, \&SaveFooter],
["permissions", "Permissions", ["permissions", "Permissions",
...@@ -397,19 +691,27 @@ if (defined $bankdescription) { ...@@ -397,19 +691,27 @@ if (defined $bankdescription) {
&$savefunc; &$savefunc;
print "Your changes have been saved."; print "Your changes have been saved.";
} }
print qq{ print qq{<H3>$bankdescription</H3><FORM METHOD="POST"><TABLE>};
<H3>$bankdescription</H3>
<FORM METHOD="POST"> # execute subroutine from @banklist based on bank selected.
<TABLE>
};
&$showfunc; &$showfunc;
print qq{
</TABLE> print qq{</TABLE><INPUT TYPE="hidden" NAME="dosave" VALUE="1">};
<INPUT TYPE="hidden" NAME="dosave" VALUE="1"> print qq{<INPUT TYPE="hidden" NAME="savedEmailTech" VALUE="};
<INPUT TYPE="hidden" NAME="bank" VALUE="$bank">
}; # default this to 0 if it's not already set
#
if (defined $showNewEmailTech) {
print qq{$showNewEmailTech">};
} else {
print qq{0">};
}
print qq{<INPUT TYPE="hidden" NAME="bank" VALUE="$bank"> };
if ($savefunc) { if ($savefunc) {
print qq{<INPUT TYPE="submit" VALUE="Submit">\n}; print qq{<table><tr><td width=150></td><td>
<INPUT TYPE="submit" VALUE="Submit Changes">
</td></tr></table> };
} }
print qq{</FORM>\n}; print qq{</FORM>\n};
} else { } else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment