[Rt-commit] rt branch, 4.2-on-4.0/protect-more-chars-while-decoding-headers, created. rt-4.0.12-23-g31d5025

Alex Vandiver alexmv at bestpractical.com
Thu May 9 17:11:33 EDT 2013


The branch, 4.2-on-4.0/protect-more-chars-while-decoding-headers has been created
        at  31d50251f9c0ea83b98c1e24316a1430dfa65a9b (commit)

- Log -----------------------------------------------------------------
commit 7bcd6c0abcd1f9273efc020df2107baa0c59efda
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Dec 24 22:08:18 2012 +0400

    ';' can not be used to separate emails in Cc field
    
    Semicolon is used to end a group if there is a group, but
    can not be used to separate emails without group.

diff --git a/t/mail/specials-in-encodedwords.t b/t/mail/specials-in-encodedwords.t
index f9da9c6..36efcd5 100644
--- a/t/mail/specials-in-encodedwords.t
+++ b/t/mail/specials-in-encodedwords.t
@@ -14,7 +14,7 @@ diag "specials (, and ;) in MIME encoded-words aren't treated as specials";
 From: root at localhost
 Subject: testing mime encoded specials
 Cc: a at example.com, =?utf8?q?d=40example.com=2ce=40example.com=3b?=
-    <b at example.com>; c at example.com
+    <b at example.com>, c at example.com
 Content-Type: text/plain; charset=utf8
 
 here's some content

commit fc7cabb0f09f94edce23eb70d0309b4e5a733b08
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Jun 28 23:08:45 2012 +0300

    change how we deal with decoding structured fields
    
    When we get rid of encoded words in formatted fields (From/To/Cc,
    Content-Disposition, Content-Type...), we have to take care of
    preserving structure of the field which means quoting parts. Old code
    were using luck and magic to achieve this instead of parsing field's
    structure.
    
    We use MIME::Field::ParamVal already to deal with continued params
    (RFC2231). This module allows us to deal with separate parameters,
    decode them and deal with quotes inside or absence of those without
    guessing.
    
    Bump the version to a version which fixes a bug [1] in parsing of quoted
    strings and quoting on stringify.
    
    Similar situation with From, Cc, Bcc and other fields with mailboxes. We
    were only dealing with subset of mailbox fields, now we handle all such
    headers that are mentioned in RFC5322.
    
    Switch to Email::Address::List to parse headers with mailboxes. Allows
    us to report errors, handles obsolete emails, don't bails out on not
    ascii.
    
    Email::Address is still used and a bug [2] was discovered in the module
    that may result in unparsable string after re-composing.
    
    [1] https://rt.cpan.org/Ticket/Display.html?id=80433
    [2] https://rt.cpan.org/Ticket/Display.html?id=81170

diff --git a/lib/RT/EmailParser.pm b/lib/RT/EmailParser.pm
index d4a261e..0754870 100644
--- a/lib/RT/EmailParser.pm
+++ b/lib/RT/EmailParser.pm
@@ -526,28 +526,42 @@ we can use that removes the bandaid
 
 =cut
 
