}
# Old mail_delivery_method choices contained no uppercase characters
- if (exists $param->{'mail_delivery_method'}
- && $param->{'mail_delivery_method'} !~ /[A-Z]/)
- {
- my $method = $param->{'mail_delivery_method'};
- my %translation = (
- 'sendmail' => 'Sendmail',
- 'smtp' => 'SMTP',
- 'qmail' => 'Qmail',
- 'testfile' => 'Test',
- 'none' => 'None'
- );
- $param->{'mail_delivery_method'} = $translation{$method};
+ my $mta = $param->{'mail_delivery_method'};
+ if ($mta) {
+ if ($mta !~ /[A-Z]/) {
+ my %translation = (
+ 'sendmail' => 'Sendmail',
+ 'smtp' => 'SMTP',
+ 'qmail' => 'Qmail',
+ 'testfile' => 'Test',
+ 'none' => 'None');
+ $param->{'mail_delivery_method'} = $translation{$mta};
+ }
+ # This will force the parameter to be reset to its default value.
+ delete $param->{'mail_delivery_method'} if $param->{'mail_delivery_method'} eq 'Qmail';
}
# Convert the old "ssl" parameter to the new "ssl_redirect" parameter.
use strict;
use warnings;
-use Email::Address;
+use Email::Address::XS;
use Socket;
use Bugzilla::Util;
sub check_email {
my ($value) = @_;
- if ($value !~ $Email::Address::mailbox) {
+ my ($address) = Email::Address::XS->parse($value);
+ if (!$address->is_valid) {
return "must be a valid email address.";
}
return "";
use Bugzilla::Config::Common;
-# Return::Value 1.666002 pollutes the error log with warnings about this
-# deprecated module. We have to set NO_CLUCK = 1 before loading Email::Send
-# to disable these warnings.
-BEGIN {
- $Return::Value::NO_CLUCK = 1;
-}
-use Email::Send;
-
our $sortkey = 1200;
sub get_param_list {
my $class = shift;
my @param_list = (
{
- name => 'mail_delivery_method',
- type => 's',
-
- # Bugzilla is not ready yet to send mails to newsgroups, and 'IO'
- # is of no use for now as we already have our own 'Test' mode.
- choices => [
- grep { $_ ne 'NNTP' && $_ ne 'IO' } Email::Send->new()->all_mailers(), 'None'
- ],
+ name => 'mail_delivery_method',
+ type => 's',
+ choices => ['Sendmail', 'SMTP', 'Test', 'None'],
default => 'Sendmail',
checker => \&check_mail_delivery_method
},
=item C<email> - The C<Email::MIME> object that's about to be sent.
-=item C<mailer_args> - An arrayref that's passed as C<mailer_args> to
-L<Email::Send/new>.
-
=back
=head2 object_before_create
use Date::Format qw(time2str);
-use Email::Address;
+use Email::Address::XS;
use Email::MIME;
use Encode qw(encode);
use Encode::MIME::Header;
use List::MoreUtils qw(none);
use Try::Tiny;
-# Return::Value 1.666002 pollutes the error log with warnings about this
-# deprecated module. We have to set NO_CLUCK = 1 before loading Email::Send
-# to disable these warnings.
-BEGIN {
- $Return::Value::NO_CLUCK = 1;
-}
-use Email::Send;
+use Email::Sender::Simple qw(sendmail);
+use Email::Sender::Transport::SMTP;
+use Bugzilla::Sender::Transport::Sendmail;
use Sys::Hostname;
use Bugzilla::Version qw(vers_cmp);
my $from = $email->header('From');
- my ($hostname, @args);
- my $mailer_class = $method;
+ my $hostname;
+ my $transport;
if ($method eq "Sendmail") {
- $mailer_class = 'Bugzilla::Send::Sendmail';
if (ON_WINDOWS) {
- $Email::Send::Sendmail::SENDMAIL = SENDMAIL_EXE;
+ $transport = Bugzilla::Sender::Transport::Sendmail->new({ sendmail => SENDMAIL_EXE });
}
- push @args, "-i";
-
- # We want to make sure that we pass *only* an email address.
- if ($from) {
- my ($email_obj) = Email::Address->parse($from);
- if ($email_obj) {
- my $from_email = $email_obj->address;
- push(@args, "-f$from_email") if $from_email;
- }
+ else {
+ $transport = Bugzilla::Sender::Transport::Sendmail->new();
}
}
else {
}
if ($method eq "SMTP") {
- push @args,
- Host => Bugzilla->params->{"smtpserver"},
- username => Bugzilla->params->{"smtp_username"},
- password => Bugzilla->params->{"smtp_password"},
- Hello => $hostname,
- Debug => Bugzilla->params->{'smtp_debug'};
+ my ($host, $port) = split(/:/, Bugzilla->params->{'smtpserver'}, 2);
+ $transport = Email::Sender::Transport::SMTP->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, mailer_args => \@args});
+ Bugzilla::Hook::process('mailer_before_send', {email => $email});
try {
my $to = $email->header('to') or die qq{Unable to find "To:" address\n};
- my @recipients = Email::Address->parse($to);
+ my @recipients = Email::Address::XS->parse($to);
die qq{Unable to parse "To:" address - $to\n} unless @recipients;
die qq{Did not expect more than one "To:" address in $to\n} if @recipients > 1;
+ die qq{Invalid address in "To:" address - $to\n} if !$recipients[0]->is_valid;
my $recipient = $recipients[0];
my $badhosts = Bugzilla::Bloomfilter->lookup("badhosts");
if ($badhosts && $badhosts->test($recipient->host)) {
close TESTFILE;
}
else {
- # This is useful for both Sendmail and Qmail, so we put it out here.
+ # This is useful for Sendmail, so we put it out here.
local $ENV{PATH} = SENDMAIL_PATH;
- my $mailer = Email::Send->new({mailer => $mailer_class, mailer_args => \@args});
- my $retval = $mailer->send($email);
- ThrowCodeError('mail_send_error', {msg => $retval, mail => $email}) if !$retval;
+ eval { sendmail($email, {transport => $transport}) };
+ if ($@) {
+ ThrowCodeError('mail_send_error', {msg => $@->message, mail => $email});
+ }
}
# insert into email_rates
use Bugzilla::Install::Util qw(indicate_progress);
use Bugzilla::Util qw(format_time trim generate_random_password);
-use Email::Address;
+use Email::Address::XS;
use Email::MIME;
use File::Basename;
use IO::File;
if ($originator !~ Bugzilla->params->{emailregexp}) {
# We use the raw header sometimes, because it looks like "From: user"
- # which Email::Address won't parse but we can still use.
+ # which Email::Address::XS won't parse but we can still use.
my $address = $email->header('From');
- my ($parsed) = Email::Address->parse($address);
- if ($parsed) {
+ my ($parsed) = Email::Address::XS->parse($address);
+ if ($parsed->is_valid) {
$address = $parsed->address;
}
if ($address) {
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
-package Bugzilla::Send::Sendmail;
+package Bugzilla::Sender::Transport::Sendmail;
+
use 5.10.1;
use strict;
use warnings;
-use base qw(Email::Send::Sendmail);
-
-use Return::Value;
-use Symbol qw(gensym);
+use parent qw(Email::Sender::Transport::Sendmail);
-sub send {
- my ($class, $message, @args) = @_;
- my $mailer = $class->_find_sendmail;
+use Email::Sender::Failure;
- return failure "Couldn't find 'sendmail' executable in your PATH"
- . " and Email::Send::Sendmail::SENDMAIL is not set"
- unless $mailer;
+sub send_email {
+ my ($self, $email, $envelope) = @_;
- return failure "Found $mailer but cannot execute it" unless -x $mailer;
+ my $pipe = $self->_sendmail_pipe($envelope);
- local $SIG{'CHLD'} = 'DEFAULT';
+ my $string = $email->as_string;
+ $string =~ s/\x0D\x0A/\x0A/g unless $^O eq 'MSWin32';
- my $pipe = gensym;
+ print $pipe $string
+ or Email::Sender::Failure->throw("couldn't send message to sendmail: $!");
- open($pipe, '|-', "$mailer -t -oi @args")
- || return failure "Error executing $mailer: $!";
- print($pipe $message->as_string)
- || return failure "Error printing via pipe to $mailer: $!";
unless (close $pipe) {
- return failure "error when closing pipe to $mailer: $!" if $!;
+ Email::Sender::Failure->throw("error when closing pipe to sendmail: $!") if $!;
my ($error_message, $is_transient) = _map_exitcode($? >> 8);
if (Bugzilla->get_param_with_override('use_mailer_queue')) {
# Return success for errors which are fatal so Bugzilla knows to
# remove them from the queue
if ($is_transient) {
- return failure "error when closing pipe to $mailer: $error_message";
+ Email::Sender::Failure->throw(
+ "error when closing pipe to sendmail: $error_message");
}
else {
- warn "error when closing pipe to $mailer: $error_message\n";
- return success;
+ warn "error when closing pipe to sendmail: $error_message\n";
+ return $self->success;
}
}
else {
- return failure "error when closing pipe to $mailer: $error_message";
+ Email::Sender::Failure->throw(
+ "error when closing pipe to sendmail: $error_message");
}
}
- return success;
+ return $self->success;
}
sub _map_exitcode {
# Returns (error message, is_transient)
- # from the sendmail source (sendmail/sysexit.h)
+ # from the sendmail source (sendmail/sysexits.h)
my $code = shift;
if ($code == 64) {
return ("Command line usage error (EX_USAGE)", 1);
1;
+=head1 B<Methods in need of POD>
+
+=over
+
+=item send_email
+
+=back
use DateTime::TimeZone;
use DateTime;
use Digest;
-use Email::Address;
+use Email::Address::XS;
use Encode qw(encode decode resolve_alias);
use Encode::Guess;
use English qw(-no_match_vars $EGID);
sub email_filter {
my ($toencode) = @_;
if (!Bugzilla->user->id) {
- my @emails = Email::Address->parse($toencode);
- if (scalar @emails) {
- my @hosts = map { quotemeta($_->host) } @emails;
- my $hosts_re = join('|', @hosts);
- $toencode =~ s/\@(?:$hosts_re)//g;
- return $toencode;
+ my $email_re = qr/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/;
+ my @hosts;
+ while ($toencode =~ /$email_re/g) {
+ my @emails = Email::Address::XS->parse($1);
+ if (scalar @emails) {
+ my @these_hosts = map { quotemeta($_->host) } @emails;
+ push @hosts, @these_hosts;
+ }
}
+ my $hosts_re = join('|', @hosts);
+
+ $toencode =~ s/\@(?:$hosts_re)//g;
+ return $toencode;
}
return $toencode;
}
my $match = Bugzilla->params->{'emailregexp'};
my $email = $addr . Bugzilla->params->{'emailsuffix'};
- # This regexp follows RFC 2822 section 3.4.1.
- my $addr_spec = $Email::Address::addr_spec;
-
- # RFC 2822 section 2.1 specifies that email addresses must
- # be made of US-ASCII characters only.
- # Email::Address::addr_spec doesn't enforce this.
+ my $address = Email::Address::XS->parse_bare_address($email);
if ( $addr =~ /$match/
+ && $address->is_valid
&& $email !~ /\P{ASCII}/
- && $email =~ /^$addr_spec$/
&& length($email) <= 127)
{
return 1;
-FROM bugzilla/bugzilla-perl-slim:20240320.1
+FROM bugzilla/bugzilla-perl-slim:20240322.1
ENV DEBIAN_FRONTEND noninteractive
'Devel::NYTProf' => '6.04',
'Digest::SHA' => '5.47',
'EV' => '4.0',
+ 'Email::Address::XS' => '1.05',
'Email::MIME' => '1.904',
- 'Email::Send' => '1.911',
+ 'Email::Sender' => '2.600',
'FFI::Platypus' => 0,
'Future' => '0.34',
'HTML::Escape' => '1.10',
upstream. Version 5.0 rewrote the email code to use currently-supported Perl
modules. That needs to be ported into Harmony.
+**[COMPLETED]**
+
# Postgresql Compatibility
We suspect, but don’t know for certain, that BMO may have moved to using
requires 'Devel::NYTProf', '6.04';
requires 'Digest::SHA', '5.47';
requires 'EV', '4.0';
-requires 'Email::Address';
+requires 'Email::Address::XS', '1.05';
requires 'Email::MIME', '1.904';
-requires 'Email::Send', '1.911';
+requires 'Email::Sender', '2.600';
requires 'FFI::Platypus';
requires 'File::Copy::Recursive';
requires 'File::MimeInfo::Magic';
}
use Data::Dumper;
-use Email::Address;
+use Email::Address::XS;
use Email::Reply qw(reply);
use Email::MIME;
use Email::MIME::Attachment::Stripper;
%fields = %{Bugzilla::Bug::map_fields(\%fields)};
- my ($reporter) = Email::Address->parse($input_email->header('From'));
+ my ($reporter) = Email::Address::XS->parse($input_email->header('From'));
$fields{'reporter'} = $reporter->address;
# The summary line only affects us if we're doing a post_bug.
use constant NAME => 'AntiSpam';
use constant REQUIRED_MODULES =>
- [{package => 'Email-Address', module => 'Email::Address', version => 0,},];
+ [{package => 'Email-Address-XS', module => 'Email::Address::XS', version => 1.01,},];
use constant OPTIONAL_MODULES => [];
__PACKAGE__->NAME;
use Bugzilla::Error;
use Bugzilla::Group;
use Bugzilla::Util qw(remote_ip);
-use Email::Address;
+use Email::Address::XS;
use Socket;
our $VERSION = '1';
sub _domain_blocking {
my ($self, $login) = @_;
- my $address = Email::Address->new(undef, $login);
+ my $address = Email::Address::XS->new(address => $login);
my $blocked
= Bugzilla->dbh->selectrow_array(
"SELECT 1 FROM antispam_domain_blocklist WHERE domain=?",
use Bugzilla::Install::Filesystem;
use Bugzilla::User;
use Bugzilla::Util qw(datetime_from time_ago);
-use Email::Address;
+use Email::Address::XS;
use Scalar::Util qw(blessed);
use List::MoreUtils qw(any);
sub _user_address {
my $mode = Bugzilla->usage_mode;
- Email::Address->disable_cache
- if any { $mode == $_ } USAGE_MODE_CMDLINE, USAGE_MODE_TEST, USAGE_MODE_EMAIL;
- return Email::Address->new(undef, $_[0]->email);
+ return Email::Address->new(address => $_[0]->email);
}
sub _user_set_last_activity_ts {
# hooks
#
-sub request_cleanup { Email::Address->purge_cache }
+# noop - Email::Address::XS no longer caches
+sub request_cleanup {}
sub bug_after_create {
my ($self, $args) = @_;
mail_delivery_method => "Defines how email is sent, or if it is sent at all.<br>
<ul>
<li>
- 'Sendmail', 'SMTP' and 'Qmail' are all MTAs.
+ 'Sendmail' and 'SMTP' are both MTAs.
You need to install a third-party sendmail replacement if
you want to use sendmail on Windows.
</li>
in 'data/mailer.testfile' instead of being sent.
</li>
<li>
- 'none' will completely disable email. $terms.Bugzilla continues
+ 'None' will completely disable email. Bugzilla continues
to act as though it is sending mail, but nothing is sent or
stored.
</li>