Commit 254e8da9 authored by Alex Vandiver's avatar Alex Vandiver
Browse files

Don't die if HTML → text conversion throws an error

HTML::FormatText::WithLinks::AndTables may contain errors which make it
incapable of rendering the HTML to text.  In the context of templates,
this led to the outgoing mail being dropped on the floor if the
conversion failed.  It also showed as errors in the REST interface and
RSS feed, in attempting to downsample an HTML-only message to plain text
to display therein.

Expliticly wrap the conversion with an eval to trap fatal errors in the
HTML::FormatText::WithLinks::AndTables module; in such cases, the method
returns undef.  In the context of template generation, the presence of
such a return value is to omit the text/plain part entirely, as email
clients may be able to generate it even if we are unable to.

It is expected that the new tests may begin to fail if
HTML::FormatText::WithLinks::AndTables resolves its bug surrounding
nested tables.  Unfortunately, marking them TODO is difficult because
they intermix passing and failing tests in mail_ok.
parent 8c818e2a
......@@ -1765,8 +1765,9 @@ sub _RecordSendEmailFailure {
=head2 ConvertHTMLToText HTML
Takes HTML and converts it to plain text. Appropriate for generating a plain
text part from an HTML part of an email.
Takes HTML and converts it to plain text. Appropriate for generating a
plain text part from an HTML part of an email. Returns undef if
conversion fails.
=cut
......@@ -1774,20 +1775,27 @@ sub ConvertHTMLToText {
my $html = shift;
require HTML::FormatText::WithLinks::AndTables;
return HTML::FormatText::WithLinks::AndTables->convert(
$html => {
leftmargin => 0,
rightmargin => 78,
no_rowspacing => 1,
before_link => '',
after_link => ' (%l)',
footnote => '',
skip_linked_urls => 1,
with_emphasis => 0,
}
);
my $text;
eval {
$text = HTML::FormatText::WithLinks::AndTables->convert(
$html => {
leftmargin => 0,
rightmargin => 78,
no_rowspacing => 1,
before_link => '',
after_link => ' (%l)',
footnote => '',
skip_linked_urls => 1,
with_emphasis => 0,
}
);
$text //= '';
};
$RT::Logger->error("Failed to downgrade HTML to plain text: $@") if $@;
return $text;
}
RT::Base->_ImportOverlays();
1;
......@@ -660,14 +660,17 @@ sub _DowngradeFromHTML {
$orig_entity->head->mime_attr( "Content-Type" => 'text/html' );
$orig_entity->head->mime_attr( "Content-Type.charset" => 'utf-8' );
$orig_entity->make_multipart('alternative', Force => 1);
require Encode;
$new_entity->bodyhandle(MIME::Body::InCore->new(
# need to decode_utf8, see the doc of MIMEObj method
\(RT::Interface::Email::ConvertHTMLToText(Encode::decode_utf8($new_entity->bodyhandle->as_string)))
));
my $body = $new_entity->bodyhandle->as_string;
# need to decode_utf8, see the doc of MIMEObj method
$body = Encode::decode_utf8( $body );
my $html = RT::Interface::Email::ConvertHTMLToText( $body );
return unless defined $html;
$new_entity->bodyhandle(MIME::Body::InCore->new( \$html ));
$orig_entity->make_multipart('alternative', Force => 1);
$orig_entity->add_part($new_entity, 0); # plain comes before html
$self->{MIMEObj} = $orig_entity;
......
......@@ -4,10 +4,11 @@ use RT::Test tests => undef;
BEGIN {
plan skip_all => 'Email::Abstract and Test::Email required.'
unless eval { require Email::Abstract; require Test::Email; 1 };
plan tests => 18;
plan tests => 22;
}
use RT::Test::Email;
use Test::Warn;
my $root = RT::User->new(RT->SystemUser);
$root->Load('root');
......@@ -86,6 +87,29 @@ mail_ok {
};
diag "Failing HTML -> Text conversion";
warnings_like {
my $body = '<table><tr><td><table><tr><td>Foo</td></tr></table></td></tr></table>';
mail_ok {
($ok, $tmsg) = $t->Correspond(
MIMEObj => HTML::Mason::Commands::MakeMIMEEntity(
Body => $body,
Type => 'text/html',
),
);
} { from => qr/RT System/,
bcc => 'root@localhost',
subject => qr/\Q[example.com #1] The internet is broken\E/,
body => qr{Ticket URL: <a href="(http://localhost:\d+/Ticket/Display\.html\?id=1)">\1</a>.+?$body}s,
'Content-Type' => qr{text/html}, # TODO
},{ from => qr/RT System/,
to => 'enduser@example.com',
subject => qr/\Q[example.com #1] The internet is broken\E/,
body => qr{<table><tr><td><table><tr><td>Foo</td></tr></table></td></tr></table>},
'Content-Type' => qr{text/html}, # TODO
};
} [(qr/uninitialized value/, qr/Failed to downgrade HTML/)x3];
diag "Admin Comment in HTML";
mail_ok {
($ok, $tmsg) = $t->Comment(
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment