summaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
authorByron Jones <glob@mozilla.com>2014-11-04 06:38:46 +0100
committerByron Jones <glob@mozilla.com>2014-11-04 06:38:46 +0100
commit7dc675fedb5b2631a8bafd0fb691eac485eff0af (patch)
tree548488280f00fc5e03ef841a2f997fa3fbb1ff73 /Bugzilla
parent300d1ba13e050aa1e954dde640092c448184cbba (diff)
downloadbugzilla-7dc675fedb5b2631a8bafd0fb691eac485eff0af.tar.gz
bugzilla-7dc675fedb5b2631a8bafd0fb691eac485eff0af.tar.xz
Bug 1092037: backport bug 1062739 to bmo (add the ability for administrators to limit the number of emails sent to a user per minute and hour)
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/Constants.pm18
-rw-r--r--Bugzilla/Install/Requirements.pm3
-rw-r--r--Bugzilla/Job/BugMail.pm16
-rw-r--r--Bugzilla/Job/Mailer.pm22
-rw-r--r--Bugzilla/Mailer.pm49
5 files changed, 89 insertions, 19 deletions
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index 37e995b81..6e0a9c7d3 100644
--- a/Bugzilla/Constants.pm
+++ b/Bugzilla/Constants.pm
@@ -208,6 +208,12 @@ use Memoize;
AUDIT_CREATE
AUDIT_REMOVE
+
+ EMAIL_LIMIT_PER_MINUTE
+ EMAIL_LIMIT_PER_HOUR
+ EMAIL_LIMIT_EXCEPTION
+
+ JOB_QUEUE_VIEW_MAX_JOBS
);
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
@@ -632,6 +638,18 @@ use constant PRIVILEGES_REQUIRED_EMPOWERED => 3;
use constant AUDIT_CREATE => '__create__';
use constant AUDIT_REMOVE => '__remove__';
+# The maximum number of emails per minute and hour a recipient can receive.
+# Email will be queued/backlogged to avoid exceeeding these limits.
+# Setting a limit to 0 will disable this feature.
+use constant EMAIL_LIMIT_PER_MINUTE => 1000;
+use constant EMAIL_LIMIT_PER_HOUR => 2500;
+# Don't change this exception message.
+use constant EMAIL_LIMIT_EXCEPTION => "email_limit_exceeded\n";
+
+# The maximum number of jobs to show when viewing the job queue
+# (view_job_queue.cgi).
+use constant JOB_QUEUE_VIEW_MAX_JOBS => 2500;
+
sub bz_locations {
# Force memoize() to re-compute data per project, to avoid
# sharing the same data across different installations.
diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm
index 1c9c91345..6bb012230 100644
--- a/Bugzilla/Install/Requirements.pm
+++ b/Bugzilla/Install/Requirements.pm
@@ -348,7 +348,8 @@ sub OPTIONAL_MODULES {
{
package => 'TheSchwartz',
module => 'TheSchwartz',
- version => 0,
+ # 1.10 supports declining of jobs.
+ version => 1.10,
feature => ['jobqueue'],
},
{
diff --git a/Bugzilla/Job/BugMail.pm b/Bugzilla/Job/BugMail.pm
index 9c176b005..403d936ad 100644
--- a/Bugzilla/Job/BugMail.pm
+++ b/Bugzilla/Job/BugMail.pm
@@ -13,19 +13,9 @@ use strict;
use Bugzilla::BugMail;
BEGIN { eval "use parent qw(Bugzilla::Job::Mailer)"; }
-sub work {
- my ($class, $job) = @_;
- my $success = eval {
- Bugzilla::BugMail::dequeue($job->arg->{vars});
- 1;
- };
- if (!$success) {
- $job->failed($@);
- undef $@;
- }
- else {
- $job->completed;
- }
+sub process_job {
+ my ($class, $arg) = @_;
+ Bugzilla::BugMail::dequeue($arg->{vars});
}
1;
diff --git a/Bugzilla/Job/Mailer.pm b/Bugzilla/Job/Mailer.pm
index 09c387326..e3b94894a 100644
--- a/Bugzilla/Job/Mailer.pm
+++ b/Bugzilla/Job/Mailer.pm
@@ -22,6 +22,9 @@
package Bugzilla::Job::Mailer;
use strict;
+use warnings;
+
+use Bugzilla::Constants;
use Bugzilla::Mailer;
BEGIN { eval "use base qw(TheSchwartz::Worker)"; }
@@ -43,15 +46,24 @@ sub retry_delay {
sub work {
my ($class, $job) = @_;
- my $msg = $job->arg->{msg};
- my $success = eval { MessageToMTA($msg, 1); 1; };
- if (!$success) {
- $job->failed($@);
+ eval { $class->process_job($job->arg) };
+ if (my $error = $@) {
+ if ($error eq EMAIL_LIMIT_EXCEPTION) {
+ $job->declined();
+ }
+ else {
+ $job->failed($error);
+ }
undef $@;
- }
+ }
else {
$job->completed;
}
}
+sub process_job {
+ my ($class, $arg) = @_;
+ MessageToMTA($arg, 1);
+}
+
1;
diff --git a/Bugzilla/Mailer.pm b/Bugzilla/Mailer.pm
index 381422821..556500b1a 100644
--- a/Bugzilla/Mailer.pm
+++ b/Bugzilla/Mailer.pm
@@ -67,6 +67,8 @@ sub MessageToMTA {
return;
}
+ my $dbh = Bugzilla->dbh;
+
my $email;
if (ref $msg) {
$email = $msg;
@@ -82,6 +84,42 @@ sub MessageToMTA {
$email = new Email::MIME($msg);
}
+ # Ensure that we are not sending emails too quickly to recipients.
+ if (Bugzilla->params->{use_mailer_queue}
+ && (EMAIL_LIMIT_PER_MINUTE || EMAIL_LIMIT_PER_HOUR))
+ {
+ $dbh->do(
+ "DELETE FROM email_rates WHERE message_ts < "
+ . $dbh->sql_date_math('LOCALTIMESTAMP(0)', '-', '1', 'HOUR'));
+
+ my $recipient = $email->header('To');
+
+ if (EMAIL_LIMIT_PER_MINUTE) {
+ my $minute_rate = $dbh->selectrow_array(
+ "SELECT COUNT(*)
+ FROM email_rates
+ WHERE recipient = ? AND message_ts >= "
+ . $dbh->sql_date_math('LOCALTIMESTAMP(0)', '-', '1', 'MINUTE'),
+ undef,
+ $recipient);
+ if ($minute_rate >= EMAIL_LIMIT_PER_MINUTE) {
+ die EMAIL_LIMIT_EXCEPTION;
+ }
+ }
+ if (EMAIL_LIMIT_PER_HOUR) {
+ my $hour_rate = $dbh->selectrow_array(
+ "SELECT COUNT(*)
+ FROM email_rates
+ WHERE recipient = ? AND message_ts >= "
+ . $dbh->sql_date_math('LOCALTIMESTAMP(0)', '-', '1', 'HOUR'),
+ undef,
+ $recipient);
+ if ($hour_rate >= EMAIL_LIMIT_PER_HOUR) {
+ die EMAIL_LIMIT_EXCEPTION;
+ }
+ }
+ }
+
# We add this header to uniquely identify all email that we
# send as coming from this Bugzilla installation.
#
@@ -208,6 +246,17 @@ sub MessageToMTA {
ThrowCodeError('mail_send_error', { msg => $retval, mail => $email })
if !$retval;
}
+
+ # insert into email_rates
+ if (Bugzilla->params->{use_mailer_queue}
+ && (EMAIL_LIMIT_PER_MINUTE || EMAIL_LIMIT_PER_HOUR))
+ {
+ $dbh->do(
+ "INSERT INTO email_rates(recipient, message_ts) VALUES (?, LOCALTIMESTAMP(0))",
+ undef,
+ $email->header('To')
+ );
+ }
}
# Builds header suitable for use as a threading marker in email notifications