[Rt-commit] rt branch, 4.0/warn-on-non-ASCII-email-headers, created. rt-4.0.6-251-gad8cac9
Jim Brandt
jbrandt at bestpractical.com
Mon Jul 23 09:32:04 EDT 2012
The branch, 4.0/warn-on-non-ASCII-email-headers has been created
at ad8cac9da45a9a8264ad455ef1ae135faaad1e47 (commit)
- Log -----------------------------------------------------------------
commit 220063a15cb1bcb25bee21aac709fa46869dd5a7
Author: Jim Brandt <jbrandt at bestpractical.com>
Date: Fri Jul 13 09:43:28 2012 -0400
Avoid warnings with undef $From
diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index 2594e99..43b501d 100644
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -149,6 +149,9 @@ sub CheckForSuspiciousSender {
my ( $From, $junk ) = ParseSenderAddressFromHead($head);
+ # If unparseable (non-ASCII), $From can come back undef
+ return undef if not defined $From;
+
if ( ( $From =~ /^mailer-daemon\@/i )
or ( $From =~ /^postmaster\@/i )
or ( $From eq "" ))
commit ad8cac9da45a9a8264ad455ef1ae135faaad1e47
Author: Jim Brandt <jbrandt at bestpractical.com>
Date: Fri Jul 13 13:49:40 2012 -0400
Improve logging for failed sender parsing in email
Track email parsing failures in ParseSenderAddressFromHead and
pass them back as an optional third parameter. This allows the
caller to report the error if desired. Failure to parse one message
will generate an error, but the function can still find and return
a valid address from another header. This function is
called from several places and returning the error rather than reporting
avoids multiple warnings from parsing the same emails.
ParseSenderAddressFromHead still reports a failure to find a sender
in any header, since that is an error. That message will be reported
multiple times, one for each call to the function.
Update MailFrom.pm's GetCurrentUser to report the parse failures
as a warning. These parse failures are reported even if a sender
was found in another header. Also update the existing error in
GetCurrentUser to indicate that a parsing failure can also
prevent finding a valid sender.
diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index 43b501d..b4d13af 100644
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -1071,23 +1071,37 @@ sub ParseCcAddressesFromHead {
=head2 ParseSenderAddressFromHead HEAD
-Takes a MIME::Header object. Returns a tuple: (user at host, friendly name)
-of the From (evaluated in order of Reply-To:, From:, Sender)
+Takes a MIME::Header object. Returns (user at host, friendly name, error msg)
+where the first two values are the From (evaluated in order of
+Reply-To:, From:, Sender).
+
+An error msg may be returned even when a Sender value is found, since it
+could be a parse error for another sender field. In this case, the
+error isn't fatal, but may be useful to investigate the parse failure.
=cut
sub ParseSenderAddressFromHead {
my $head = shift;
+ my @sender_headers = ('Reply-To', 'From', 'Sender');
+ my $error_msg; # Accumulate any errors
#Figure out who's sending this message.
- foreach my $header ('Reply-To', 'From', 'Sender') {
+ foreach my $header ( @sender_headers ) {
my $addr_line = $head->get($header) || next;
my ($addr, $name) = ParseAddressFromHeader( $addr_line );
# only return if the address is not empty
- return ($addr, $name) if $addr;
+ return ($addr, $name, $error_msg) if $addr;
+
+ chomp $addr_line;
+ $error_msg = "Failed to parse sender using " if not $error_msg;
+ $error_msg .= "$header: $addr_line";
}
- return (undef, undef);
+ $RT::Logger->warning("Couldn't find a sender in "
+ . join(', ', @sender_headers) );
+
+ return (undef, undef, $error_msg);
}
=head2 ParseErrorsToAddressFromHead HEAD
diff --git a/lib/RT/Interface/Email/Auth/MailFrom.pm b/lib/RT/Interface/Email/Auth/MailFrom.pm
index e733bda..e7fcd97 100644
--- a/lib/RT/Interface/Email/Auth/MailFrom.pm
+++ b/lib/RT/Interface/Email/Auth/MailFrom.pm
@@ -66,9 +66,11 @@ sub GetCurrentUser {
# We don't need to do any external lookups
- my ( $Address, $Name ) = ParseSenderAddressFromHead( $args{'Message'}->head );
+ my ( $Address, $Name, $Error_msg ) = ParseSenderAddressFromHead( $args{'Message'}->head );
+ $RT::Logger->warning($Error_msg) if $Error_msg;
+
unless ( $Address ) {
- $RT::Logger->error("Couldn't find sender's address");
+ $RT::Logger->error("Couldn't parse or find sender's address");
return ( $args{'CurrentUser'}, -1 );
}
diff --git a/t/mail/header-characters.t b/t/mail/header-characters.t
new file mode 100644
index 0000000..296329b
--- /dev/null
+++ b/t/mail/header-characters.t
@@ -0,0 +1,80 @@
+use strict;
+use warnings;
+
+use RT::Test tests => 12;
+use Test::Warn;
+
+my ($baseurl, $m) = RT::Test->started_ok;
+
+diag "Testing non-ASCII in From: header";
+{
+ my $mail = <<'.';
+From: René@example.com>
+Reply-To: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
+Subject: testing non-ASCII From
+Content-Type: text/plain; charset=iso-8859-1
+
+here's some content
+.
+
+ my ($status, $id);
+ warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
+ [qr/Couldn't find a sender in/,
+ qr/Couldn't find a sender in/,
+ qr/Failed to parse sender using/,
+ qr/Couldn't parse or find sender's address/
+ ],
+ 'Got parse error for non-ASCII in From';
+ is( $status >> 8, 0, "The mail gateway exited normally" );
+ TODO: {
+ local $TODO = "Currently don't handle non-ASCII for sender";
+ ok( $id, "Created ticket" );
+ }
+}
+
+diag "Testing iso-8859-1 encoded non-ASCII in From: header";
+{
+ my $mail = <<'.';
+From: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
+Reply-To: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
+Subject: testing non-ASCII From
+Content-Type: text/plain; charset=iso-8859-1
+
+here's some content
+.
+
+ my ($status, $id);
+ warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
+ [qr/Couldn't find a sender in/,
+ qr/Couldn't find a sender in/,
+ qr/Failed to parse sender using/,
+ qr/Couldn't parse or find sender's address/
+ ],
+ 'Got parse error for iso-8859-1 in From';
+ is( $status >> 8, 0, "The mail gateway exited normally" );
+ TODO: {
+ local $TODO = "Currently don't handle non-ASCII in sender";
+ ok( $id, "Created ticket" );
+ }
+}
+
+diag "No sender";
+{
+ my $mail = <<'.';
+To: rt at example.com
+Subject: testing non-ASCII From
+Content-Type: text/plain; charset=iso-8859-1
+
+here's some content
+.
+
+ my ($status, $id);
+ warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
+ [qr/Couldn't find a sender in/,
+ qr/Couldn't find a sender in/,
+ qr/Couldn't parse or find sender's address/
+ ],
+ 'Got parse error with no sender fields';
+ is( $status >> 8, 0, "The mail gateway exited normally" );
+ ok( !$id, "No ticket created" );
+}
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list