--- /dev/null
+# 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;
+use strict;
+use warnings;
+use Email::Address;
+
+# 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 ORIGINAL_RECIPIENT (postfix) env is set
+sub recipient_specified {
+ my ($klass, $filter) = @_;
+ my $or = $ENV{ORIGINAL_RECIPIENT};
+ defined($or) or return 1; # for imports
+ my @or = Email::Address->parse($or);
+ my $oaddr = __drop_plus($or[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;
use strict;
use warnings;
use Email::Filter;
+use Email::Address;
use PublicInbox::Filter;
use IPC::Run qw(run);
my $usage = "public-inbox-mda main_repo fail_repo < rfc2822_message";
my $filtered;
if (length($filter->simple->as_string) <= $max
+ && PublicInbox->recipient_specified($filter)
&& do_spamc($filter->simple, \$filtered)) {
# update our message with SA headers (in case our filter rejects it)
my $simple = Email::Simple->new($filtered);
--- /dev/null
+# Copyright (C) 2014, Eric Wong <normalperson@yhbt.net> and all contributors
+# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
+use strict;
+use warnings;
+use Test::More;
+use Email::Simple;
+use Email::Filter;
+use PublicInbox;
+
+sub do_checks {
+ my ($s) = @_;
+
+ my $f = Email::Filter->new(data => $s->as_string);
+ local %ENV;
+ delete $ENV{ORIGINAL_RECIPIENT};
+
+ ok(PublicInbox->recipient_specified($f),
+ "ORIGINAL_RECIPIENT unset is OK");
+
+ $ENV{ORIGINAL_RECIPIENT} = 'foo@example.com';
+ ok(!PublicInbox->recipient_specified($f),
+ "wrong ORIGINAL_RECIPIENT rejected");
+
+ $ENV{ORIGINAL_RECIPIENT} = 'b@example.com';
+ ok(PublicInbox->recipient_specified($f),
+ "ORIGINAL_RECIPIENT in To: is OK");
+
+ $ENV{ORIGINAL_RECIPIENT} = 'c@example.com';
+ ok(PublicInbox->recipient_specified($f),
+ "ORIGINAL_RECIPIENT in Cc: is OK");
+}
+
+{
+ do_checks(Email::Simple->create(
+ header => [
+ From => 'a@example.com',
+ To => 'b@example.com',
+ Cc => 'c@example.com',
+ 'Content-Type' => 'text/plain',
+ Subject => 'this is a subject',
+ ],
+ body => "hello world\n",
+ ));
+}
+
+{
+ do_checks(Email::Simple->create(
+ header => [
+ From => 'a@example.com',
+ To => 'b+plus@example.com',
+ Cc => 'John Doe <c@example.com>',
+ 'Content-Type' => 'text/plain',
+ Subject => 'this is a subject',
+ ],
+ body => "hello world\n",
+ ));
+}
+
+done_testing();