svn commit: r1927705 - in spamassassin/trunk: lib/Mail/SpamAssassin lib/Mail/SpamAssassin/Plugin t

[email protected]
Newsgroups gmane.mail.spam.spamassassin.cvs
Message-ID <175468326439.214148.17413401968534344796@svn02-us-east.apache.org>
Author: fkento
Date: Fri Aug  8 20:01:04 2025
New Revision: 1927705

Log:
Bug 8340: DMARC Avoidance

Added:
   spamassassin/trunk/t/util_parse_header_addresses.t
Modified:
   spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm
   spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm	Fri Aug  8 18:50:51 2025	(r1927704)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm	Fri Aug  8 20:01:04 2025	(r1927705)
@@ -69,6 +69,7 @@ my $VERSION = 0.2;
 
 use Mail::SpamAssassin;
 use Mail::SpamAssassin::Plugin;
+use Mail::SpamAssassin::Util qw(is_fqdn_valid);
 
 our @ISA = qw(Mail::SpamAssassin::Plugin);
 
@@ -274,6 +275,10 @@ sub _check_dmarc {
     return if !defined $mfrom_domain;
     dbg("EnvelopeFrom header not found, using From");
   }
+  if(!is_fqdn_valid($mfrom_domain)) {
+    dbg("Invalid domain name $mfrom_domain");
+    return;
+  }
 
   my $spf_status = 'none';
   if ($pms->{spf_pass})         { $spf_status = 'pass'; }

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm	Fri Aug  8 18:50:51 2025	(r1927704)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm	Fri Aug  8 20:01:04 2025	(r1927705)
@@ -2635,6 +2635,7 @@ sub _parse_header_addresses {
     my $comment = defined $5 ? $5 : undef;
 
     my ($user, $host, $invalid);
+    $invalid = 0;
 
     # Check relaxed <> capture
     if (defined $2) {
@@ -2642,7 +2643,7 @@ sub _parse_header_addresses {
       $address =~ s/\((?:|(?:[^()\\]++|\\.)*+)\)//gs;
       # Validate as somewhat email looking
       if ($address !~ /^$header_address_mailre$/) {
-        $address = undef;
+        $invalid = 1;
       }
     }
 
@@ -2670,6 +2671,7 @@ sub _parse_header_addresses {
         }
       }
       $phrase = $newphrase;
+      $phrase =~ s/^\s+|\s+\z//gs; # Trim whitespace
 
       # If we only have phrase which looks email, swap when valid
       # Check all in one if, either swap or don't
@@ -2710,7 +2712,7 @@ sub _parse_header_addresses {
       ($user, $host) = ($2, $3);
     }
 
-    $invalid = !defined $host || !is_fqdn_valid(idn_to_ascii($host), 1);
+    $invalid = 1 if !defined $host || !is_fqdn_valid(idn_to_ascii($host), 1);
     push @results, {
       'phrase' => $phrase,
       'user' => $user,

Added: spamassassin/trunk/t/util_parse_header_addresses.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ spamassassin/trunk/t/util_parse_header_addresses.t	Fri Aug  8 20:01:04 2025	(r1927705)
@@ -0,0 +1,149 @@
+#!/usr/bin/perl -T
+use utf8;
+use open qw( :std :encoding(UTF-8) );
+use lib '.'; use lib 't';
+use SATest; sa_t_init("util_parse_header_addresses");
+use Test::More;
+
+use strict;
+require Mail::SpamAssassin::Util;
+
+my @data = (
+    {
+        in  => 'companyname <"no reply"@example.com>',
+        out => [
+            {
+                'phrase'  => 'companyname',
+                'user'    => '"no reply"',
+                'host'    => 'example.com',
+                'address' => '"no reply"@example.com',
+                'comment' => undef,
+                'invalid' => 0
+            }
+        ],
+    },
+    {
+        in  => 'companyname <no [email protected]>',
+        out => [
+            {
+                'phrase'  => 'companyname',
+                'user'    => 'no reply',
+                'host'    => 'example.com',
+                'address' => 'no [email protected]',
+                'comment' => undef,
+                'invalid' => 1
+            }
+        ],
+    },
+    {
+        in  => 'Support <[email protected]_bar.com>',
+        out => [
+            {
+                'phrase'  => 'Support',
+                'user'    => 'support',
+                'host'    => 'foo.com_bar.com',
+                'address' => '[email protected]_bar.com',
+                'comment' => undef,
+                'invalid' => 1
+            }
+        ],
+    },
+    {
+        in  => 'user@example.みんな',
+        out => [
+            {
+                'phrase'  => undef,
+                'user'    => 'user',
+                'host'    => 'example.みんな',
+                'address' => 'user@example.みんな',
+                'comment' => undef,
+                'invalid' => 0
+            }
+        ],
+    },
+    {
+        in  => 'John Doe <[email protected]> (Support Team)',
+        out => [
+            {
+                'phrase'  => 'John Doe',
+                'user'    => 'jdoe',
+                'host'    => 'example.com',
+                'address' => '[email protected]',
+                'comment' => 'Support Team',
+                'invalid' => 0
+            }
+        ],
+    },
+    {
+        in  => 'Alice <[email protected]>, Bob <[email protected]>',
+        out => [
+            {
+                'phrase'  => 'Alice',
+                'user'    => 'alice',
+                'host'    => 'example.com',
+                'address' => '[email protected]',
+                'comment' => undef,
+                'invalid' => 0
+            },
+            {
+                'phrase'  => 'Bob',
+                'user'    => 'bob',
+                'host'    => 'example.org',
+                'address' => '[email protected]',
+                'comment' => undef,
+                'invalid' => 0
+            }
+        ],
+    },
+    {
+        in  => 'Root User <root>',
+        out => [
+            {
+                'phrase'  => 'Root User',
+                'user'    => 'root',
+                'host'    => undef,
+                'address' => 'root',
+                'comment' => undef,
+                'invalid' => 1
+            }
+        ],
+    },
+    {
+        in  => 'Invalid <[email protected]>',
+        out => [
+            {
+                'phrase'  => 'Invalid',
+                'user'    => 'user',
+                'host'    => 'domain..com',
+                'address' => '[email protected]',
+                'comment' => undef,
+                'invalid' => 1
+            }
+        ],
+    },
+    {
+        in  => '<invalid@address>',
+        out => [
+            {
+                'phrase'  => undef,
+                'user'    => 'invalid',
+                'host'    => 'address',
+                'address' => 'invalid@address',
+                'comment' => undef,
+                'invalid' => 1
+            }
+        ],
+    },
+);
+
+plan tests => scalar @data;
+
+foreach my $test (@data) {
+    my $in = $test->{in};
+    my $out = $test->{out};
+
+    my @addresses = Mail::SpamAssassin::Util::parse_header_addresses($in);
+
+    is_deeply(\@addresses, $out, "parse_header_addresses('$in')");
+}
+
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.