1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use lib '.';
use Sendmail::Milter;
use Spline::DMARC qw(check_addresses);
use Spline::Log qw(set_verbose debug info);
use Spline::Data;
use Data::Dumper;
my %milter_callbacks = (
'envfrom' => \&from_callback,
'envrcpt' => \&rcpt_callback,
'header' => \&header_callback,
'eoh' => \&eom_callback,
'abort' => \&abort_callback,
'close' => \&close_callback,
);
sub from_callback($$@) {
my $ctx = shift;
my $from = shift;
my $data = Spline::Data->new($ctx);
$data->set('counter', 0);
debug "MAIL FROM: $from";
return SMFIS_CONTINUE;
}
sub rcpt_callback($$@) {
my $ctx = shift;
my $rcpt_to = shift;
my $data = Spline::Data->load($ctx);
debug "RCPT TO: $rcpt_to";
my $next_hop = $ctx->getsymval('{rcpt_host}');
if ($next_hop eq '[lists.spline.inf.fu-berlin.de]') {
info "Mailinglist address: $rcpt_to";
$data->set('counter', 1);
}
return SMFIS_CONTINUE;
}
sub header_callback($$$) {
my $ctx = shift;
my ($field, $value) = @_;
my $data = Spline::Data->load($ctx);
debug "HEADER '$field': $value";
if (lc($field) eq 'from') {
return SMFIS_CONTINUE if $data->get('counter') == 0;
my $reject = check_addresses($value);
if ($reject) {
info 'Rejecting mail';
$ctx->setreply('550', '5.7.2', 'Your provider does not permit sending to mailing lists (DMARC policy)');
return SMFIS_REJECT;
}
}
# We cannot SMFIS_ACCEPT here, because there could
# be multiple From headers.
return SMFIS_CONTINUE;
}
sub eoh_callback($) {
my $ctx = shift;
my $data = Spline::Data->load($ctx);
$data->set('counter', 0);
debug 'END OF HEADER';
return SMFIS_ACCEPT;
}
sub abort_callback($) {
my $ctx = shift;
my $data = Spline::Data->load($ctx);
$data->set('counter', 0);
debug 'ABORT';
return SMFIS_CONTINUE;
}
sub close_callback($) {
my $ctx = shift;
Spline::Data->load($ctx);
$ctx->setpriv(undef);
debug 'CLOSE';
return SMFIS_CONTINUE;
}
sub main($) {
my $listen = shift;
Sendmail::Milter::setconn($listen);
Sendmail::Milter::register("dmarc_lists_filter",
\%milter_callbacks, SMFI_CURR_ACTS);
Sendmail::Milter::main();
}
main('inet:12345@localhost');
# vim: set et tabstop=4 tw=70:
|