Author: fkento
Date: Thu Aug 20 16:26:35 2026
New Revision: 1937273
Log:
HTML: honor style attribute on body and font, apply CSS after HTML attributes
text_style() iterated tag attributes with keys %$attr, so on a tag carrying
both a presentational attribute and a style attribute, hash order decided
which won. <body bgcolor="black" style="background-color: white"> rendered
as invisible or visible depending on the hash seed. Sort so 'style' is
processed last, matching CSS precedence over presentational attributes.
Also add 'style' to %ok_attributes for body and font.
Modified:
spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm
spamassassin/trunk/t/html_visibility.t
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm Thu Aug 20 14:20:45 2026 (r1937272)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm Thu Aug 20 16:26:35 2026 (r1937273)
@@ -75,8 +75,8 @@ my %elements_uri = map {; $_ => 1 }
# permitted element attributes
my %ok_attributes;
-$ok_attributes{body}{$_} = 1 for qw( text bgcolor link alink vlink background );
-$ok_attributes{font}{$_} = 1 for qw( color face size );
+$ok_attributes{body}{$_} = 1 for qw( text bgcolor link alink vlink background style );
+$ok_attributes{font}{$_} = 1 for qw( color face size style );
$ok_attributes{marquee}{$_} = 1 for qw( bgcolor background );
$ok_attributes{table}{$_} = 1 for qw( bgcolor style );
$ok_attributes{td}{$_} = 1 for qw( bgcolor style );
@@ -653,7 +653,8 @@ sub text_style {
}
# tag attributes
- for my $name (keys %$attr) {
+ # process 'style' last so CSS takes precedence over HTML attributes
+ for my $name (sort { ($a eq 'style') <=> ($b eq 'style') or $a cmp $b } keys %$attr) {
next unless exists $ok_attributes{$tag}{$name};
if ($name eq "text" || $name eq "color") {
# two different names for text color
Modified: spamassassin/trunk/t/html_visibility.t
==============================================================================
--- spamassassin/trunk/t/html_visibility.t Thu Aug 20 14:20:45 2026 (r1937272)
+++ spamassassin/trunk/t/html_visibility.t Thu Aug 20 16:26:35 2026 (r1937273)
@@ -98,11 +98,39 @@ my @tests = (
font_invalid_color => 0,
},
{
+ html => '<font style="display: none">X</font>',
+ visibility => 'invisible',
+ font_invalid_color => 0,
+ },
+ {
+ html => '<font style="color: transparent">X</font>',
+ visibility => 'invisible',
+ font_invalid_color => 0,
+ },
+ {
+ # CSS takes precedence over HTML attributes
+ html => '<font color="red" style="color: transparent">X</font>',
+ visibility => 'invisible',
+ font_invalid_color => 0,
+ },
+ {
+ # CSS takes precedence regardless of attribute order
+ html => '<font style="color: red" color="transparent">X</font>',
+ visibility => 'visible',
+ font_invalid_color => 0,
+ },
+ {
html => '<body bgcolor="black">X</body>',
visibility => 'invisible',
font_invalid_color => 0,
},
{
+ # CSS takes precedence over HTML attributes
+ html => '<body bgcolor="black" style="background-color: white">X</body>',
+ visibility => 'visible',
+ font_invalid_color => 0,
+ },
+ {
html => '<strong style="display: none;">X</strong>',
visibility => 'invisible',
font_invalid_color => 0,
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.