+use Email::Address::List;
+
 sub ParseEmailAddress {
     my $self = shift;
     my $address_string = shift;
 
-    $address_string =~ s/^\s+|\s+$//g;
+    my @list = Email::Address::List->parse(
+        $address_string,
+        skip_comments => 1,
+        skip_groups => 1,
+    );
+    my $logger = sub { RT->Logger->error(
+        "Unable to parse an email address from $address_string: ". shift
+    ) };
 
     my @addresses;
-    # if it looks like a username / local only email
-    if ($address_string !~ /@/ && $address_string =~ /^\w+$/) {
-        my $user = RT::User->new( RT->SystemUser );
-        my ($id, $msg) = $user->Load($address_string);
-        if ($id) {
-            push @addresses, Email::Address->new($user->Name,$user->EmailAddress);
+    foreach my $e ( @list ) {
+        if ($e->{'type'} eq 'mailbox') {
+            if ($e->{'not_ascii'}) {
+                $logger->($e->{'value'} ." contains not ASCII values");
+                next;
+            }
+            push @addresses, $e->{'value'}
+        } elsif ( $e->{'value'} =~ /^\s*(\w+)\s*$/ ) {
+            my $user = RT::User->new( RT->SystemUser );
+            $user->Load( $1 );
+            if ($user->id) {
+                push @addresses, Email::Address->new($user->Name, $user->EmailAddress);
+            } else {
+                $logger->($e->{'value'} ." is not a valid email address and is not user name");
+            }
         } else {
-            $RT::Logger->error("Unable to parse an email address from $address_string: $msg");
+            $logger->($e->{'value'} ." is not a valid email address");
         }
-    } else {
-        @addresses = Email::Address->parse($address_string);
     }
-
     return @addresses;
-
 }
 
 =head2 RescueOutlook 
diff --git a/lib/RT/I18N.pm b/lib/RT/I18N.pm
index 0e75b9f..65ae627 100644
--- a/lib/RT/I18N.pm
+++ b/lib/RT/I18N.pm
@@ -295,14 +295,65 @@ sub DecodeMIMEWordsToEncoding {
     my $str = shift;
     my $to_charset = _CanonicalizeCharset(shift);
     my $field = shift || '';
+    $RT::Logger->warning(
+        "DecodeMIMEWordsToEncoding was called without field name."
+        ."It's known to cause troubles with decoding fields properly."
+    ) unless $field;
+
+    # XXX TODO: RT doesn't currently do the right thing with mime-encoded headers
+    # We _should_ be preserving them encoded until after parsing is completed and
+    # THEN undo the mime-encoding.
+    #
+    # This routine should be translating the existing mimeencoding to utf8 but leaving
+    # things encoded.
+    #
+    # It's legal for headers to contain mime-encoded commas and semicolons which
+    # should not be treated as address separators. (Encoding == quoting here)
+    #
+    # until this is fixed, we must escape any string containing a comma or semicolon
+    # this is only a bandaid
+
+    # Some _other_ MUAs encode quotes _already_, and double quotes
+    # confuse us a lot, so only quote it if it isn't quoted
+    # already.
 
     # handle filename*=ISO-8859-1''%74%E9%73%74%2E%74%78%74, parameter value
     # continuations, and similar syntax from RFC 2231
-    if ($field =~ /^Content-(Type|Disposition)/i) {
+    if ($field =~ /^Content-/i) {
         # This concatenates continued parameters and normalizes encoded params
         # to QB encoded-words which we handle below
-        $str = MIME::Field::ParamVal->parse($str)->stringify;
+        my $params = MIME::Field::ParamVal->parse_params($str);
+        foreach my $v ( values %$params ) {
+            $v = _DecodeMIMEWordsToEncoding( $v, $to_charset );
+        }
+        $str = bless({}, 'MIME::Field::ParamVal')->set($params)->stringify;
+    }
+    elsif ( $field =~ /^(?:Resent-)?(?:To|From|B?Cc|Sender|Reply-To)$/i ) {
+        my @addresses = RT::EmailParser->ParseEmailAddress( $str );
+        foreach my $address ( @addresses ) {
+            foreach my $field (qw(phrase comment)) {
+                my $v = $address->$field() or next;
+                $v = _DecodeMIMEWordsToEncoding( $v, $to_charset );
+                $address->$field($v);
+            }
+        }
+        $str = join ', ', map $_->format, @addresses;
     }
+    else {
+        $str = _DecodeMIMEWordsToEncoding( $str, $to_charset );
+    }
+
+
+    # We might have \n without trailing whitespace, which will result in
+    # invalid headers.
+    $str =~ s/\n//g;
+
+    return ($str)
+}
+
+sub _DecodeMIMEWordsToEncoding {
+    my $str = shift;
+    my $to_charset = shift;
 
     # Pre-parse by removing all whitespace between encoded words
     my $encoded_word = qr/
@@ -330,79 +381,51 @@ sub DecodeMIMEWordsToEncoding {
                          $encoded_word
                          ([^=]*)        # trailing
                         /xgcs;
+    return $str unless @list;
+
+    # add everything that hasn't matched to the end of the latest
+    # string in array this happen when we have 'key="=?encoded?="; key="plain"'
+    $list[-1] .= substr($str, pos $str);
+
+    $str = '';
+    while (@list) {
+        my ($prefix, $charset, $encoding, $enc_str, $trailing) =
+                splice @list, 0, 5;
+        $charset  = _CanonicalizeCharset($charset);
+        $encoding = lc $encoding;
+
+        $trailing =~ s/\s?\t?$//;               # Observed from Outlook Express
+
+        if ( $encoding eq 'q' ) {
+            use MIME::QuotedPrint;
+            $enc_str =~ tr/_/ /;		# Observed from Outlook Express
+            $enc_str = decode_qp($enc_str);
+        } elsif ( $encoding eq 'b' ) {
+            use MIME::Base64;
+            $enc_str = decode_base64($enc_str);
+        } else {
+            $RT::Logger->warning("Incorrect encoding '$encoding' in '$str', "
+                ."only Q(uoted-printable) and B(ase64) are supported");
+        }
 
-    if ( @list ) {
-        # add everything that hasn't matched to the end of the latest
-        # string in array this happen when we have 'key="=?encoded?="; key="plain"'
-        $list[-1] .= substr($str, pos $str);
-
-        $str = "";
-        while (@list) {
-            my ($prefix, $charset, $encoding, $enc_str, $trailing) =
-                    splice @list, 0, 5;
-            $charset  = _CanonicalizeCharset($charset);
-            $encoding = lc $encoding;
-
-            $trailing =~ s/\s?\t?$//;               # Observed from Outlook Express
-
-            if ( $encoding eq 'q' ) {
-                use MIME::QuotedPrint;
-                $enc_str =~ tr/_/ /;		# Observed from Outlook Express
-                $enc_str = decode_qp($enc_str);
-            } elsif ( $encoding eq 'b' ) {
-                use MIME::Base64;
-                $enc_str = decode_base64($enc_str);
+        # now we have got a decoded subject, try to convert into the encoding
+        if ( $charset ne $to_charset || $charset =~ /^utf-?8(?:-strict)?$/i ) {
+            if ( Encode::find_encoding($charset) ) {
+                Encode::from_to( $enc_str, $charset, $to_charset );
             } else {
-                $RT::Logger->warning("Incorrect encoding '$encoding' in '$str', "
-                    ."only Q(uoted-printable) and B(ase64) are supported");
-            }
-
-            # now we have got a decoded subject, try to convert into the encoding
-            if ( $charset ne $to_charset || $charset =~ /^utf-?8(?:-strict)?$/i ) {
-                if ( Encode::find_encoding($charset) ) {
-                    Encode::from_to( $enc_str, $charset, $to_charset );
-                } else {
-                    $RT::Logger->warning("Charset '$charset' is not supported");
-                    $enc_str =~ s/[^[:print:]]/\357\277\275/g;
-                    Encode::from_to( $enc_str, 'UTF-8', $to_charset )
-                        unless $to_charset eq 'utf-8';
-                }
+                $RT::Logger->warning("Charset '$charset' is not supported");
+                $enc_str =~ s/[^[:print:]]/\357\277\275/g;
+                Encode::from_to( $enc_str, 'UTF-8', $to_charset )
+                    unless $to_charset eq 'utf-8';
             }
-
-            # XXX TODO: RT doesn't currently do the right thing with mime-encoded headers
-            # We _should_ be preserving them encoded until after parsing is completed and
-            # THEN undo the mime-encoding.
-            #
-            # This routine should be translating the existing mimeencoding to utf8 but leaving
-            # things encoded.
-            #
-            # It's legal for headers to contain mime-encoded commas and semicolons which
-            # should not be treated as address separators. (Encoding == quoting here)
-            #
-            # until this is fixed, we must escape any string containing a comma or semicolon
-            # this is only a bandaid
-
-            # Some _other_ MUAs encode quotes _already_, and double quotes
-            # confuse us a lot, so only quote it if it isn't quoted
-            # already.
-            $enc_str = qq{"$enc_str"}
-                if $enc_str =~ /[,;]/
-                and $enc_str !~ /^".*"$/
-                and (!$field || $field =~ /^(?:To$|From$|B?Cc$|Content-)/i);
-
-            $str .= $prefix . $enc_str . $trailing;
         }
+        $str .= $prefix . $enc_str . $trailing;
     }
 
-    # We might have \n without trailing whitespace, which will result in
-    # invalid headers.
-    $str =~ s/\n//g;
-
     return ($str)
 }
 
 
-
 =head2 _FindOrGuessCharset MIME::Entity, $head_only
 
 When handed a MIME::Entity will first attempt to read what charset the message is encoded in. Failing that, will use Encode::Guess to try to figure it out
diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 26593d9..6961551 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -200,9 +200,10 @@ Sys::Syslog 0.16
 Locale::Maketext 1.06
 Locale::Maketext::Lexicon 0.32
 Locale::Maketext::Fuzzy
-MIME::Entity 5.425
+MIME::Entity 5.504
 Mail::Mailer 1.57
-Email::Address
+Email::Address 1.897
+Email::Address::List
 Text::Wrapper 
 Time::ParseDate
 Time::HiRes 
diff --git a/t/mail/dashboards.t b/t/mail/dashboards.t
index edd4553..fe317d4 100644
--- a/t/mail/dashboards.t
+++ b/t/mail/dashboards.t
@@ -101,7 +101,7 @@ sub produces_dashboard_mail_ok { # {{{
 
     my $mail = parse_mail( $mails[0] );
     is($mail->head->get('Subject'), $subject);
-    is($mail->head->get('From'), "root\n");
+    is($mail->head->get('From'), qq{"root" <root\@localhost>\n});
     is($mail->head->get('X-RT-Dashboard-Id'), "$dashboard_id\n");
     is($mail->head->get('X-RT-Dashboard-Subscription-Id'), "$subscription_id\n");
 
diff --git a/t/mail/mime_decoding.t b/t/mail/mime_decoding.t
index 4b3e3c0..311903f 100644
--- a/t/mail/mime_decoding.t
+++ b/t/mail/mime_decoding.t
@@ -12,6 +12,11 @@ diag q{'=' char in a leading part before an encoded part};
         'key="plain"; key="мой_файл.bin"',
         "right decoding"
     );
+    is(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
+        'key="plain"; key="мой_файл.bin"',
+        "right decoding"
+    );
 }
 
 diag q{not compliant with standards, but MUAs send such field when attachment has non-ascii in name};
@@ -22,6 +27,11 @@ diag q{not compliant with standards, but MUAs send such field when attachment ha
         'attachment; filename="мой_файл.bin"',
         "right decoding"
     );
+    is(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
+        'attachment; filename="мой_файл.bin"',
+        "right decoding"
+    );
 }
 
 diag q{'=' char in a trailing part after an encoded part};
@@ -32,6 +42,11 @@ diag q{'=' char in a trailing part after an encoded part};
         'attachment; filename="мой_файл.bin"; some_prop="value"',
         "right decoding"
     );
+    is(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
+        'attachment; filename="мой_файл.bin"; some_prop="value"',
+        "right decoding"
+    );
 }
 
 diag q{regression test for #5248 from rt3.fsck.com};
@@ -39,7 +54,7 @@ diag q{regression test for #5248 from rt3.fsck.com};
     my $str = qq{Subject: =?ISO-8859-1?Q?Re=3A_=5BXXXXXX=23269=5D_=5BComment=5D_Frag?=}
         . qq{\n =?ISO-8859-1?Q?e_zu_XXXXXX--xxxxxx_/_Xxxxx=FCxxxxxxxxxx?=};
     is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Subject'),
         qq{Subject: Re: [XXXXXX#269] [Comment] Frage zu XXXXXX--xxxxxx / Xxxxxüxxxxxxxxxx},
         "right decoding"
     );
@@ -53,6 +68,11 @@ diag q{newline and encoded file name};
         qq{application/vnd.ms-powerpoint;\tname="Main presentation.ppt"},
         "right decoding"
     );
+    is(
+        RT::I18N::DecodeMIMEWordsToUTF8($str,'content-type'),
+        qq{application/vnd.ms-powerpoint; name="Main presentation.ppt"},
+        "right decoding"
+    );
 }
 
 diag q{rfc2231};

commit ff728bc9082c87d3d9448270c6aa85a7fcaa4000
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Nov 17 22:20:47 2012 +0400

    deal with hidden quotes within encoded-word
    
    After decoding a part (a param value or display name)
    may contain a quoted string inside, we de-quote and
    de-escape it just to avoid useless quotes.

diff --git a/lib/RT/I18N.pm b/lib/RT/I18N.pm
index 65ae627..6e7354d 100644
--- a/lib/RT/I18N.pm
+++ b/lib/RT/I18N.pm
@@ -325,6 +325,8 @@ sub DecodeMIMEWordsToEncoding {
         my $params = MIME::Field::ParamVal->parse_params($str);
         foreach my $v ( values %$params ) {
             $v = _DecodeMIMEWordsToEncoding( $v, $to_charset );
+            # de-quote in case those were hidden inside encoded part
+            $v =~ s/\\(.)/$1/g if $v =~ s/^"(.*)"$/$1/;
         }
         $str = bless({}, 'MIME::Field::ParamVal')->set($params)->stringify;
     }
@@ -334,6 +336,10 @@ sub DecodeMIMEWordsToEncoding {
             foreach my $field (qw(phrase comment)) {
                 my $v = $address->$field() or next;
                 $v = _DecodeMIMEWordsToEncoding( $v, $to_charset );
+                if ( $field eq 'phrase' ) {
+                    # de-quote in case quoted value were hidden inside encoded part
+                    $v =~ s/\\(.)/$1/g if $v =~ s/^"(.*)"$/$1/;
+                }
                 $address->$field($v);
             }
         }

commit 6c78d437d02f4fc55547d17cfd0aaa3a2b2e489e
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Fri Oct 26 15:50:53 2012 -0700

    test more MIME word decoding cases

diff --git a/t/mail/mime_decoding.t b/t/mail/mime_decoding.t
index 311903f..afb2032 100644
--- a/t/mail/mime_decoding.t
+++ b/t/mail/mime_decoding.t
@@ -1,6 +1,7 @@
 use strict;
 use warnings;
-use RT::Test nodb => 1, tests => 13;
+use RT::Test nodb => 1, tests => undef;
+use Test::LongString;
 
 use_ok('RT::I18N');
 
@@ -116,7 +117,6 @@ diag q{canonicalize mime word encodings like gb2312};
     );
 }
 
-
 diag q{Whitespace between encoded words should be removed};
 {
     my $str = "=?utf-8?Q?=E3=82=AD?=    =?utf-8?Q?=E3=83=A3?=";
@@ -158,3 +158,63 @@ EOT
     );
 
 }
+
+diag "multiple mime words containing special chars already in quotes";
+{
+    my $str = q{attachment; filename="=?ISO-2022-JP?B?Mi4bJEIlSyVlITwlOSVqJWohPCU5GyhC?= =?ISO-2022-JP?B?LnBkZg==?="};
+    is_string(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+        q{attachment; filename="2.ニュースリリース.pdf"},
+        "base64"
+    );
+
+    $str = q{attachment; filename="=?UTF-8?Q?2=2E=E3=83=8B=E3=83=A5=E3=83=BC=E3=82=B9=E3=83=AA=E3=83=AA?= =?UTF-8?Q?=E3=83=BC=E3=82=B9=2Epdf?="};
+    is_string(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+        q{attachment; filename="2.ニュースリリース.pdf"},
+        "QP"
+    );
+}
+
+diag "mime word combined with text in quoted filename property";
+{
+    my $str = q{attachment; filename="=?UTF-8?B?Q2VjaSBuJ2VzdCBwYXMgdW5l?= pipe.pdf"};
+    is_string(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+        q{attachment; filename="Ceci n'est pas une pipe.pdf"},
+        "base64"
+    );
+
+    $str = q{attachment; filename="=?UTF-8?B?Q2VjaSBuJ2VzdCBwYXMgdW5lLi4u?= pipe.pdf"};
+    is_string(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+        q{attachment; filename="Ceci n'est pas une... pipe.pdf"},
+        "base64"
+    );
+
+    $str = q{attachment; filename="=?UTF-8?Q?Ceci n'est pas une?= pipe.pdf"};
+    is_string(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+        q{attachment; filename="Ceci n'est pas une pipe.pdf"},
+        "QP"
+    );
+
+    $str = q{attachment; filename="=?UTF-8?Q?Ceci n'est pas une...?= pipe.pdf"};
+    is_string(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+        q{attachment; filename="Ceci n'est pas une... pipe.pdf"},
+        "QP"
+    );
+}
+
+diag "quotes in filename";
+{
+    my $str = q{attachment; filename="=?UTF-8?B?YSAicXVvdGVkIiBmaWxl?="};
+    is_string(
+        RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+        q{attachment; filename="a \"quoted\" file"},
+        "quoted filename correctly decoded"
+    );
+}
+
+done_testing;

commit 141986480efb94751bb80b8dd288bcb4d7fc6d7f
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed May 8 15:36:00 2013 -0700

    Tests: Adjust diagnostic descriptions to match what's actually being tested

diff --git a/t/mail/header-characters.t b/t/mail/header-characters.t
index fe06d1a..10952ea 100644
--- a/t/mail/header-characters.t
+++ b/t/mail/header-characters.t
@@ -8,7 +8,7 @@ use Encode;
 
 my ($baseurl, $m) = RT::Test->started_ok;
 
-diag "Testing non-ASCII in From: header";
+diag "Testing non-ASCII latin1 in From: header";
 SKIP:{
     skip "Test requires Email::Address 1.893 or later, "
       . "you have $Email::Address::VERSION", 3,
@@ -36,7 +36,7 @@ here's some content
       }
 }
 
