@@ -247,4 +247,92 @@ This is the original forwarded email
247247</div></blockquote></div><hr class="clear"></div></div>
248248EOF
249249
250+ diag " multipart/related with a text/plain root (no text/html) must still display the body" ;
251+ {
252+ my $path = RT::Test::get_relocatable_file( ' multipart-related-text-plain' ,
253+ ( File::Spec-> updir(), ' data' , ' emails' ) );
254+ my $email = RT::Test-> file_content($path );
255+
256+ my ( $status , $id ) = RT::Test-> send_via_mailgate($email );
257+ is( $status >> 8, 0, ' mail gateway exited normally' );
258+ ok( $id , " created ticket #$id from multipart/related message" );
259+
260+ my $ticket = RT::Ticket-> new( RT-> SystemUser );
261+ $ticket -> Load($id );
262+ is( $ticket -> Id, $id , " loaded ticket #$id " );
263+
264+ # Confirm the message really has the structure under test before asserting
265+ # on how it is displayed.
266+ my $txn = $ticket -> Transactions-> First;
267+ my $top = $txn -> Attachments-> First;
268+ is( lc $top -> ContentType, ' multipart/related' ,
269+ ' top-level part is multipart/related' );
270+
271+ my %child_types =
272+ map { lc ( $_ -> ContentType ) => 1 }
273+ grep { $_ -> Parent == $top -> Id } @{ $txn -> Attachments-> ItemsArrayRef };
274+ ok( $child_types {' text/plain' }, ' has a text/plain child part' );
275+ ok( !$child_types {' text/html' }, ' has no text/html child part' );
276+
277+ $m -> get_ok( " /Ticket/History.html?id=$id " , ' fetched ticket history' );
278+
279+ my @bodies = $m -> dom-> find(' div.messagebody' )-> map (' all_text' )-> each ;
280+ ok(
281+ ( grep { / UNIQUEPLAINBODY/ } @bodies ),
282+ ' text/plain body of the multipart/related message is displayed inline'
283+ ) or diag " Rendered message bodies: " . join ( ' ||' , @bodies );
284+ }
285+
286+ # Returns the concatenated text of every rendered message body for a ticket.
287+ sub history_bodies {
288+ my $tid = shift ;
289+ $m -> get_ok( " /Ticket/History.html?id=$tid " , " fetched history for #$tid " );
290+ return join ' ||' , $m -> dom-> find(' div.messagebody' )-> map (' all_text' )-> each ;
291+ }
292+
293+ # Used by both the PreferRichText on/off cases below.
294+ my $alt_id ;
295+
296+ diag " nested multipart/alternative -> multipart/related(html): exactly one textual part renders" ;
297+ {
298+ # The common MUA structure (Outlook, Apple Mail, Gmail):
299+ # multipart/alternative
300+ # text/plain # plain downgrade
301+ # multipart/related
302+ # text/html # composed rich body
303+ # image/png # inline CID image
304+ # The text/html part's direct parent is the multipart/related. RT must
305+ # show exactly one textual part, never both (the "duplicate message"
306+ # regression fixed in 4a38585f75) and never neither. With PreferRichText
307+ # on (the default) the rich body wins.
308+ my $path = RT::Test::get_relocatable_file( ' multipart-alternative-related-html' ,
309+ ( File::Spec-> updir(), ' data' , ' emails' ) );
310+ my $email = RT::Test-> file_content($path );
311+
312+ my ( $status , $id ) = RT::Test-> send_via_mailgate($email );
313+ is( $status >> 8, 0, ' mail gateway exited normally' );
314+ ok( $id , " created ticket #$id from nested alternative/related message" );
315+ $alt_id = $id ;
316+
317+ my $bodies = history_bodies($id );
318+ like( $bodies , qr / HTMLBODYMARKER/ ,
319+ ' PreferRichText on: text/html body is displayed' );
320+ unlike( $bodies , qr / PLAINDOWNGRADEMARKER/ ,
321+ ' PreferRichText on: text/plain downgrade is suppressed (no duplicate)' );
322+ }
323+
324+ RT::Test-> stop_server;
325+ RT-> Config-> Set( PreferRichText => 0 );
326+ ( $baseurl , $m ) = RT::Test-> started_ok;
327+ ok( $m -> login, ' logged in after restart' );
328+
329+ diag " same message with PreferRichText off: the plain downgrade wins" ;
330+ {
331+ my $bodies = history_bodies($alt_id );
332+ like( $bodies , qr / PLAINDOWNGRADEMARKER/ ,
333+ ' PreferRichText off: text/plain downgrade is displayed' );
334+ unlike( $bodies , qr / HTMLBODYMARKER/ ,
335+ ' PreferRichText off: text/html body is suppressed (no duplicate)' );
336+ }
337+
250338done_testing;
0 commit comments