aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Mailer.pm')
-rw-r--r--Bugzilla/Mailer.pm362
1 files changed, 186 insertions, 176 deletions
diff --git a/Bugzilla/Mailer.pm b/Bugzilla/Mailer.pm
index 5ccf2d1ed..a5f79b9bc 100644
--- a/Bugzilla/Mailer.pm
+++ b/Bugzilla/Mailer.pm
@@ -28,199 +28,209 @@ use Email::Sender::Transport::SMTP::Persistent;
use Bugzilla::Sender::Transport::Sendmail;
sub generate_email {
- my ($vars, $templates) = @_;
- my ($lang, $email_format, $msg_text, $msg_html, $msg_header);
- state $use_utf8 = Bugzilla->params->{'utf8'};
-
- if ($vars->{to_user}) {
- $lang = $vars->{to_user}->setting('lang');
- $email_format = $vars->{to_user}->setting('email_format');
- } else {
- # If there are users in the CC list who don't have an account,
- # use the default language for email notifications.
- $lang = Bugzilla::User->new()->setting('lang');
- # However we cannot fall back to the default email_format, since
- # it may be HTML, and many of the includes used in the HTML
- # template require a valid user object. Instead we fall back to
- # the plaintext template.
- $email_format = 'text_only';
- }
-
- my $template = Bugzilla->template_inner($lang);
-
- $template->process($templates->{header}, $vars, \$msg_header)
- || ThrowTemplateError($template->error());
- $template->process($templates->{text}, $vars, \$msg_text)
- || ThrowTemplateError($template->error());
-
- my @parts = (
- Bugzilla::MIME->create(
- attributes => {
- content_type => 'text/plain',
- charset => $use_utf8 ? 'UTF-8' : 'iso-8859-1',
- encoding => 'quoted-printable',
- },
- body_str => $msg_text,
- )
- );
- if ($templates->{html} && $email_format eq 'html') {
- $template->process($templates->{html}, $vars, \$msg_html)
- || ThrowTemplateError($template->error());
- push @parts, Bugzilla::MIME->create(
- attributes => {
- content_type => 'text/html',
- charset => $use_utf8 ? 'UTF-8' : 'iso-8859-1',
- encoding => 'quoted-printable',
- },
- body_str => $msg_html,
- );
- }
-
- my $email = Bugzilla::MIME->new($msg_header);
- if (scalar(@parts) == 1) {
- $email->content_type_set($parts[0]->content_type);
- } else {
- $email->content_type_set('multipart/alternative');
- # Some mail clients need same encoding for each part, even empty ones.
- $email->charset_set('UTF-8') if $use_utf8;
- }
- $email->parts_set(\@parts);
- return $email;
+ my ($vars, $templates) = @_;
+ my ($lang, $email_format, $msg_text, $msg_html, $msg_header);
+ state $use_utf8 = Bugzilla->params->{'utf8'};
+
+ if ($vars->{to_user}) {
+ $lang = $vars->{to_user}->setting('lang');
+ $email_format = $vars->{to_user}->setting('email_format');
+ }
+ else {
+ # If there are users in the CC list who don't have an account,
+ # use the default language for email notifications.
+ $lang = Bugzilla::User->new()->setting('lang');
+
+ # However we cannot fall back to the default email_format, since
+ # it may be HTML, and many of the includes used in the HTML
+ # template require a valid user object. Instead we fall back to
+ # the plaintext template.
+ $email_format = 'text_only';
+ }
+
+ my $template = Bugzilla->template_inner($lang);
+
+ $template->process($templates->{header}, $vars, \$msg_header)
+ || ThrowTemplateError($template->error());
+ $template->process($templates->{text}, $vars, \$msg_text)
+ || ThrowTemplateError($template->error());
+
+ my @parts = (Bugzilla::MIME->create(
+ attributes => {
+ content_type => 'text/plain',
+ charset => $use_utf8 ? 'UTF-8' : 'iso-8859-1',
+ encoding => 'quoted-printable',
+ },
+ body_str => $msg_text,
+ ));
+ if ($templates->{html} && $email_format eq 'html') {
+ $template->process($templates->{html}, $vars, \$msg_html)
+ || ThrowTemplateError($template->error());
+ push @parts,
+ Bugzilla::MIME->create(
+ attributes => {
+ content_type => 'text/html',
+ charset => $use_utf8 ? 'UTF-8' : 'iso-8859-1',
+ encoding => 'quoted-printable',
+ },
+ body_str => $msg_html,
+ );
+ }
+
+ my $email = Bugzilla::MIME->new($msg_header);
+ if (scalar(@parts) == 1) {
+ $email->content_type_set($parts[0]->content_type);
+ }
+ else {
+ $email->content_type_set('multipart/alternative');
+
+ # Some mail clients need same encoding for each part, even empty ones.
+ $email->charset_set('UTF-8') if $use_utf8;
+ }
+ $email->parts_set(\@parts);
+ return $email;
}
sub MessageToMTA {
- my ($msg, $send_now) = (@_);
- my $method = Bugzilla->params->{'mail_delivery_method'};
- return if $method eq 'None';
-
- if (Bugzilla->params->{'use_mailer_queue'}
- && ! $send_now
- && ! Bugzilla->dbh->bz_in_transaction()
- ) {
- Bugzilla->job_queue->insert('send_mail', { msg => $msg });
- return;
- }
-
- my $dbh = Bugzilla->dbh;
-
- my $email = ref($msg) ? $msg : Bugzilla::MIME->new($msg);
-
- # If we're called from within a transaction, we don't want to send the
- # email immediately, in case the transaction is rolled back. Instead we
- # insert it into the mail_staging table, and bz_commit_transaction calls
- # send_staged_mail() after the transaction is committed.
- if (! $send_now && $dbh->bz_in_transaction()) {
- # The e-mail string may contain tainted values.
- my $string = $email->as_string;
- trick_taint($string);
-
- my $sth = $dbh->prepare("INSERT INTO mail_staging (message) VALUES (?)");
- $sth->bind_param(1, $string, $dbh->BLOB_TYPE);
- $sth->execute;
- return;
- }
-
- my $from = $email->header('From');
-
- my $hostname;
- my $transport;
- if ($method eq "Sendmail") {
- if (ON_WINDOWS) {
- $transport = Bugzilla::Sender::Transport::Sendmail->new({ sendmail => SENDMAIL_EXE });
- }
- else {
- $transport = Bugzilla::Sender::Transport::Sendmail->new();
- }
+ my ($msg, $send_now) = (@_);
+ my $method = Bugzilla->params->{'mail_delivery_method'};
+ return if $method eq 'None';
+
+ if ( Bugzilla->params->{'use_mailer_queue'}
+ && !$send_now
+ && !Bugzilla->dbh->bz_in_transaction())
+ {
+ Bugzilla->job_queue->insert('send_mail', {msg => $msg});
+ return;
+ }
+
+ my $dbh = Bugzilla->dbh;
+
+ my $email = ref($msg) ? $msg : Bugzilla::MIME->new($msg);
+
+ # If we're called from within a transaction, we don't want to send the
+ # email immediately, in case the transaction is rolled back. Instead we
+ # insert it into the mail_staging table, and bz_commit_transaction calls
+ # send_staged_mail() after the transaction is committed.
+ if (!$send_now && $dbh->bz_in_transaction()) {
+
+ # The e-mail string may contain tainted values.
+ my $string = $email->as_string;
+ trick_taint($string);
+
+ my $sth = $dbh->prepare("INSERT INTO mail_staging (message) VALUES (?)");
+ $sth->bind_param(1, $string, $dbh->BLOB_TYPE);
+ $sth->execute;
+ return;
+ }
+
+ my $from = $email->header('From');
+
+ my $hostname;
+ my $transport;
+ if ($method eq "Sendmail") {
+ if (ON_WINDOWS) {
+ $transport
+ = Bugzilla::Sender::Transport::Sendmail->new({sendmail => SENDMAIL_EXE});
}
else {
- # Sendmail will automatically append our hostname to the From
- # address, but other mailers won't.
- my $urlbase = Bugzilla->params->{'urlbase'};
- $urlbase =~ m|//([^:/]+)[:/]?|;
- $hostname = $1 || 'localhost';
- $from .= "\@$hostname" if $from !~ /@/;
- $email->header_set('From', $from);
-
- # Sendmail adds a Date: header also, but others may not.
- if (!defined $email->header('Date')) {
- $email->header_set('Date', time2str("%a, %d %b %Y %T %z", time()));
- }
- }
-
- if ($method eq "SMTP") {
- my ($host, $port) = split(/:/, Bugzilla->params->{'smtpserver'}, 2);
- $transport = Bugzilla->request_cache->{smtp} //=
- Email::Sender::Transport::SMTP::Persistent->new({
- host => $host,
- defined($port) ? (port => $port) : (),
- sasl_username => Bugzilla->params->{'smtp_username'},
- sasl_password => Bugzilla->params->{'smtp_password'},
- helo => $hostname,
- ssl => Bugzilla->params->{'smtp_ssl'},
- debug => Bugzilla->params->{'smtp_debug'} });
+ $transport = Bugzilla::Sender::Transport::Sendmail->new();
}
-
- Bugzilla::Hook::process('mailer_before_send', { email => $email });
-
- return if $email->header('to') eq '';
-
- if ($method eq "Test") {
- my $filename = bz_locations()->{'datadir'} . '/mailer.testfile';
- open TESTFILE, '>>', $filename;
- # From - <date> is required to be a valid mbox file.
- print TESTFILE "\n\nFrom - " . $email->header('Date') . "\n" . $email->as_string;
- close TESTFILE;
+ }
+ else {
+ # Sendmail will automatically append our hostname to the From
+ # address, but other mailers won't.
+ my $urlbase = Bugzilla->params->{'urlbase'};
+ $urlbase =~ m|//([^:/]+)[:/]?|;
+ $hostname = $1 || 'localhost';
+ $from .= "\@$hostname" if $from !~ /@/;
+ $email->header_set('From', $from);
+
+ # Sendmail adds a Date: header also, but others may not.
+ if (!defined $email->header('Date')) {
+ $email->header_set('Date', time2str("%a, %d %b %Y %T %z", time()));
}
- else {
- # This is useful for Sendmail, so we put it out here.
- local $ENV{PATH} = SENDMAIL_PATH;
- eval { sendmail($email, { transport => $transport }) };
- if ($@) {
- ThrowCodeError('mail_send_error', { msg => $@->message, mail => $email });
- }
+ }
+
+ if ($method eq "SMTP") {
+ my ($host, $port) = split(/:/, Bugzilla->params->{'smtpserver'}, 2);
+ $transport = Bugzilla->request_cache->{smtp}
+ //= Email::Sender::Transport::SMTP::Persistent->new({
+ host => $host,
+ defined($port) ? (port => $port) : (),
+ sasl_username => Bugzilla->params->{'smtp_username'},
+ sasl_password => Bugzilla->params->{'smtp_password'},
+ helo => $hostname,
+ ssl => Bugzilla->params->{'smtp_ssl'},
+ debug => Bugzilla->params->{'smtp_debug'}
+ });
+ }
+
+ Bugzilla::Hook::process('mailer_before_send', {email => $email});
+
+ return if $email->header('to') eq '';
+
+ if ($method eq "Test") {
+ my $filename = bz_locations()->{'datadir'} . '/mailer.testfile';
+ open TESTFILE, '>>', $filename;
+
+ # From - <date> is required to be a valid mbox file.
+ print TESTFILE "\n\nFrom - "
+ . $email->header('Date') . "\n"
+ . $email->as_string;
+ close TESTFILE;
+ }
+ else {
+ # This is useful for Sendmail, so we put it out here.
+ local $ENV{PATH} = SENDMAIL_PATH;
+ eval { sendmail($email, {transport => $transport}) };
+ if ($@) {
+ ThrowCodeError('mail_send_error', {msg => $@->message, mail => $email});
}
+ }
}
# Builds header suitable for use as a threading marker in email notifications
sub build_thread_marker {
- my ($bug_id, $user_id, $is_new) = @_;
-
- if (!defined $user_id) {
- $user_id = Bugzilla->user->id;
- }
-
- my $sitespec = '@' . Bugzilla->params->{'urlbase'};
- $sitespec =~ s/:\/\//\./; # Make the protocol look like part of the domain
- $sitespec =~ s/^([^:\/]+):(\d+)/$1/; # Remove a port number, to relocate
- if ($2) {
- $sitespec = "-$2$sitespec"; # Put the port number back in, before the '@'
- }
-
- my $threadingmarker;
- if ($is_new) {
- $threadingmarker = "Message-ID: <bug-$bug_id-$user_id$sitespec>";
- }
- else {
- my $rand_bits = generate_random_password(10);
- $threadingmarker = "Message-ID: <bug-$bug_id-$user_id-$rand_bits$sitespec>" .
- "\nIn-Reply-To: <bug-$bug_id-$user_id$sitespec>" .
- "\nReferences: <bug-$bug_id-$user_id$sitespec>";
- }
-
- return $threadingmarker;
+ my ($bug_id, $user_id, $is_new) = @_;
+
+ if (!defined $user_id) {
+ $user_id = Bugzilla->user->id;
+ }
+
+ my $sitespec = '@' . Bugzilla->params->{'urlbase'};
+ $sitespec =~ s/:\/\//\./; # Make the protocol look like part of the domain
+ $sitespec =~ s/^([^:\/]+):(\d+)/$1/; # Remove a port number, to relocate
+ if ($2) {
+ $sitespec = "-$2$sitespec"; # Put the port number back in, before the '@'
+ }
+
+ my $threadingmarker;
+ if ($is_new) {
+ $threadingmarker = "Message-ID: <bug-$bug_id-$user_id$sitespec>";
+ }
+ else {
+ my $rand_bits = generate_random_password(10);
+ $threadingmarker
+ = "Message-ID: <bug-$bug_id-$user_id-$rand_bits$sitespec>"
+ . "\nIn-Reply-To: <bug-$bug_id-$user_id$sitespec>"
+ . "\nReferences: <bug-$bug_id-$user_id$sitespec>";
+ }
+
+ return $threadingmarker;
}
sub send_staged_mail {
- my $dbh = Bugzilla->dbh;
+ my $dbh = Bugzilla->dbh;
- my $emails = $dbh->selectall_arrayref('SELECT id, message FROM mail_staging');
- my $sth = $dbh->prepare('DELETE FROM mail_staging WHERE id = ?');
+ my $emails = $dbh->selectall_arrayref('SELECT id, message FROM mail_staging');
+ my $sth = $dbh->prepare('DELETE FROM mail_staging WHERE id = ?');
- foreach my $email (@$emails) {
- my ($id, $message) = @$email;
- MessageToMTA($message);
- $sth->execute($id);
- }
+ foreach my $email (@$emails) {
+ my ($id, $message) = @$email;
+ MessageToMTA($message);
+ $sth->execute($id);
+ }
}
1;