-diag "Testing iso-8859-1 encoded non-ASCII in From: header";
+diag "Testing non-ASCII latin1 in From: header with MIME-word-encoded phrase";
 SKIP:{
     skip "Test requires Email::Address 1.893 or later, "
       . "you have $Email::Address::VERSION", 3,

commit bc30f4742bf18ac28b65ec8ed0d82fbeee600cf2
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed May 8 15:42:16 2013 -0700

    Tests: Correct a typo'd email address in the From: header

diff --git a/t/mail/header-characters.t b/t/mail/header-characters.t
index 10952ea..46e596e 100644
--- a/t/mail/header-characters.t
+++ b/t/mail/header-characters.t
@@ -15,7 +15,7 @@ SKIP:{
       if $Email::Address::VERSION < 1.893;
 
     my $mail = encode( 'iso-8859-1', <<'.' );
-From: René@example.com>
+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

commit 6b2e53315d2fa2c66410a725acd4fa0e51bb2849
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed May 8 15:42:39 2013 -0700

    Tests: Catch the new "unparseable email address" warnings
    
    A warning is now issued for each header field instead of a single
    warning for all sender fields.

diff --git a/t/mail/header-characters.t b/t/mail/header-characters.t
index 46e596e..97fdd62 100644
--- a/t/mail/header-characters.t
+++ b/t/mail/header-characters.t
@@ -25,7 +25,7 @@ here's some content
 
     my ($status, $id);
     warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
-        [qr/Failed to parse Reply-To:.*, From:/,
+        [(qr/Unable to parse an email address from/) x 2,
          qr/Couldn't parse or find sender's address/
         ],
         'Got parse error for non-ASCII in From';
@@ -53,7 +53,7 @@ here's some content
 
     my ($status, $id);
     warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
-        [qr/Failed to parse Reply-To:.*, From:/,
+        [(qr/Unable to parse an email address from/) x 2,
          qr/Couldn't parse or find sender's address/
         ],
         'Got parse error for iso-8859-1 in From';

commit 6e1cfa14ec4395388b943486b38a83b5e0fae43e
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed May 8 15:37:22 2013 -0700

    Tests: Remove Requestors from approval templates
    
    The ->Requestors method returns an RT::Group object which stringified
    during template interpolation.  The new email address parsing balks at
    RT::Group=HASH(0xDEADBEEF), appropriately so.  Providing the actual
    requestor email addresses would cause autoreplies to go out and the rest
    of the test assumptions to break, so simply remove the requestors all
    together.  Generally approval tickets don't use requestors in real use
    cases anyway.

diff --git a/t/approval/admincc.t b/t/approval/admincc.t
index b439296..92b7f5f 100644
--- a/t/approval/admincc.t
+++ b/t/approval/admincc.t
@@ -42,7 +42,6 @@ Queue: ___Approvals
 Type: approval
 Owner: CTO
 AdminCCs: COO, CEO
-Requestors: {$Tickets{"TOP"}->Requestors}
 DependedOnBy: TOP
 Subject: CTO Approval for PO: {$Tickets{"TOP"}->Id} - {$Tickets{"TOP"}->Subject}
 Due: {time + 86400}
diff --git a/t/approval/basic.t b/t/approval/basic.t
index 2d00eb5..31b869c 100644
--- a/t/approval/basic.t
+++ b/t/approval/basic.t
@@ -33,7 +33,6 @@ my $approvals =
 Queue: ___Approvals
 Type: approval
 Owner: CFO
-Requestors: {$Tickets{"TOP"}->Requestors}
 Refers-To: TOP
 Subject: CFO Approval for PO: {$Tickets{"TOP"}->Id} - {$Tickets{"TOP"}->Subject}
 Due: {time + 86400}
@@ -46,7 +45,6 @@ ENDOFCONTENT
 Queue: ___Approvals
 Type: approval
 Owner: CEO
-Requestors: {$Tickets{"TOP"}->Requestors}
 Subject: PO approval request for {$Tickets{"TOP"}->Subject}
 Refers-To: TOP
 Depends-On: for-CFO

commit 52c44bb6d4d7e65f45026bec9a837be3419823f7
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed May 8 15:41:06 2013 -0700

    Tests: Catch warnings when calling DecodeMIMEWordsTo* without a field name
    
    Or provide a field name when possible to avoid the warnings altogether.
    We explicitly test without field names to compare results, but no where
    in core RT should do the same.

diff --git a/t/mail/mime_decoding.t b/t/mail/mime_decoding.t
index afb2032..b6d371c 100644
--- a/t/mail/mime_decoding.t
+++ b/t/mail/mime_decoding.t
@@ -2,17 +2,20 @@ use strict;
 use warnings;
 use RT::Test nodb => 1, tests => undef;
 use Test::LongString;
+use Test::Warn;
 
 use_ok('RT::I18N');
 
 diag q{'=' char in a leading part before an encoded part};
 {
     my $str = 'key="plain"; key="=?UTF-8?B?0LzQvtC5X9GE0LDQudC7LmJpbg==?="';
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        'key="plain"; key="мой_файл.bin"',
-        "right decoding"
-    );
+    warnings_like {
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            'key="plain"; key="мой_файл.bin"',
+            "right decoding"
+        );
+    } [qr/DecodeMIMEWordsTo.*?called without field name/i];
     is(
         RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
         'key="plain"; key="мой_файл.bin"',
@@ -23,11 +26,13 @@ diag q{'=' char in a leading part before an encoded part};
 diag q{not compliant with standards, but MUAs send such field when attachment has non-ascii in name};
 {
     my $str = 'attachment; filename="=?UTF-8?B?0LzQvtC5X9GE0LDQudC7LmJpbg==?="';
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        'attachment; filename="мой_файл.bin"',
-        "right decoding"
-    );
+    warnings_like {
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            'attachment; filename="мой_файл.bin"',
+            "right decoding"
+        );
+    } [qr/DecodeMIMEWordsTo.*?called without field name/i];
     is(
         RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
         'attachment; filename="мой_файл.bin"',
@@ -38,11 +43,13 @@ diag q{not compliant with standards, but MUAs send such field when attachment ha
 diag q{'=' char in a trailing part after an encoded part};
 {
     my $str = 'attachment; filename="=?UTF-8?B?0LzQvtC5X9GE0LDQudC7LmJpbg==?="; some_prop="value"';
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        'attachment; filename="мой_файл.bin"; some_prop="value"',
-        "right decoding"
-    );
+    warnings_like {
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            'attachment; filename="мой_файл.bin"; some_prop="value"',
+            "right decoding"
+        );
+    } [qr/DecodeMIMEWordsTo.*?called without field name/i];
     is(
         RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
         'attachment; filename="мой_файл.bin"; some_prop="value"',
@@ -64,11 +71,13 @@ diag q{regression test for #5248 from rt3.fsck.com};
 diag q{newline and encoded file name};
 {
     my $str = qq{application/vnd.ms-powerpoint;\n\tname="=?ISO-8859-1?Q?Main_presentation.ppt?="};
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        qq{application/vnd.ms-powerpoint;\tname="Main presentation.ppt"},
-        "right decoding"
-    );
+    warnings_like {
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            qq{application/vnd.ms-powerpoint;\tname="Main presentation.ppt"},
+            "right decoding"
+        );
+    } [qr/DecodeMIMEWordsTo.*?called without field name/i];
     is(
         RT::I18N::DecodeMIMEWordsToUTF8($str,'content-type'),
         qq{application/vnd.ms-powerpoint; name="Main presentation.ppt"},
@@ -111,7 +120,7 @@ diag q{canonicalize mime word encodings like gb2312};
 	=?gb2312?B?dHRhY2hlbWVudCB0ZXN0IGluIENOIHNpbXBsaWZpZWQ=?=};
 
     is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
+        RT::I18N::DecodeMIMEWordsToUTF8($str, "Subject"),
         qq{Subject: 在世界各地共有超過_Simplified_CN_GB2312attachement test in CN simplified},
         "right decoding"
     );
@@ -119,44 +128,47 @@ diag q{canonicalize mime word encodings like gb2312};
 
 diag q{Whitespace between encoded words should be removed};
 {
-    my $str = "=?utf-8?Q?=E3=82=AD?=    =?utf-8?Q?=E3=83=A3?=";
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        "キャ",
-        "whitespace between encoded words is removed",
-    );
-
-    $str = "=?utf-8?Q?=E3=82=AD?=  \n   =?utf-8?Q?=E3=83=A3?=";
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        "キャ",
-        "newlines between encoded words also removed",
-    );
+    warnings_like {
+        my $str = "=?utf-8?Q?=E3=82=AD?=    =?utf-8?Q?=E3=83=A3?=";
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            "キャ",
+            "whitespace between encoded words is removed",
+        );
+
+        $str = "=?utf-8?Q?=E3=82=AD?=  \n   =?utf-8?Q?=E3=83=A3?=";
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            "キャ",
+            "newlines between encoded words also removed",
+        );
+    } [(qr/DecodeMIMEWordsTo.*?called without field name/i) x 2];
 }
 
 diag q{Multiple octets split across QP hunks are correctly reassembled};
 {
-    # This passes even without explicit code to handle it because utf8
-    # is perl's internal string encoding.
-    my $str = "=?utf-8?Q?=E3?=    =?utf-8?Q?=82?=    =?utf-8?Q?=AD?=";
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        "ã‚­",
-        "UTF8 character split in three is successfully reassembled",
-    );
-
-    # Non-utf8 encodings thus also must be checked
-    $str = <<EOT; chomp $str;
+    warnings_like {
+        # This passes even without explicit code to handle it because utf8
+        # is perl's internal string encoding.
+        my $str = "=?utf-8?Q?=E3?=    =?utf-8?Q?=82?=    =?utf-8?Q?=AD?=";
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            "ã‚­",
+            "UTF8 character split in three is successfully reassembled",
+        );
+
+        # Non-utf8 encodings thus also must be checked
+        $str = <<EOT; chomp $str;
 =?gb2312?q?Chinese(gb2312)=20=20=C3=C0=B9=FA=C7=B0=CB=BE=B7=A8=B2=BF=B3?=
  =?gb2312?q?=A4=C3=E6=BC=FB=C8=F8=B4=EF=C4=B7=BA=F3=B3=C6=C6=E4=D7=B4=CC=AC?=
  =?gb2312?q?=BA=DC=BA=C3=20=20Chinese=20(gb2312)?=
 EOT
