about summary refs log tree commit homepage
path: root/lib/PublicInbox/MDA.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2014-04-19 23:11:00 +0000
committerEric Wong <e@80x24.org>2014-04-19 23:11:00 +0000
commit4024aae69fe08c0aa14a69a12d55ca2b7dd4a4ab (patch)
tree5d981b2983ef9e5a9fd09047b6812528575144b1 /lib/PublicInbox/MDA.pm
parent6a414a4087a59ad8c62cbef30984632ea31ced23 (diff)
downloadpublic-inbox-4024aae69fe08c0aa14a69a12d55ca2b7dd4a4ab.tar.gz
We will be combining common code between -learn and -mda
Diffstat (limited to 'lib/PublicInbox/MDA.pm')
-rw-r--r--lib/PublicInbox/MDA.pm56
1 files changed, 56 insertions, 0 deletions
diff --git a/lib/PublicInbox/MDA.pm b/lib/PublicInbox/MDA.pm
new file mode 100644
index 00000000..22879236
--- /dev/null
+++ b/lib/PublicInbox/MDA.pm
@@ -0,0 +1,56 @@
+# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
+# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
+package PublicInbox::MDA;
+use strict;
+use warnings;
+use Email::Address;
+use Date::Parse qw(strptime);
+use constant MAX_SIZE => 1024 * 500; # same as spamc default
+
+# drop plus addressing for matching
+sub __drop_plus {
+        my ($str_addr) = @_;
+        $str_addr =~ s/\+.*\@/\@/;
+        $str_addr;
+}
+
+# do not allow Bcc, only Cc and To if recipient is set
+sub precheck {
+        my ($klass, $filter, $recipient) = @_;
+        my $simple = $filter->simple;
+        my $mid = $simple->header("Message-ID");
+        return 0 unless usable_str(length('<m@h>'), $mid) && $mid =~ /\@/;
+        return 0 unless usable_str(length('u@h'), $filter->from);
+        return 0 unless usable_str(length(':o'), $simple->header("Subject"));
+        return 0 unless usable_date($simple->header("Date"));
+        return 0 if length($simple->as_string) > MAX_SIZE;
+        recipient_specified($filter, $recipient);
+}
+
+sub usable_str {
+        my ($len, $str) = @_;
+        defined($str) && length($str) >= $len;
+}
+
+sub usable_date {
+        my @t = eval { strptime(@_) };
+        scalar @t;
+}
+
+sub recipient_specified {
+        my ($filter, $recipient) = @_;
+        defined($recipient) or return 1; # for mass imports
+        my @recip = Email::Address->parse($recipient);
+        my $oaddr = __drop_plus($recip[0]->address);
+        $oaddr = qr/\b\Q$oaddr\E\b/i;
+        my @to = Email::Address->parse($filter->to);
+        my @cc = Email::Address->parse($filter->cc);
+        foreach my $addr (@to, @cc) {
+                if (__drop_plus($addr->address) =~ $oaddr) {
+                        return 1;
+                }
+        }
+        return 0;
+}
+
+1;