-    is(
-        RT::I18N::DecodeMIMEWordsToUTF8($str),
-        "Chinese(gb2312)  美国前司法部长面见萨达姆后称其状态很好  Chinese (gb2312)",
-        "gb2312 character is successfully reassembled",
-    );
-
+        is(
+            RT::I18N::DecodeMIMEWordsToUTF8($str),
+            "Chinese(gb2312)  美国前司法部长面见萨达姆后称其状态很好  Chinese (gb2312)",
+            "gb2312 character is successfully reassembled",
+        );
+    } [(qr/DecodeMIMEWordsTo.*?called without field name/i) x 2];
 }
 
 diag "multiple mime words containing special chars already in quotes";

commit d5a3d74fdb50089ea44101afe74665109b086411
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed May 8 15:43:42 2013 -0700

    Tests: Set a correspond address
    
    ... so we don't try to parse an empty address on the way back in.

diff --git a/t/mail/multipart.t b/t/mail/multipart.t
index 1c11064..67f39d9 100644
--- a/t/mail/multipart.t
+++ b/t/mail/multipart.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 4;
+use RT::Test tests => 4, config => q{Set($CorrespondAddress, 'rt at example.com');};
 use RT::Test::Email;
 
 my $queue = RT::Test->load_or_create_queue( Name => 'General' );

commit f428fe5e8f3dad991aca31a7e7c7ec25f9bc6049
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed May 8 15:44:22 2013 -0700

    Tests: Double quotes are not allowed by our email address parsing
    
    The double quote case for requestor email addresses is skipped further
    down in the file, but the ticket was still created with a bogus
    requestor.  Avoid the added warnings by skipping the requestor when
    testing double quotes.

diff --git a/t/web/googleish_search.t b/t/web/googleish_search.t
index a5f834e..73de128 100644
--- a/t/web/googleish_search.t
+++ b/t/web/googleish_search.t
@@ -164,7 +164,9 @@ for my $quote ( q{'}, q{"} ) {
         Subject   => qq!base${quote}ticket $$!,
         Queue     => 'general',
         Owner     => $user->Name,
-        Requestor => qq!custom${quote}search\@localhost!,
+        ( $quote eq q{'}
+            ? (Requestor => qq!custom${quote}search\@localhost!)
+            : () ),
         Content   => qq!this is base${quote}ticket with quote inside!,
     );
     ok( $ticket_quote->id, 'created ticket with quote for custom search' );

commit 31d50251f9c0ea83b98c1e24316a1430dfa65a9b
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu May 9 17:09:07 2013 -0400

    Remove assumptions that we might have Email::Address < 1.897

diff --git a/sbin/rt-test-dependencies.in b/sbin/rt-test-dependencies.in
index 6961551..f5547be 100644
--- a/sbin/rt-test-dependencies.in
+++ b/sbin/rt-test-dependencies.in
@@ -370,7 +370,6 @@ HTML::Entities
 
 my %AVOID = (
     'DBD::Oracle' => [qw(1.23)],
-    'Email::Address' => [qw(1.893 1.894)],
     'Devel::StackTrace' => [qw(1.28 1.29)],
 );
 
diff --git a/t/mail/header-characters.t b/t/mail/header-characters.t
index 97fdd62..66cc05f 100644
--- a/t/mail/header-characters.t
+++ b/t/mail/header-characters.t
@@ -9,11 +9,7 @@ use Encode;
 my ($baseurl, $m) = RT::Test->started_ok;
 
 diag "Testing non-ASCII latin1 in From: header";
-SKIP:{
-    skip "Test requires Email::Address 1.893 or later, "
-      . "you have $Email::Address::VERSION", 3,
-      if $Email::Address::VERSION < 1.893;
-
+{
     my $mail = encode( 'iso-8859-1', <<'.' );
 From: <René@example.com>
 Reply-To: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
@@ -37,11 +33,7 @@ here's some content
 }
 
 diag "Testing non-ASCII latin1 in From: header with MIME-word-encoded phrase";
-SKIP:{
-    skip "Test requires Email::Address 1.893 or later, "
-      . "you have $Email::Address::VERSION", 3,
-      if $Email::Address::VERSION < 1.893;
-
+{
     my $mail = encode( 'iso-8859-1', <<'.' );
 From: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
 Reply-To: =?iso-8859-1?Q?Ren=E9?= <René@example.com>

-----------------------------------------------------------------------


More information about the Rt-commit mailing list