├── .gitignore ├── .travis.yml ├── Changes ├── LICENSE ├── Makefile.PL ├── README.md ├── bin ├── authentication_milter ├── authentication_milter_blocker ├── authentication_milter_client └── authentication_milter_log ├── dist.ini ├── lib └── Mail │ └── Milter │ ├── Authentication.pm │ └── Authentication │ ├── App │ ├── Blocker │ │ ├── App.pm │ │ └── App │ │ │ └── Command │ │ │ ├── add.pm │ │ │ ├── delete.pm │ │ │ └── list.pm │ └── ProcessLog │ │ ├── App.pm │ │ └── App │ │ └── Command │ │ └── arex.pm │ ├── Client.pm │ ├── Config.pm │ ├── Constants.pm │ ├── Exception.pm │ ├── HTDocs.pm │ ├── Handler.pm │ ├── Handler │ ├── ARC.pm │ ├── ARC_metrics.json │ ├── AbusixDataFeed.pm │ ├── AddID.pm │ ├── AlignedFrom.pm │ ├── AlignedFrom_metrics.json │ ├── Auth.pm │ ├── Auth_metrics.json │ ├── BIMI.pm │ ├── Blocker.pm │ ├── DKIM.pm │ ├── DKIM_metrics.json │ ├── DMARC.pm │ ├── DMARC_metrics.json │ ├── IPRev.pm │ ├── IPRev_metrics.json │ ├── LocalIP.pm │ ├── LocalIP_metrics.json │ ├── Logger.pm │ ├── PTR.pm │ ├── PTR_metrics.json │ ├── RBLDNS.pm │ ├── ReturnOK.pm │ ├── ReturnOK_metrics.json │ ├── SPF.pm │ ├── SPF_metrics.json │ ├── Sanitize.pm │ ├── Sanitize_metrics.json │ ├── SenderID.pm │ ├── SenderID_metrics.json │ ├── Size.pm │ ├── Size_metrics.json │ ├── TLS.pm │ ├── TLS_metrics.json │ ├── TestTimeout.pm │ ├── TrustedIP.pm │ ├── TrustedIP_metrics.json │ ├── XGoogleDKIM.pm │ └── XGoogleDKIM_metrics.json │ ├── Metric.pm │ ├── Metric │ ├── Base.json │ ├── Grafana.pm │ ├── RowErrors.json │ ├── RowProcesses.json │ ├── RowProcessingTime.json │ ├── RowThroughput.json │ └── RowUptime.json │ ├── Net │ ├── Milter.pm │ └── ServerPatches.pm │ ├── Pragmas.pm │ ├── Protocol │ ├── Milter.pm │ └── SMTP.pm │ ├── Resolver.pm │ ├── Tester.pm │ ├── Tester │ └── HandlerTester.pm │ └── htdocs │ └── css │ ├── authmilter.css │ ├── normalize.css │ └── skeleton.css ├── share ├── authentication_milter.init ├── authentication_milter.json └── mail-dmarc.ini ├── t ├── 00-load.t ├── 01-func-pipeline.t ├── 01-func-tools.t ├── 02-unit-mail-milter-authentication-handler-rbl.t ├── 02-unit-mail-milter-authentication-handler.t ├── 03-func-milter.t ├── 03-func-smtp.t ├── 04-unit-handler-abusixdatafeed.t ├── 04-unit-handler-aligned-from_dmarc.t ├── 04-unit-handler-aligned-from_nodmarc.t ├── 04-unit-handler-auth.t ├── 04-unit-handler-bimi.t ├── 04-unit-handler-blocker.t ├── 04-unit-handler-dkim.t ├── 04-unit-handler-dmarc-strict-from.t ├── 04-unit-handler-dmarc.t ├── 04-unit-handler-localip.t ├── 04-unit-handler-remap.t ├── 04-unit-handler-spfu.t ├── 04-unit-handler-trustedip.t ├── AuthMilterTest.pm ├── TestAlignedFromHandler.pm ├── bimi.zonefile ├── conf │ ├── blocker.toml │ ├── blocker2.toml │ └── blocker3.toml ├── config │ ├── dmarc_reject.smtp │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── dmarc_reject │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── dmarc_reject_wl.smtp │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── dmarc_reject_wl │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── dryrun.smtp │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── dryrun │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── handler │ │ └── etc │ │ │ └── mail-dmarc.ini │ ├── hide_none.smtp │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── hide_none │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── normal.smtp │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ ├── normal │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini │ └── timeout │ │ ├── authentication_milter.json │ │ └── mail-dmarc.ini ├── data │ ├── FM_BIMI.svg │ ├── example │ │ ├── dmarc_multi.eml │ │ ├── dmarc_multi_2.eml │ │ ├── dmarc_reject.eml │ │ ├── dmarc_reject.smtp.eml │ │ ├── dmarc_reject_case.eml │ │ ├── dmarc_reject_case.smtp.eml │ │ ├── dmarc_reject_hard.eml │ │ ├── dmarc_reject_hard_whitelisted.eml │ │ ├── dmarc_reject_hard_whitelisted.smtp.eml │ │ ├── dmarc_reject_wl.eml │ │ ├── dmarc_reject_wl.smtp.eml │ │ ├── google_apps_bad.eml │ │ ├── google_apps_bad.smtp.eml │ │ ├── google_apps_bad_space.eml │ │ ├── google_apps_bad_space.smtp.eml │ │ ├── google_apps_bad_spf_fail.eml │ │ ├── google_apps_bad_spf_fail.smtp.eml │ │ ├── google_apps_bad_spf_fail_hard.eml │ │ ├── google_apps_bad_spf_fail_hard.smtp.eml │ │ ├── google_apps_good.8bit.smtp.eml │ │ ├── google_apps_good.eml │ │ ├── google_apps_good.local.eml │ │ ├── google_apps_good.local.smtp.eml │ │ ├── google_apps_good.smtp.eml │ │ ├── google_apps_good.timeout.eml │ │ ├── google_apps_good.trusted.eml │ │ ├── google_apps_good.trusted.smtp.eml │ │ ├── google_apps_good_case.local.eml │ │ ├── google_apps_good_case.local.smtp.eml │ │ ├── google_apps_good_cn.eml │ │ ├── google_apps_good_cn.smtp.eml │ │ ├── google_apps_good_dryrun.eml │ │ ├── google_apps_good_dryrun.smtp.eml │ │ ├── google_apps_good_hide_none.eml │ │ ├── google_apps_good_hide_none.smtp.eml │ │ ├── google_apps_good_map.eml │ │ ├── google_apps_good_map.smtp.eml │ │ ├── google_apps_good_map_cidr.eml │ │ ├── google_apps_good_map_cidr.smtp.eml │ │ ├── google_apps_good_nofrom.eml │ │ ├── google_apps_good_nofrom.smtp.eml │ │ ├── google_apps_good_sanitize.eml │ │ ├── google_apps_good_sanitize.smtp.eml │ │ ├── google_apps_good_sanitize_authserv_id.eml │ │ ├── google_apps_good_sanitize_authserv_id.smtp.eml │ │ ├── google_apps_good_spf_fail.eml │ │ ├── google_apps_good_spf_fail.smtp.eml │ │ ├── google_apps_headers.smtp.eml │ │ ├── google_apps_nodkim.eml │ │ ├── google_apps_nodkim.smtp.eml │ │ ├── google_apps_nodkim_hide_none.eml │ │ ├── google_apps_nodkim_hide_none.smtp.eml │ │ ├── google_apps_nodkim_spf_fail.eml │ │ ├── google_apps_nodkim_spf_fail.smtp.eml │ │ ├── google_apps_nospf_hide_none.eml │ │ ├── google_apps_nospf_hide_none.smtp.eml │ │ ├── google_apps_noxgdkim_hide_none.eml │ │ ├── google_apps_noxgdkim_hide_none.smtp.eml │ │ ├── list.smtp.eml │ │ ├── longlines.eml │ │ ├── longlines.smtp.eml │ │ ├── pipelined.limit.smtp.eml │ │ ├── pipelined.smtp.eml │ │ ├── spam_headers.smtp.eml │ │ ├── spam_headers_hide_none.eml │ │ ├── spam_headers_hide_none.smtp.eml │ │ ├── spam_headers_spf_hide_none.eml │ │ ├── spam_headers_spf_hide_none.smtp.eml │ │ ├── tools_pipeline_test.eml │ │ ├── tools_test.eml │ │ └── transparency.smtp.eml │ ├── metrics │ │ ├── milter_1.json │ │ ├── milter_2.json │ │ ├── milter_3.json │ │ ├── milter_4.json │ │ ├── milter_5.json │ │ ├── milter_timeout.json │ │ ├── smtp_1.json │ │ ├── smtp_2.json │ │ ├── smtp_3.json │ │ ├── smtp_4.json │ │ └── smtp_5.json │ └── source │ │ ├── dmarc_multi.eml │ │ ├── dmarc_reject.eml │ │ ├── dmarc_reject_case.eml │ │ ├── dmarc_reject_wl.eml │ │ ├── google_apps_bad.eml │ │ ├── google_apps_bad_space.eml │ │ ├── google_apps_good.eml │ │ ├── google_apps_good_case.eml │ │ ├── google_apps_good_sanitize.eml │ │ ├── google_apps_headers.eml │ │ ├── google_apps_nodkim.eml │ │ ├── google_apps_noxgdkim.eml │ │ ├── list.eml │ │ ├── longlines.eml │ │ ├── spam_headers.eml │ │ ├── tools_test.eml │ │ └── transparency.eml ├── dev-boilerplate.t ├── dev-critic.t ├── dev-manifest.t ├── dev-pod.t ├── get_record.pl ├── perlcriticrc └── zonefile └── weaver.ini /.gitignore: -------------------------------------------------------------------------------- 1 | /.build/ 2 | /.last_cover_stats 3 | /.lwpcookies 4 | /Build 5 | /Build.bat 6 | /META.* 7 | /MYMETA.* 8 | /Mail-Milter-Authentication-* 9 | /Mail-Milter-Authentication-*.tar.gz 10 | /Makefile 11 | /Makefile.old 12 | /_build/ 13 | /blib/ 14 | /cover_db/ 15 | /debian 16 | /debian.bak 17 | /inc/ 18 | /nytprof.out 19 | /pm_to_blib 20 | /pod2htm*.tmp 21 | /t/tmp 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: perl 2 | perl: 3 | - "5.30" 4 | - "5.28" 5 | - "5.26" 6 | - "5.24" 7 | - "5.22" 8 | - "5.20.3" 9 | 10 | #branches: 11 | # only: 12 | # - releases 13 | 14 | matrix: 15 | include: 16 | - perl: 5.26 17 | env: COVERAGE=1 18 | 19 | before_install: 20 | - git config --global user.name "TravisCI" 21 | - git clone git://github.com/travis-perl/helpers ~/travis-perl-helpers 22 | - source ~/travis-perl-helpers/init 23 | - build-perl 24 | - perl -V 25 | - cpanm -n Devel::Cover::Report::Coveralls 26 | - coverage-setup 27 | 28 | install: 29 | - cpanm --quiet --notest --skip-satisfied Dist::Zilla 30 | - cpanm --quiet --notest Module::Install 31 | - cpanm --quiet --notest Mail::SPF --install-args="--install-path sbin=/tmp" 32 | - cpanm --quiet --notest Test::More Test::File::Contents Test::Perl::Critic 33 | - cpanm --quiet --notest List::MoreUtils::XS List::MoreUtils 34 | - cpanm --quiet --notest Test::CheckManifest Test::Pod::Coverage Test::Pod 35 | - cpanm --quiet --notest Cwd Email::Date::Format Email::Simple 36 | - cpanm --quiet --notest English IO::Socket JSON Mail::DKIM::Verifier Mail::DKIM Mail::AuthenticationResults 37 | - cpanm --quiet --notest MIME::Base64 Module::Load Module::Loaded 38 | - cpanm --quiet --notest Net::DNS 39 | - cpanm --quiet --notest Net::DNS::Resolver::Mock 40 | - cpanm --quiet --notest Net::IP Net::Server 41 | - cpanm --quiet --notest Pod::Usage Proc::ProcessTable Socket Sys::Hostname Sys::Syslog 42 | - cpanm --quiet --notest git://github.com/fastmailops/mail-dmarc.git@fastmail 43 | - cpanm --quiet --notest Dist::Zilla::Plugin::OurPkgVersion || cpanm --quiet --notest Dist::Zilla::Plugin::OurPkgVersion@0.14 44 | - dzil authordeps --missing | cpanm --quiet --notest 45 | - dzil listdeps --missing | cpanm --quiet --notest 46 | - cpan-install --coverage 47 | 48 | script: 49 | - dzil test 50 | 51 | after_success: 52 | - coverage-report 53 | 54 | -------------------------------------------------------------------------------- /bin/authentication_milter_blocker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Manage the Authentication Milter Block List 7 | # PODNAME: authentication_milter_blocker 8 | # VERSION 9 | use Mail::Milter::Authentication::App::Blocker::App; 10 | 11 | Mail::Milter::Authentication::App::Blocker::App->run; 12 | -------------------------------------------------------------------------------- /bin/authentication_milter_log: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Work with Authentication Milter logs 7 | # PODNAME: authentication_milter_log 8 | # VERSION 9 | use Mail::Milter::Authentication::App::ProcessLog::App; 10 | 11 | Mail::Milter::Authentication::App::ProcessLog::App->run; 12 | -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | name = Mail-Milter-Authentication 2 | author = Marc Bradshaw 3 | license = Perl_5 4 | copyright_holder = Marc Bradshaw 5 | copyright_year = 2020 6 | 7 | [MetaJSON] 8 | [MetaResources] 9 | ;homepage = http://authmilter.org/ 10 | bugtracker.web = https://github.com/fastmail/authentication_milter/issues 11 | repository.url = git://github.com/fastmail/authentication_milter.git 12 | repository.web = https://github.com/fastmail/authentication_milter 13 | repository.type = git 14 | 15 | [@Git] 16 | [GatherDir] 17 | exclude_filename = LICENSE 18 | exclude_filename = Makefile.PL 19 | 20 | [PruneCruft] 21 | [ManifestSkip] 22 | [MetaYAML] 23 | [License] 24 | [Readme] 25 | [ExtraTests] 26 | [ExecDir] 27 | [ShareDir] 28 | [MakeMaker] 29 | [Manifest] 30 | [TestRelease] 31 | [ConfirmRelease] 32 | [UploadToCPAN] 33 | 34 | [AutoVersion] 35 | format = 3.{{ cldr('yyyyMMdd') }} 36 | 37 | [Git::Contributors] 38 | 39 | [ReadmeAnyFromPod / build] 40 | type=text 41 | filename=README 42 | location=build 43 | 44 | [CopyFilesFromBuild] 45 | copy = LICENSE 46 | copy = Makefile.PL 47 | 48 | [OurPkgVersion] 49 | [NextRelease] 50 | 51 | [PodWeaver] 52 | ;[PodCoverageTests] 53 | [PodSyntaxTests] 54 | 55 | [Test::Perl::Critic] 56 | critic_config = t/perlcriticrc 57 | 58 | [AutoPrereqs] 59 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/App/Blocker/App.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::App::Blocker::App; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: App::Cmd base class 7 | # VERSION 8 | use App::Cmd::Setup -app; 9 | 1; 10 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/App/Blocker/App/Command/delete.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::App::Blocker::App::Command::delete; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Command to delete a block for a given file 7 | # VERSION 8 | use Mail::Milter::Authentication::App::Blocker::App -command; 9 | use TOML; 10 | use Text::Table; 11 | 12 | sub abstract { 'Delete a block in a given file' } 13 | sub description { 'Delete a block from a given toml file' }; 14 | 15 | sub opt_spec { 16 | return ( 17 | [ 'file=s', 'Config file to operate on' ], 18 | [ 'id=s', 'ID of the block to delete' ], 19 | ); 20 | } 21 | 22 | sub validate_args($self,$opt,$args) { 23 | # no args allowed but options! 24 | $self->usage_error('Must supply a filename') if ( !$opt->{file} ); 25 | $self->usage_error('Supplied filename does not exist') if ( ! -e $opt->{file} ); 26 | $self->usage_error('Must supply an id') if ( !$opt->{id} ); 27 | $self->usage_error('No args allowed') if @$args; 28 | } 29 | 30 | sub execute($self,$opt,$args) { 31 | 32 | open ( my $inf, '<', $opt->{file} ); 33 | my $body = do { local $/; <$inf> }; 34 | close $inf; 35 | my ( $data, $error ) = from_toml( $body ); 36 | 37 | if ( $error ) { 38 | say 'Error parsing file'; 39 | say $error; 40 | exit 1; 41 | } 42 | 43 | if ( ! exists $data->{$opt->{id}} ) { 44 | say 'The given ID does not exist in that file'; 45 | exit 1; 46 | } 47 | 48 | delete $data->{$opt->{id}}; 49 | open my $outf, '>', $opt->{file}; 50 | print $outf to_toml($data); 51 | close $outf; 52 | 53 | say 'Block deleted and file saved'; 54 | 55 | } 56 | 57 | 1; 58 | 59 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/App/Blocker/App/Command/list.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::App::Blocker::App::Command::list; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Command to list current blocks for a given file 7 | # VERSION 8 | use Mail::Milter::Authentication::App::Blocker::App -command; 9 | use Date::Format; 10 | use TOML; 11 | use Text::Table; 12 | 13 | sub abstract { 'List current blocks in a given file' } 14 | sub description { 'Parse a toml file and list the current blocks' } 15 | 16 | sub opt_spec { 17 | return ( 18 | [ 'file=s@', 'Config files to operate on' ], 19 | ); 20 | } 21 | 22 | sub validate_args($self,$opt,$args) { 23 | # no args allowed but options! 24 | $self->usage_error('Must supply a filename') if ( !$opt->{file} ); 25 | foreach my $file ( $opt->{file}->@* ) { 26 | $self->usage_error('Supplied filename does not exist') if ( ! -e $file ); 27 | } 28 | $self->usage_error('No args allowed') if @$args; 29 | } 30 | 31 | sub execute($self,$opt,$args) { 32 | 33 | foreach my $file ( $opt->{file}->@* ) { 34 | 35 | say "In file $file"; 36 | say ''; 37 | 38 | open ( my $inf, '<', $file ); 39 | my $body = do { local $/; <$inf> }; 40 | close $inf; 41 | my ( $data, $error ) = from_toml( $body ); 42 | 43 | if ( $error ) { 44 | say 'Error parsing file'; 45 | say $error; 46 | exit 1; 47 | } 48 | 49 | my $tb = Text::Table->new( 50 | 'Id', 51 | 'Callback', 52 | 'Value', 53 | 'With', 54 | 'Percent', 55 | 'Until', 56 | ); 57 | 58 | foreach my $key ( sort keys $data->%* ) { 59 | $tb->add( 60 | $key, 61 | $data->{$key}->{callback}, 62 | $data->{$key}->{value}, 63 | $data->{$key}->{with}, 64 | $data->{$key}->{percent}, 65 | $data->{$key}->{until} ? time2str('%C',$data->{$key}->{until}) : '-', 66 | ); 67 | } 68 | 69 | print $tb->title; 70 | print $tb->rule('-'); 71 | print $tb->body; 72 | say ''; 73 | } 74 | } 75 | 76 | 1; 77 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/App/ProcessLog/App.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::App::ProcessLog::App; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: App::Cmd base class 7 | # VERSION 8 | use App::Cmd::Setup -app; 9 | 1; 10 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Exception.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Exception; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Class representing an exception 7 | # VERSION 8 | 9 | =constructor I 10 | 11 | die Mail::Milter::Authentication::Exception->new({ 'Type' => 'Timeout', 'Text' => 'Example timeout exception' }); 12 | 13 | Create a new exception object. 14 | 15 | =cut 16 | 17 | sub new { 18 | my ( $class, $args ) = @_; 19 | my $self = $args; 20 | bless $self, $class; 21 | return $self; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/HTDocs.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::HTDocs; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Load and serve static files via the in-built http server. 7 | # VERSION 8 | 9 | =head1 DESCRIPTION 10 | 11 | Load and serve static files via the in-build http server. 12 | 13 | =cut 14 | 15 | =constructor I 16 | 17 | Return a new instance of this class 18 | 19 | =cut 20 | 21 | sub new { 22 | my ( $class ) = @_; 23 | my $self = {}; 24 | bless $self, $class; 25 | return $self; 26 | } 27 | 28 | =method I 29 | 30 | Return an arrayref of valid URLs/Filenames whih are allowed to be served. 31 | 32 | =cut 33 | 34 | sub get_whitelist { 35 | my ( $self, $path ) = @_; 36 | 37 | my @whitelist; 38 | 39 | if ( opendir( my $dh, join( '/', $self->get_basedir(), $path ) ) ) { 40 | while ( my $file = readdir( $dh ) ) { 41 | next if $file =~ /^\./; 42 | my $full_path = join( '/', $self->get_basedir(), $path, $file ); 43 | if ( -f $full_path ) { 44 | push @whitelist, join( '/', $path, $file ); 45 | } 46 | if ( -d $full_path ) { 47 | @whitelist = ( @whitelist, @{ $self->get_whitelist( join ( '/', $path, $file ) ) } ); 48 | } 49 | } 50 | } 51 | 52 | return \@whitelist; 53 | } 54 | 55 | =method I 56 | 57 | Return the base directory for htdocs files 58 | 59 | =cut 60 | 61 | sub get_basedir { 62 | my ( $self ) = @_; 63 | my $basedir = __FILE__; 64 | $basedir =~ s/HTDocs\.pm$/htdocs/; 65 | return $basedir; 66 | } 67 | 68 | =method I 69 | 70 | Return a full HTTP response for the given filename, or null if it does not exist. 71 | 72 | =cut 73 | 74 | sub get_file { 75 | my ( $self, $file ) = @_; 76 | 77 | my $whitelisted = grep { $_ eq $file } @{ $self->get_whitelist( '' ) }; 78 | return if ! $whitelisted; 79 | 80 | my $basefile = $self->get_basedir(); 81 | $basefile .= $file; 82 | if ( ! -e $basefile ) { 83 | return; 84 | } 85 | open my $InF, '<', $basefile; 86 | my @Content = <$InF>; 87 | close $InF; 88 | return join( q{}, @Content ); 89 | } 90 | 91 | 1; 92 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/ARC_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 29, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "hideEmpty" : false, 18 | "hideZero" : true, 19 | "max" : false, 20 | "min" : false, 21 | "show" : true, 22 | "total" : false, 23 | "values" : false 24 | }, 25 | "lines" : true, 26 | "linewidth" : 2, 27 | "links" : [], 28 | "nullPointMode" : "connected", 29 | "percentage" : false, 30 | "pointradius" : 5, 31 | "points" : false, 32 | "renderer" : "flot", 33 | "seriesOverrides" : [], 34 | "span" : 12, 35 | "stack" : false, 36 | "steppedLine" : false, 37 | "targets" : [ 38 | { 39 | "expr" : "sum(rate(authmilter_arc_total{node=~\"$node\"}[$ratetime])) by(result)", 40 | "interval" : "", 41 | "intervalFactor" : 2, 42 | "legendFormat" : "{{ result }}", 43 | "metric" : "authmilter_dkim_error_total", 44 | "refId" : "A", 45 | "step" : 60 46 | } 47 | ], 48 | "thresholds" : [], 49 | "timeFrom" : null, 50 | "timeShift" : null, 51 | "title" : "ARC results rate", 52 | "tooltip" : { 53 | "msResolution" : false, 54 | "shared" : true, 55 | "sort" : 2, 56 | "value_type" : "cumulative" 57 | }, 58 | "type" : "graph", 59 | "xaxis" : { 60 | "mode" : "time", 61 | "name" : null, 62 | "show" : true, 63 | "values" : [] 64 | }, 65 | "yaxes" : [ 66 | { 67 | "format" : "short", 68 | "label" : null, 69 | "logBase" : 1, 70 | "max" : null, 71 | "min" : null, 72 | "show" : true 73 | }, 74 | { 75 | "format" : "short", 76 | "label" : null, 77 | "logBase" : 1, 78 | "max" : null, 79 | "min" : null, 80 | "show" : true 81 | } 82 | ] 83 | } 84 | ], 85 | "repeat" : null, 86 | "repeatIteration" : null, 87 | "repeatRowId" : null, 88 | "showTitle" : true, 89 | "title" : "ARC Handler", 90 | "titleSize" : "h6" 91 | } 92 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/AddID.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Handler::AddID; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Example handler class 7 | # VERSION 8 | use base 'Mail::Milter::Authentication::Handler'; 9 | 10 | sub default_config { 11 | return {}; 12 | } 13 | 14 | sub eom_callback { 15 | my ($self) = @_; 16 | $self->append_header('X-Authentication-Milter','Header added by Authentication Milter'); 17 | } 18 | 19 | 1; 20 | 21 | __END__ 22 | 23 | =head1 DESCRIPTION 24 | 25 | Simple module which adds a header to all email processed. 26 | 27 | This is meant as an example only. 28 | 29 | =head1 CONFIGURATION 30 | 31 | No configuration options exist for this handler. 32 | 33 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/AlignedFrom_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "dashLength" : 10, 9 | "dashes" : false, 10 | "datasource" : "${DS_PROMETHEUS}", 11 | "editable" : true, 12 | "error" : false, 13 | "fill" : 1, 14 | "grid" : {}, 15 | "id" : 5, 16 | "legend" : { 17 | "avg" : false, 18 | "current" : false, 19 | "hideZero" : true, 20 | "max" : false, 21 | "min" : false, 22 | "show" : true, 23 | "total" : false, 24 | "values" : false 25 | }, 26 | "lines" : true, 27 | "linewidth" : 2, 28 | "links" : [], 29 | "nullPointMode" : "connected", 30 | "percentage" : false, 31 | "pointradius" : 5, 32 | "points" : false, 33 | "renderer" : "flot", 34 | "seriesOverrides" : [], 35 | "spaceLength" : 10, 36 | "span" : 12, 37 | "stack" : false, 38 | "steppedLine" : false, 39 | "targets" : [ 40 | { 41 | "expr" : "sum(rate(authmilter_alignedfrom_total{node=~\"$node\"}[$ratetime])) by(result)", 42 | "interval" : "", 43 | "intervalFactor" : 2, 44 | "legendFormat" : "{{ result }}", 45 | "metric" : "authmilter_dkim_error_total", 46 | "refId" : "A", 47 | "step" : 4 48 | } 49 | ], 50 | "thresholds" : [], 51 | "timeFrom" : null, 52 | "timeShift" : null, 53 | "title" : "AlignedFrom results rate", 54 | "tooltip" : { 55 | "msResolution" : false, 56 | "shared" : true, 57 | "sort" : 2, 58 | "value_type" : "cumulative" 59 | }, 60 | "type" : "graph", 61 | "xaxis" : { 62 | "buckets" : null, 63 | "mode" : "time", 64 | "name" : null, 65 | "show" : true, 66 | "values" : [] 67 | }, 68 | "yaxes" : [ 69 | { 70 | "format" : "short", 71 | "label" : null, 72 | "logBase" : 1, 73 | "max" : null, 74 | "min" : null, 75 | "show" : true 76 | }, 77 | { 78 | "format" : "short", 79 | "label" : null, 80 | "logBase" : 1, 81 | "max" : null, 82 | "min" : null, 83 | "show" : true 84 | } 85 | ] 86 | } 87 | ], 88 | "repeat" : null, 89 | "repeatIteration" : null, 90 | "repeatRowId" : null, 91 | "showTitle" : true, 92 | "title" : "AlignedFrom Handler", 93 | "titleSize" : "h6" 94 | } 95 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/Auth.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Handler::Auth; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Handler class for SMTP Auth 7 | # VERSION 8 | use base 'Mail::Milter::Authentication::Handler'; 9 | 10 | sub default_config { 11 | return {}; 12 | } 13 | 14 | sub grafana_rows { 15 | my ( $self ) = @_; 16 | my @rows; 17 | push @rows, $self->get_json( 'Auth_metrics' ); 18 | return \@rows; 19 | } 20 | 21 | sub register_metrics { 22 | return { 23 | 'authenticated_connect_total' => 'The number of connections from an authenticated host', 24 | }; 25 | } 26 | 27 | sub pre_loop_setup { 28 | my ( $self ) = @_; 29 | my $protocol = Mail::Milter::Authentication::Config::get_config()->{'protocol'}; 30 | if ( $protocol ne 'milter' ) { 31 | warn 'The Auth handler only works with the milter protocol'; 32 | } 33 | } 34 | 35 | sub get_auth_name { 36 | my ($self) = @_; 37 | my $name = $self->get_symbol('{auth_authen}'); 38 | return $name; 39 | } 40 | 41 | sub connect_callback { 42 | my ( $self, $hostname, $ip ) = @_; 43 | $self->{'is_authenticated'} = 0; 44 | } 45 | 46 | sub envfrom_callback { 47 | my ( $self, $env_from ) = @_; 48 | my $auth_name = $self->get_auth_name(); 49 | if ($auth_name) { 50 | $self->dbgout( 'AuthenticatedAs', $auth_name, LOG_INFO ); 51 | # Clear the current auth headers ( iprev and helo may already be added ) 52 | # ToDo is this a good idea? 53 | my $top_handler = $self->get_top_handler(); 54 | for my $type ( sort keys $top_handler->{'c_auth_headers'}->%* ) { 55 | $top_handler->{'c_auth_headers'}->{$type} = []; 56 | } 57 | for my $type ( sort keys $top_handler->{'auth_headers'}->%* ) { 58 | $top_handler->{'auth_headers'}->{$type} = []; 59 | } 60 | $self->{'is_authenticated'} = 1; 61 | $self->metric_count( 'authenticated_connect_total' ); 62 | my $header = Mail::AuthenticationResults::Header::Entry->new()->set_key( 'auth' )->safe_set_value( 'pass' ); 63 | $self->add_auth_header( $header ); 64 | } 65 | } 66 | 67 | sub close_callback { 68 | my ( $self ) = @_; 69 | delete $self->{'is_authenticated'}; 70 | } 71 | 72 | 1; 73 | 74 | __END__ 75 | 76 | =head1 DESCRIPTION 77 | 78 | Module which identifies email that was sent via an authenticated connection. 79 | 80 | =head1 CONFIGURATION 81 | 82 | No configuration options exist for this handler. 83 | 84 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/IPRev_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 42, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "hideEmpty" : false, 18 | "hideZero" : true, 19 | "max" : false, 20 | "min" : false, 21 | "show" : true, 22 | "total" : false, 23 | "values" : false 24 | }, 25 | "lines" : true, 26 | "linewidth" : 2, 27 | "links" : [], 28 | "nullPointMode" : "connected", 29 | "percentage" : false, 30 | "pointradius" : 5, 31 | "points" : false, 32 | "renderer" : "flot", 33 | "seriesOverrides" : [], 34 | "span" : 12, 35 | "stack" : false, 36 | "steppedLine" : false, 37 | "targets" : [ 38 | { 39 | "expr" : "sum(rate(authmilter_iprev_total{node=~\"$node\"}[$ratetime])) by(result)", 40 | "interval" : "", 41 | "intervalFactor" : 2, 42 | "legendFormat" : "{{ result }}", 43 | "metric" : "authmilter_dkim_error_total", 44 | "refId" : "A", 45 | "step" : 60 46 | } 47 | ], 48 | "thresholds" : [], 49 | "timeFrom" : null, 50 | "timeShift" : null, 51 | "title" : "IPRev results rate", 52 | "tooltip" : { 53 | "msResolution" : false, 54 | "shared" : true, 55 | "sort" : 2, 56 | "value_type" : "cumulative" 57 | }, 58 | "type" : "graph", 59 | "xaxis" : { 60 | "mode" : "time", 61 | "name" : null, 62 | "show" : true, 63 | "values" : [] 64 | }, 65 | "yaxes" : [ 66 | { 67 | "format" : "short", 68 | "label" : null, 69 | "logBase" : 1, 70 | "max" : null, 71 | "min" : null, 72 | "show" : true 73 | }, 74 | { 75 | "format" : "short", 76 | "label" : null, 77 | "logBase" : 1, 78 | "max" : null, 79 | "min" : null, 80 | "show" : true 81 | } 82 | ] 83 | } 84 | ], 85 | "repeat" : null, 86 | "repeatIteration" : null, 87 | "repeatRowId" : null, 88 | "showTitle" : true, 89 | "title" : "IPRev Handler", 90 | "titleSize" : "h6" 91 | } 92 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/LocalIP.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Handler::LocalIP; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Handler class for Local IP Connections 7 | # VERSION 8 | use base 'Mail::Milter::Authentication::Handler'; 9 | 10 | sub default_config { 11 | return {}; 12 | } 13 | 14 | sub grafana_rows { 15 | my ( $self ) = @_; 16 | my @rows; 17 | push @rows, $self->get_json( 'LocalIP_metrics' ); 18 | return \@rows; 19 | } 20 | 21 | sub is_local_ip_address { 22 | my ( $self, $ip ) = @_; 23 | my $ip_address = $ip->short(); 24 | my $ip_type = $ip->iptype(); 25 | my $type_map = { 26 | 'PRIVATE' => 1, 27 | 'SHARED' => 1, 28 | 'LOOPBACK' => 1, 29 | 'LINK-LOCAL' => 1, 30 | 'RESERVED' => 1, 31 | 'TEST-NET' => 0, 32 | '6TO4-RELAY' => 0, 33 | 'MULTICAST' => 0, 34 | 'BROADCAST' => 0, 35 | 'UNSPECIFIED' => 0, 36 | 'IPV4MAP' => 0, 37 | 'DISCARD' => 0, 38 | 'GLOBAL-UNICAST' => 0, 39 | 'TEREDO' => 0, 40 | 'BMWG' => 0, 41 | 'DOCUMENTATION' => 0, 42 | 'ORCHID' => 0, 43 | '6TO4' => 0, 44 | 'UNIQUE-LOCAL-UNICAST' => 1, 45 | 'LINK-LOCAL-UNICAST' => 1, 46 | }; 47 | $self->dbgout( 'IPAddress', "Address $ip_address detected as type $ip_type", LOG_DEBUG ); 48 | return $type_map->{ $ip_type } || 0; 49 | } 50 | 51 | sub register_metrics { 52 | return { 53 | 'localip_connect_total' => 'The number of connections from a local IP', 54 | }; 55 | } 56 | 57 | sub connect_callback { 58 | my ( $self, $hostname, $ip ) = @_; 59 | $self->{'is_local_ip_address'} = 0; 60 | if ( $self->is_local_ip_address($ip) ) { 61 | $self->dbgout( 'LocalIP', 'pass', LOG_DEBUG ); 62 | my $header = Mail::AuthenticationResults::Header::Entry->new()->set_key( 'x-local-ip' )->safe_set_value( 'pass' ); 63 | $self->add_c_auth_header( $header ); 64 | $self->{'is_local_ip_address'} = 1; 65 | $self->metric_count( 'localip_connect_total' ); 66 | } 67 | } 68 | 69 | sub close_callback { 70 | my ( $self ) = @_; 71 | delete $self->{'is_local_ip_address'}; 72 | } 73 | 74 | 1; 75 | 76 | __END__ 77 | 78 | =head1 DESCRIPTION 79 | 80 | Detect a Local IP address and act accordingly. 81 | 82 | =head1 CONFIGURATION 83 | 84 | No configuration options exist for this handler. 85 | 86 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/LocalIP_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 12, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "max" : false, 18 | "min" : false, 19 | "show" : true, 20 | "total" : false, 21 | "values" : false 22 | }, 23 | "lines" : true, 24 | "linewidth" : 2, 25 | "links" : [], 26 | "nullPointMode" : "connected", 27 | "percentage" : false, 28 | "pointradius" : 5, 29 | "points" : false, 30 | "renderer" : "flot", 31 | "seriesOverrides" : [], 32 | "span" : 12, 33 | "stack" : false, 34 | "steppedLine" : false, 35 | "targets" : [ 36 | { 37 | "expr" : "sum(rate(authmilter_connect_total{node=~\"$node\"}[$ratetime]))", 38 | "intervalFactor" : 2, 39 | "legendFormat" : "Connections", 40 | "metric" : "authmilter_connect_total", 41 | "refId" : "A", 42 | "step" : 4 43 | }, 44 | { 45 | "expr" : "sum(rate(authmilter_localip_connect_total{node=~\"$node\"}[$ratetime]))", 46 | "interval" : "", 47 | "intervalFactor" : 2, 48 | "legendFormat" : "Local connections", 49 | "metric" : "connect", 50 | "refId" : "B", 51 | "step" : 4 52 | } 53 | ], 54 | "thresholds" : [], 55 | "timeFrom" : null, 56 | "timeShift" : null, 57 | "title" : "Local/NonLocal IP rate", 58 | "tooltip" : { 59 | "msResolution" : false, 60 | "shared" : true, 61 | "sort" : 2, 62 | "value_type" : "cumulative" 63 | }, 64 | "type" : "graph", 65 | "xaxis" : { 66 | "mode" : "time", 67 | "name" : null, 68 | "show" : true, 69 | "values" : [] 70 | }, 71 | "yaxes" : [ 72 | { 73 | "format" : "short", 74 | "label" : null, 75 | "logBase" : 1, 76 | "max" : null, 77 | "min" : null, 78 | "show" : true 79 | }, 80 | { 81 | "format" : "short", 82 | "label" : null, 83 | "logBase" : 1, 84 | "max" : null, 85 | "min" : null, 86 | "show" : true 87 | } 88 | ] 89 | } 90 | ], 91 | "repeat" : null, 92 | "repeatIteration" : null, 93 | "repeatRowId" : null, 94 | "showTitle" : true, 95 | "title" : "LocalIP Handler", 96 | "titleSize" : "h6" 97 | } 98 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/Logger.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Handler::Logger; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Handler class for logging of headerss 7 | # VERSION 8 | use base 'Mail::Milter::Authentication::Handler'; 9 | 10 | use Sys::Syslog qw{:standard :macros}; 11 | 12 | sub default_config { 13 | return { 14 | connect => 0, 15 | helo => 0, 16 | envfrom => 0, 17 | envrcpt => 0, 18 | header => [ 19 | 'from', 20 | 'to', 21 | 'message-id', 22 | ], 23 | }; 24 | } 25 | 26 | sub connect_callback { 27 | my ( $self, $hostname, $ip ) = @_; 28 | my $config = $self->handler_config(); 29 | return if ! $config->{connect}; 30 | $self->dbgout( 'Logger', 'Connection host: ' . $hostname, LOG_INFO ); 31 | $self->dbgout( 'Logger', 'Connection IP: ' . $ip->short(), LOG_INFO ); 32 | return; 33 | } 34 | 35 | sub helo_callback { 36 | my ( $self, $helo_host ) = @_; 37 | my $config = $self->handler_config(); 38 | return if ! $config->{helo}; 39 | $self->dbgout( 'Logger', 'HELO: ' . $helo_host, LOG_INFO ); 40 | return; 41 | } 42 | 43 | sub envfrom_callback { 44 | my ( $self, $env_from ) = @_; 45 | my $config = $self->handler_config(); 46 | return if ! $config->{envfrom}; 47 | $self->dbgout( 'Logger', 'MAIL FROM: ' . $env_from, LOG_INFO ); 48 | return; 49 | } 50 | 51 | sub envrcpt_callback { 52 | my ( $self, $env_to ) = @_; 53 | my $config = $self->handler_config(); 54 | return if ! $config->{envrcpt}; 55 | $self->dbgout( 'Logger', 'RCPT TO: ' . $env_to, LOG_INFO ); 56 | return; 57 | } 58 | 59 | sub header_callback { 60 | my ( $self, $header, $value ) = @_; 61 | my $config = $self->handler_config(); 62 | return if ! $config->{header}; 63 | my @wanted = map { lc $_ } sort $config->{header}->@*; 64 | if ( grep { $_ eq lc( $header ) } @wanted ) { 65 | $self->dbgout( 'Logger', 'Header: ' . $header . ': ' . $value, LOG_INFO ); 66 | } 67 | return; 68 | } 69 | 70 | 1; 71 | 72 | __END__ 73 | 74 | =head1 DESCRIPTION 75 | 76 | Log things 77 | 78 | =head1 CONFIGURATION 79 | 80 | "Logger" : { | 81 | "connect" : 1, | Log connection details 82 | "helo" : 1, | Log HELO details 83 | "envfrom" : 1, | Log Mail From details 84 | "envrcpt" : 1, | Log Mail To details 85 | "header" : [ | List of headers to log 86 | "From", 87 | "To", 88 | "Message-Id", 89 | ] 90 | } 91 | 92 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/PTR.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Handler::PTR; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Handler class for PTR checking 7 | # VERSION 8 | use base 'Mail::Milter::Authentication::Handler'; 9 | 10 | sub default_config { 11 | return {}; 12 | } 13 | 14 | sub grafana_rows { 15 | my ( $self ) = @_; 16 | my @rows; 17 | push @rows, $self->get_json( 'PTR_metrics' ); 18 | return \@rows; 19 | } 20 | 21 | sub register_metrics { 22 | return { 23 | 'ptr_total' => 'The number of emails processed for PTR', 24 | }; 25 | } 26 | 27 | sub helo_callback { 28 | 29 | # On HELO 30 | my ( $self, $helo_host ) = @_; 31 | return if ( $self->is_local_ip_address() ); 32 | return if ( $self->is_trusted_ip_address() ); 33 | return if ( $self->is_authenticated() ); 34 | 35 | if ( ! $self->is_handler_loaded( 'IPRev' ) ) { 36 | $self->log_error( 'PTR Config Error: IPRev is missing '); 37 | return; 38 | } 39 | 40 | my $iprev_handler = $self->get_handler('IPRev'); 41 | my $domains = 42 | exists( $iprev_handler->{'verified_ptr'} ) 43 | ? $iprev_handler->{'verified_ptr'} 44 | : q{}; 45 | 46 | my $found_match = 0; 47 | 48 | foreach my $domain ( split ',', $domains ) { 49 | if ( lc $domain eq lc $helo_host ) { 50 | $found_match = 1; 51 | } 52 | } 53 | 54 | my $result = $found_match ? 'pass' : 'fail'; 55 | $self->dbgout( 'PTRMatch', $result, LOG_DEBUG ); 56 | my $header = Mail::AuthenticationResults::Header::Entry->new()->set_key( 'x-ptr' )->safe_set_value( $result ); 57 | $header->add_child( Mail::AuthenticationResults::Header::SubEntry->new()->set_key( 'smtp.helo' )->safe_set_value( $helo_host ) ); 58 | $header->add_child( Mail::AuthenticationResults::Header::SubEntry->new()->set_key( 'policy.ptr' )->safe_set_value( $domains ) ); 59 | $self->add_c_auth_header( $header ); 60 | $self->metric_count( 'ptr_total', { 'result' => $result} ); 61 | } 62 | 63 | 1; 64 | 65 | __END__ 66 | 67 | =head1 DESCRIPTION 68 | 69 | Check DNS PTR Records match. 70 | 71 | This handler requires the IPRev handler to be installed and active. 72 | 73 | =head1 CONFIGURATION 74 | 75 | No configuration options exist for this handler. 76 | 77 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/PTR_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 43, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "hideEmpty" : false, 18 | "hideZero" : true, 19 | "max" : false, 20 | "min" : false, 21 | "show" : true, 22 | "total" : false, 23 | "values" : false 24 | }, 25 | "lines" : true, 26 | "linewidth" : 2, 27 | "links" : [], 28 | "nullPointMode" : "connected", 29 | "percentage" : false, 30 | "pointradius" : 5, 31 | "points" : false, 32 | "renderer" : "flot", 33 | "seriesOverrides" : [], 34 | "span" : 12, 35 | "stack" : false, 36 | "steppedLine" : false, 37 | "targets" : [ 38 | { 39 | "expr" : "sum(rate(authmilter_ptr_total{node=~\"$node\"}[$ratetime])) by(result)", 40 | "interval" : "", 41 | "intervalFactor" : 2, 42 | "legendFormat" : "{{ result }}", 43 | "metric" : "authmilter_dkim_error_total", 44 | "refId" : "A", 45 | "step" : 60 46 | } 47 | ], 48 | "thresholds" : [], 49 | "timeFrom" : null, 50 | "timeShift" : null, 51 | "title" : "PTR results rate", 52 | "tooltip" : { 53 | "msResolution" : false, 54 | "shared" : true, 55 | "sort" : 2, 56 | "value_type" : "cumulative" 57 | }, 58 | "type" : "graph", 59 | "xaxis" : { 60 | "mode" : "time", 61 | "name" : null, 62 | "show" : true, 63 | "values" : [] 64 | }, 65 | "yaxes" : [ 66 | { 67 | "format" : "short", 68 | "label" : null, 69 | "logBase" : 1, 70 | "max" : null, 71 | "min" : null, 72 | "show" : true 73 | }, 74 | { 75 | "format" : "short", 76 | "label" : null, 77 | "logBase" : 1, 78 | "max" : null, 79 | "min" : null, 80 | "show" : true 81 | } 82 | ] 83 | } 84 | ], 85 | "repeat" : null, 86 | "repeatIteration" : null, 87 | "repeatRowId" : null, 88 | "showTitle" : true, 89 | "title" : "PTR Handler", 90 | "titleSize" : "h6" 91 | } 92 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/SPF_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : "250px", 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 3, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "hideZero" : true, 18 | "max" : false, 19 | "min" : false, 20 | "show" : true, 21 | "total" : false, 22 | "values" : false 23 | }, 24 | "lines" : true, 25 | "linewidth" : 2, 26 | "links" : [], 27 | "nullPointMode" : "connected", 28 | "percentage" : false, 29 | "pointradius" : 5, 30 | "points" : false, 31 | "renderer" : "flot", 32 | "seriesOverrides" : [], 33 | "span" : 12, 34 | "stack" : false, 35 | "steppedLine" : false, 36 | "targets" : [ 37 | { 38 | "expr" : "sum(rate(authmilter_spf_total{node=~\"$node\"}[$ratetime])) by(result)", 39 | "interval" : "", 40 | "intervalFactor" : 2, 41 | "legendFormat" : "{{ result }}", 42 | "metric" : "", 43 | "refId" : "A", 44 | "step" : 4 45 | } 46 | ], 47 | "thresholds" : [], 48 | "timeFrom" : null, 49 | "timeShift" : null, 50 | "title" : "SPF results rate", 51 | "tooltip" : { 52 | "msResolution" : false, 53 | "shared" : true, 54 | "sort" : 2, 55 | "value_type" : "cumulative" 56 | }, 57 | "type" : "graph", 58 | "xaxis" : { 59 | "mode" : "time", 60 | "name" : null, 61 | "show" : true, 62 | "values" : [] 63 | }, 64 | "yaxes" : [ 65 | { 66 | "format" : "short", 67 | "label" : null, 68 | "logBase" : 1, 69 | "max" : null, 70 | "min" : null, 71 | "show" : true 72 | }, 73 | { 74 | "format" : "short", 75 | "label" : null, 76 | "logBase" : 1, 77 | "max" : null, 78 | "min" : null, 79 | "show" : true 80 | } 81 | ] 82 | } 83 | ], 84 | "repeat" : null, 85 | "repeatIteration" : null, 86 | "repeatRowId" : null, 87 | "showTitle" : true, 88 | "title" : "SPF Handler", 89 | "titleSize" : "h6" 90 | } 91 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/Sanitize_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "dashLength" : 10, 9 | "dashes" : false, 10 | "datasource" : "${DS_PROMETHEUS}", 11 | "editable" : true, 12 | "error" : false, 13 | "fill" : 1, 14 | "grid" : {}, 15 | "id" : 40, 16 | "legend" : { 17 | "avg" : false, 18 | "current" : false, 19 | "max" : false, 20 | "min" : false, 21 | "show" : true, 22 | "total" : false, 23 | "values" : false 24 | }, 25 | "lines" : true, 26 | "linewidth" : 2, 27 | "links" : [], 28 | "nullPointMode" : "connected", 29 | "percentage" : false, 30 | "pointradius" : 5, 31 | "points" : false, 32 | "renderer" : "flot", 33 | "seriesOverrides" : [], 34 | "spaceLength" : 10, 35 | "span" : 12, 36 | "stack" : false, 37 | "steppedLine" : false, 38 | "targets" : [ 39 | { 40 | "expr" : "sum(rate(authmilter_sanitize_remove_total{node=~\"$node\"}[$ratetime])) by(header)", 41 | "format" : "time_series", 42 | "interval" : "", 43 | "intervalFactor" : 2, 44 | "legendFormat" : "{{ header }}", 45 | "metric" : "connect", 46 | "refId" : "B", 47 | "step" : 30 48 | } 49 | ], 50 | "thresholds" : [], 51 | "timeFrom" : null, 52 | "timeShift" : null, 53 | "title" : "Sanitized headers rate", 54 | "tooltip" : { 55 | "msResolution" : false, 56 | "shared" : true, 57 | "sort" : 2, 58 | "value_type" : "cumulative" 59 | }, 60 | "type" : "graph", 61 | "xaxis" : { 62 | "buckets" : null, 63 | "mode" : "time", 64 | "name" : null, 65 | "show" : true, 66 | "values" : [] 67 | }, 68 | "yaxes" : [ 69 | { 70 | "format" : "short", 71 | "label" : null, 72 | "logBase" : 1, 73 | "max" : null, 74 | "min" : null, 75 | "show" : true 76 | }, 77 | { 78 | "format" : "short", 79 | "label" : null, 80 | "logBase" : 1, 81 | "max" : null, 82 | "min" : null, 83 | "show" : true 84 | } 85 | ] 86 | } 87 | ], 88 | "repeat" : null, 89 | "repeatIteration" : null, 90 | "repeatRowId" : null, 91 | "showTitle" : true, 92 | "title" : "Sanitize Handler", 93 | "titleSize" : "h6" 94 | } 95 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/SenderID_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 38, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "hideZero" : true, 18 | "max" : false, 19 | "min" : false, 20 | "show" : true, 21 | "total" : false, 22 | "values" : false 23 | }, 24 | "lines" : true, 25 | "linewidth" : 2, 26 | "links" : [], 27 | "nullPointMode" : "connected", 28 | "percentage" : false, 29 | "pointradius" : 5, 30 | "points" : false, 31 | "renderer" : "flot", 32 | "seriesOverrides" : [], 33 | "span" : 12, 34 | "stack" : false, 35 | "steppedLine" : false, 36 | "targets" : [ 37 | { 38 | "expr" : "sum(rate(authmilter_senderid_total{node=~\"$node\"}[$ratetime])) by(result)", 39 | "interval" : "", 40 | "intervalFactor" : 2, 41 | "legendFormat" : "{{ result }}", 42 | "metric" : "", 43 | "refId" : "A", 44 | "step" : 240 45 | } 46 | ], 47 | "thresholds" : [], 48 | "timeFrom" : null, 49 | "timeShift" : null, 50 | "title" : "SenderID results rate", 51 | "tooltip" : { 52 | "msResolution" : false, 53 | "shared" : true, 54 | "sort" : 2, 55 | "value_type" : "cumulative" 56 | }, 57 | "type" : "graph", 58 | "xaxis" : { 59 | "mode" : "time", 60 | "name" : null, 61 | "show" : true, 62 | "values" : [] 63 | }, 64 | "yaxes" : [ 65 | { 66 | "format" : "short", 67 | "label" : null, 68 | "logBase" : 1, 69 | "max" : null, 70 | "min" : null, 71 | "show" : true 72 | }, 73 | { 74 | "format" : "short", 75 | "label" : null, 76 | "logBase" : 1, 77 | "max" : null, 78 | "min" : null, 79 | "show" : true 80 | } 81 | ] 82 | } 83 | ], 84 | "repeat" : null, 85 | "repeatIteration" : null, 86 | "repeatRowId" : null, 87 | "showTitle" : true, 88 | "title" : "SenderID Handler", 89 | "titleSize" : "h6" 90 | } 91 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/Size.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Handler::Size; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Handler class for message size metrics 7 | # VERSION 8 | use base 'Mail::Milter::Authentication::Handler'; 9 | 10 | sub default_config { 11 | return {}; 12 | } 13 | 14 | sub grafana_rows { 15 | my ( $self ) = @_; 16 | my @rows; 17 | push @rows, $self->get_json( 'Size_metrics' ); 18 | return \@rows; 19 | } 20 | 21 | sub register_metrics { 22 | return { 23 | 'size_total' => 'The number of emails processed for Size', 24 | 'size_header_bytes_added_total' => 'The header size added to emails processed for Size', 25 | 'size_header_bytes_total' => 'The header size of emails processed for Size', 26 | 'size_body_bytes_total' => 'The body size of emails processed for Size', 27 | }; 28 | } 29 | 30 | sub envfrom_callback { 31 | my ( $self, $env_from ) = @_; 32 | $self->{'headersize'} = 0; 33 | $self->{'bodysize'} = 0; 34 | } 35 | 36 | sub header_callback { 37 | my ( $self, $header, $value ) = @_; 38 | $self->{ 'headersize' } = $self->{ 'headersize' } + length( $header . ': ' . $value ) + 2; 39 | } 40 | 41 | sub body_callback { 42 | my ( $self, $body_chunk ) = @_; 43 | $self->{ 'bodysize' } = $self->{ 'bodysize' } + length ( $body_chunk ); 44 | } 45 | 46 | sub eom_callback { 47 | my ($self) = @_; 48 | $self->metric_count( 'size_total', {}, 1 ); 49 | $self->metric_count( 'size_header_bytes_total', {}, $self->{ 'headersize' } ); 50 | $self->metric_count( 'size_body_bytes_total', {}, $self->{ 'bodysize' } ); 51 | } 52 | 53 | sub close_callback { 54 | my ( $self ) = @_; 55 | 56 | my $top_handler = $self->get_top_handler(); 57 | if ( exists( $top_handler->{'pre_headers'} ) ) { 58 | foreach my $header ( @{ $top_handler->{'pre_headers'} } ) { 59 | my $size = length( $header->{'field'} ) + length ( $header->{'value'} ) + 3; 60 | $self->metric_count( 'size_header_bytes_added_total', { where => 'pre', 'header' => $header->{'field'} }, $size ); 61 | } 62 | } 63 | if ( exists( $top_handler->{'add_headers'} ) ) { 64 | foreach my $header ( @{ $top_handler->{'add_headers'} } ) { 65 | my $size = length( $header->{'field'} ) + length ( $header->{'value'} ) + 3; 66 | $self->metric_count( 'size_header_bytes_added_total', { where => 'add', 'header' => $header->{'field'} }, $size ); 67 | } 68 | } 69 | 70 | delete $self->{'bodysize'}; 71 | delete $self->{'headersize'}; 72 | } 73 | 74 | 1; 75 | 76 | __END__ 77 | 78 | =head1 DESCRIPTION 79 | 80 | Module to provide metrics related to message size. 81 | 82 | =head1 CONFIGURATION 83 | 84 | "Size" : {}, | Config for the Size Module 85 | 86 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/TestTimeout.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Handler::TestTimeout; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | use Mail::Milter::Authentication::Pragmas; 6 | # ABSTRACT: Timeout Tester 7 | # VERSION 8 | use base 'Mail::Milter::Authentication::Handler'; 9 | 10 | sub _timeout { 11 | alarm ( 1 ); 12 | sleep 10; 13 | return; 14 | } 15 | 16 | 17 | sub connect_callback { return _timeout(); } 18 | sub helo_callback { return _timeout(); } 19 | sub envfrom_callback { return _timeout(); } 20 | sub envrcpt_callback { return _timeout(); } 21 | sub header_callback { return _timeout(); } 22 | sub eoh_callback { return _timeout(); } 23 | sub body_callback { return _timeout(); } 24 | sub eom_callback { return _timeout(); } 25 | sub abort_callback { return _timeout(); } 26 | sub close_callback { return _timeout(); } 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/TrustedIP_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 39, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "max" : false, 18 | "min" : false, 19 | "show" : true, 20 | "total" : false, 21 | "values" : false 22 | }, 23 | "lines" : true, 24 | "linewidth" : 2, 25 | "links" : [], 26 | "nullPointMode" : "connected", 27 | "percentage" : false, 28 | "pointradius" : 5, 29 | "points" : false, 30 | "renderer" : "flot", 31 | "seriesOverrides" : [], 32 | "span" : 12, 33 | "stack" : false, 34 | "steppedLine" : false, 35 | "targets" : [ 36 | { 37 | "expr" : "sum(rate(authmilter_connect_total{node=~\"$node\"}[$ratetime]))", 38 | "intervalFactor" : 2, 39 | "legendFormat" : "Connections", 40 | "metric" : "authmilter_connect_total", 41 | "refId" : "A", 42 | "step" : 2 43 | }, 44 | { 45 | "expr" : "sum(rate(authmilter_trustedip_connect_total{node=~\"$node\"}[$ratetime]))", 46 | "interval" : "", 47 | "intervalFactor" : 2, 48 | "legendFormat" : "Trusted connections", 49 | "metric" : "connect", 50 | "refId" : "B", 51 | "step" : 2 52 | } 53 | ], 54 | "thresholds" : [], 55 | "timeFrom" : null, 56 | "timeShift" : null, 57 | "title" : "Trusted connections IP rate", 58 | "tooltip" : { 59 | "msResolution" : false, 60 | "shared" : true, 61 | "sort" : 2, 62 | "value_type" : "cumulative" 63 | }, 64 | "type" : "graph", 65 | "xaxis" : { 66 | "mode" : "time", 67 | "name" : null, 68 | "show" : true, 69 | "values" : [] 70 | }, 71 | "yaxes" : [ 72 | { 73 | "format" : "short", 74 | "label" : null, 75 | "logBase" : 1, 76 | "max" : null, 77 | "min" : null, 78 | "show" : true 79 | }, 80 | { 81 | "format" : "short", 82 | "label" : null, 83 | "logBase" : 1, 84 | "max" : null, 85 | "min" : null, 86 | "show" : true 87 | } 88 | ] 89 | } 90 | ], 91 | "repeat" : null, 92 | "repeatIteration" : null, 93 | "repeatRowId" : null, 94 | "showTitle" : true, 95 | "title" : "TrustedIP Handler", 96 | "titleSize" : "h6" 97 | } 98 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Handler/XGoogleDKIM_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : 250, 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 1, 12 | "grid" : {}, 13 | "id" : 5, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "hideZero" : true, 18 | "max" : false, 19 | "min" : false, 20 | "show" : true, 21 | "total" : false, 22 | "values" : false 23 | }, 24 | "lines" : true, 25 | "linewidth" : 2, 26 | "links" : [], 27 | "nullPointMode" : "connected", 28 | "percentage" : false, 29 | "pointradius" : 5, 30 | "points" : false, 31 | "renderer" : "flot", 32 | "seriesOverrides" : [], 33 | "span" : 12, 34 | "stack" : false, 35 | "steppedLine" : false, 36 | "targets" : [ 37 | { 38 | "expr" : "sum(rate(authmilter_xgoogledkim_total{node=~\"$node\"}[$ratetime])) by(result)", 39 | "interval" : "", 40 | "intervalFactor" : 2, 41 | "legendFormat" : "{{ result }}", 42 | "metric" : "authmilter_dkim_error_total", 43 | "refId" : "A", 44 | "step" : 4 45 | } 46 | ], 47 | "thresholds" : [], 48 | "timeFrom" : null, 49 | "timeShift" : null, 50 | "title" : "X-Google-DKIM results rate", 51 | "tooltip" : { 52 | "msResolution" : false, 53 | "shared" : true, 54 | "sort" : 2, 55 | "value_type" : "cumulative" 56 | }, 57 | "type" : "graph", 58 | "xaxis" : { 59 | "mode" : "time", 60 | "name" : null, 61 | "show" : true, 62 | "values" : [] 63 | }, 64 | "yaxes" : [ 65 | { 66 | "format" : "short", 67 | "label" : null, 68 | "logBase" : 1, 69 | "max" : null, 70 | "min" : null, 71 | "show" : true 72 | }, 73 | { 74 | "format" : "short", 75 | "label" : null, 76 | "logBase" : 1, 77 | "max" : null, 78 | "min" : null, 79 | "show" : true 80 | } 81 | ] 82 | } 83 | ], 84 | "repeat" : null, 85 | "repeatIteration" : null, 86 | "repeatRowId" : null, 87 | "showTitle" : true, 88 | "title" : "XGoogleDKIM Handler", 89 | "titleSize" : "h6" 90 | } 91 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Metric/RowErrors.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : "250px", 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "dashLength" : 10, 9 | "dashes" : false, 10 | "datasource" : "${DS_PROMETHEUS}", 11 | "editable" : true, 12 | "error" : false, 13 | "fill" : 1, 14 | "grid" : {}, 15 | "id" : 10, 16 | "legend" : { 17 | "avg" : false, 18 | "current" : false, 19 | "hideZero" : true, 20 | "max" : false, 21 | "min" : false, 22 | "show" : true, 23 | "total" : false, 24 | "values" : false 25 | }, 26 | "lines" : true, 27 | "linewidth" : 2, 28 | "links" : [], 29 | "nullPointMode" : "connected", 30 | "percentage" : false, 31 | "pointradius" : 5, 32 | "points" : false, 33 | "renderer" : "flot", 34 | "seriesOverrides" : [], 35 | "spaceLength" : 10, 36 | "span" : 12, 37 | "stack" : false, 38 | "steppedLine" : false, 39 | "targets" : [ 40 | { 41 | "expr" : "sum(authmilter_callback_error_total{node=~\"$node\"}) by(stage,node,handler,type)", 42 | "format" : "time_series", 43 | "interval" : "", 44 | "intervalFactor" : 2, 45 | "legendFormat" : "{{ node }} {{ handler }} {{ stage }} {{ type }}", 46 | "metric" : "authmilter_call", 47 | "refId" : "A", 48 | "step" : 4 49 | } 50 | ], 51 | "thresholds" : [], 52 | "timeFrom" : null, 53 | "timeShift" : null, 54 | "title" : "Callback Errors Total", 55 | "tooltip" : { 56 | "msResolution" : false, 57 | "shared" : true, 58 | "sort" : 2, 59 | "value_type" : "cumulative" 60 | }, 61 | "type" : "graph", 62 | "xaxis" : { 63 | "buckets" : null, 64 | "mode" : "time", 65 | "name" : null, 66 | "show" : true, 67 | "values" : [] 68 | }, 69 | "yaxes" : [ 70 | { 71 | "format" : "short", 72 | "label" : null, 73 | "logBase" : 1, 74 | "max" : null, 75 | "min" : null, 76 | "show" : true 77 | }, 78 | { 79 | "format" : "short", 80 | "label" : null, 81 | "logBase" : 1, 82 | "max" : null, 83 | "min" : null, 84 | "show" : true 85 | } 86 | ] 87 | } 88 | ], 89 | "repeat" : null, 90 | "repeatIteration" : null, 91 | "repeatRowId" : null, 92 | "showTitle" : true, 93 | "title" : "Errors", 94 | "titleSize" : "h6" 95 | } 96 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Metric/RowUptime.json: -------------------------------------------------------------------------------- 1 | { 2 | "collapse" : true, 3 | "height" : "250px", 4 | "panels" : [ 5 | { 6 | "aliasColors" : {}, 7 | "bars" : false, 8 | "datasource" : "${DS_PROMETHEUS}", 9 | "editable" : true, 10 | "error" : false, 11 | "fill" : 0, 12 | "grid" : {}, 13 | "id" : 11, 14 | "legend" : { 15 | "avg" : false, 16 | "current" : false, 17 | "max" : false, 18 | "min" : false, 19 | "show" : true, 20 | "total" : false, 21 | "values" : false 22 | }, 23 | "lines" : true, 24 | "linewidth" : 2, 25 | "links" : [], 26 | "nullPointMode" : "connected", 27 | "percentage" : false, 28 | "pointradius" : 5, 29 | "points" : false, 30 | "renderer" : "flot", 31 | "seriesOverrides" : [], 32 | "span" : 12, 33 | "stack" : false, 34 | "steppedLine" : false, 35 | "targets" : [ 36 | { 37 | "expr" : "sum(authmilter_uptime_seconds_total{node=~\"$node\"}) by(node)", 38 | "intervalFactor" : 2, 39 | "legendFormat" : "Uptime {{ node }}", 40 | "refId" : "A", 41 | "step" : 4 42 | } 43 | ], 44 | "thresholds" : [], 45 | "timeFrom" : null, 46 | "timeShift" : null, 47 | "title" : "Uptime", 48 | "tooltip" : { 49 | "msResolution" : false, 50 | "shared" : true, 51 | "sort" : 2, 52 | "value_type" : "cumulative" 53 | }, 54 | "type" : "graph", 55 | "xaxis" : { 56 | "mode" : "time", 57 | "name" : null, 58 | "show" : true, 59 | "values" : [] 60 | }, 61 | "yaxes" : [ 62 | { 63 | "format" : "s", 64 | "label" : "", 65 | "logBase" : 1, 66 | "max" : null, 67 | "min" : null, 68 | "show" : true 69 | }, 70 | { 71 | "format" : "short", 72 | "label" : null, 73 | "logBase" : 1, 74 | "max" : null, 75 | "min" : null, 76 | "show" : true 77 | } 78 | ] 79 | } 80 | ], 81 | "repeat" : null, 82 | "repeatIteration" : null, 83 | "repeatRowId" : null, 84 | "showTitle" : true, 85 | "title" : "Uptime", 86 | "titleSize" : "h6" 87 | } 88 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/Pragmas.pm: -------------------------------------------------------------------------------- 1 | package Mail::Milter::Authentication::Pragmas; 2 | use 5.20.0; 3 | use strict; 4 | use warnings; 5 | # ABSTRACT: Setup system wide pragmas 6 | # VERSION 7 | use base 'Exporter'; 8 | require feature; 9 | use open ':std', ':encoding(UTF-8)'; 10 | use Import::Into; 11 | 12 | use Mail::Milter::Authentication::Constants; 13 | use Mail::Milter::Authentication::Config; 14 | use Carp; 15 | use Clone; 16 | use English; 17 | use File::Slurp; 18 | use JSON::XS; 19 | use Module::Load; 20 | use Module::Loaded; 21 | use Mail::AuthenticationResults 1.20200108; 22 | use Mail::AuthenticationResults::Header; 23 | use Mail::AuthenticationResults::Header::AuthServID; 24 | use Mail::AuthenticationResults::Header::Comment; 25 | use Mail::AuthenticationResults::Header::Entry; 26 | use Mail::AuthenticationResults::Header::SubEntry; 27 | 28 | 29 | sub import { 30 | strict->import(); 31 | warnings->import(); 32 | feature->import($_) for ( qw{ postderef signatures } ); 33 | warnings->unimport($_) for ( qw{ experimental::postderef experimental::signatures } ); 34 | 35 | Mail::Milter::Authentication::Config->import::into(scalar caller,qw{ set_config get_config setup_config }); 36 | Mail::Milter::Authentication::Constants->import::into(scalar caller); 37 | 38 | Carp->import::into(scalar caller); 39 | Clone->import::into(scalar caller,qw{ clone }); 40 | English->import::into(scalar caller); 41 | File::Slurp->import::into(scalar caller, qw{ read_file write_file } ); 42 | JSON::XS->import::into(scalar caller); 43 | Module::Load->import::into(scalar caller); 44 | Module::Loaded->import::into(scalar caller); 45 | } 46 | 47 | 1; 48 | -------------------------------------------------------------------------------- /lib/Mail/Milter/Authentication/htdocs/css/authmilter.css: -------------------------------------------------------------------------------- 1 | HTTP/1.0 200 OK 2 | Content-Type: text/css 3 | 4 | body { 5 | background: #ddeeff; 6 | color: #003366; 7 | border-top: 4px solid #003366; 8 | } 9 | 10 | h1 { 11 | font-size: 4rem; 12 | border-bottom: 1px solid grey; 13 | color: black; 14 | } 15 | 16 | h2 { 17 | font-size: 2rem; 18 | font-weight: bold; 19 | margin-bottom: 0.25em; 20 | } 21 | 22 | hr { 23 | border-top: 1px solid grey; 24 | } 25 | 26 | li { 27 | margin-bottom: 0; 28 | } 29 | 30 | ul ul { 31 | margin-top: 0; 32 | } 33 | 34 | .spaceAfter { 35 | margin-bottom: 2.5rem; 36 | } 37 | 38 | .handler { 39 | padding: .2rem .5rem; 40 | margin: 0 .2rem; 41 | white-space: nowrap; 42 | background: #e1e1F1; 43 | border: 1px solid #d1d1E1; 44 | border-radius: 4px; 45 | font-family: monospace; 46 | } 47 | 48 | .callbackstable tr td { 49 | padding: 0.25rem 1rem; 50 | border: 0; 51 | } 52 | 53 | .versionBlock { 54 | right: 0px; 55 | position: absolute; 56 | top: 0; 57 | display: inline-block; 58 | text-align: right; 59 | } 60 | -------------------------------------------------------------------------------- /share/authentication_milter.init: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: authentication_milter 5 | # Required-Start: $remote_fs 6 | # Required-Stop: $remote_fs 7 | # Should-Start: $network $syslog 8 | # Default-Start: 2 3 4 5 9 | # Default-Stop: 0 1 6 10 | ### END INIT INFO 11 | 12 | DAEMON=/usr/local/bin/authentication_milter 13 | NAME=authentication_milter 14 | SNAME=authentication_milter 15 | DESC="Authentication Mail Filter Daemon" 16 | PIDFILE="/run/$NAME.pid" 17 | 18 | export TMPDIR=/tmp 19 | cd $TMPDIR 20 | 21 | . /lib/lsb/init-functions 22 | 23 | test -f /etc/default/authentication_milter && . /etc/default/authentication_milter 24 | 25 | DOPTIONS="--pidfile=$PIDFILE" 26 | 27 | if [ "$ENABLED" = "0" ]; then 28 | echo "$DESC: disabled, see /etc/default/authentication_milter" 29 | exit 0 30 | fi 31 | 32 | test -f $DAEMON || exit 0 33 | 34 | case "$1" in 35 | 36 | start) 37 | echo -n "Starting $DESC: " 38 | $DAEMON $DOPTIONS --control=start 39 | echo "$NAME." 40 | ;; 41 | 42 | stop) 43 | echo -n "Stopping $DESC: " 44 | $DAEMON $DOPTIONS --control=stop 45 | /bin/rm $PIDFILE 46 | echo "$NAME." 47 | ;; 48 | 49 | reload|force-reload) 50 | echo -n "Reloading $DESC: " 51 | $DAEMON $DOPTIONS --control=restart 52 | echo "$NAME." 53 | ;; 54 | 55 | restart) 56 | echo -n "Restarting $DESC: " 57 | $DAEMON $DOPTIONS --control=restart 58 | echo "$NAME." 59 | ;; 60 | 61 | status) 62 | $DAEMON $DOPTIONS --control=status 63 | ;; 64 | 65 | *) 66 | N=/etc/init.d/$SNAME 67 | echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2 68 | exit 1 69 | ;; 70 | 71 | esac 72 | 73 | exit 0 74 | -------------------------------------------------------------------------------- /share/authentication_milter.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug" : 0, 3 | "dryrun" : 0, 4 | "logtoerr" : 0, 5 | "error_log" : "/var/log/authentication_milter.err", 6 | 7 | "connection" : "inet:12345@localhost", 8 | "umask" : "0000", 9 | "runas" : "nobody", 10 | "rungroup" : "nogroup", 11 | "chroot" : "", 12 | 13 | "listen_backlog" : 20, 14 | "min_children" : 20, 15 | "max_children" : 200, 16 | "min_spare_children" : 10, 17 | "max_spare_children" : 20, 18 | "max_requests_per_child" : 200, 19 | 20 | "connect_timeout" : 30, 21 | "command_timeout" : 30, 22 | "content_timeout" : 300, 23 | "dns_timeout" : 10, 24 | "dns_retry" : 2, 25 | "cache_dns_timeouts" : 1, 26 | 27 | "tempfail_on_error" : "1", 28 | "tempfail_on_error_authenticated" : "0", 29 | "tempfail_on_error_local" : "0", 30 | "tempfail_on_error_trusted" : "0", 31 | 32 | "handlers" : { 33 | 34 | "SPF" : { 35 | "hide_none" : 0 36 | }, 37 | 38 | "DKIM" : { 39 | "hide_none" : 0, 40 | "check_adsp" : 1, 41 | "show_default_adsp" : 0, 42 | "adsp_hide_none" : 0 43 | }, 44 | 45 | "DMARC" : { 46 | "hide_none" : 0, 47 | "detect_list_id" : "1" 48 | }, 49 | 50 | "PTR" : {}, 51 | 52 | "SenderID" : { 53 | "hide_none" : 1 54 | }, 55 | 56 | "IPRev" : {}, 57 | 58 | "Auth" : {}, 59 | 60 | "LocalIP" : {}, 61 | 62 | "TrustedIP" : { 63 | "trusted_ip_list" : [ 64 | "100.200.100.2", 65 | "2001:44c2:3881:aa00::/56", 66 | "2001:44b8:3021:123:dead:beef:abcd:1234" 67 | ] 68 | }, 69 | 70 | "!AddID" : {}, 71 | 72 | "ReturnOK" : {}, 73 | 74 | "Sanitize" : { 75 | "hosts_to_remove" : [ 76 | "example.com", 77 | "example.net" 78 | ], 79 | "remove_headers" : "yes" 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /share/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = example.com 4 | org_name = My Company Limited 5 | email = admin@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | ;dsn = dbi:SQLite:dbname=dmarc_reports.sqlite 15 | dsn = dbi:mysql:database=dmarc_reporting_database;host=localhost;port=3306 16 | user = authmilterusername 17 | pass = authmiltpassword 18 | 19 | ; backend can be perl or libopendmarc 20 | [dmarc] 21 | backend = perl 22 | 23 | [dns] 24 | timeout = 5 25 | public_suffix_list = share/public_suffix_list 26 | 27 | [smtp] 28 | ; hostname is the external FQDN of this MTA 29 | hostname = mx1.example.com 30 | cc = dmarc.copy@example.com 31 | 32 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 33 | ; see sample whitelist in share/dmarc_whitelist 34 | whitelist = /path/to/etc/dmarc_whitelist 35 | 36 | ; By default, we attempt to email directly to the report recipient. 37 | ; Set these to relay via a SMTP smart host. 38 | smarthost = mx2.example.com 39 | smartuser = dmarccopyusername 40 | smartpass = dmarccopypassword 41 | 42 | [imap] 43 | server = mail.example.com 44 | user = 45 | pass = 46 | ; the imap folder where new dmarc messages will be found 47 | folder = dmarc 48 | ; the folders to store processed reports (a=aggregate, f=forensic) 49 | f_done = dmarc.forensic 50 | a_done = dmarc.aggregate 51 | 52 | [http] 53 | port = 8080 54 | 55 | [https] 56 | port = 8443 57 | ssl_crt = 58 | ssl_key = 59 | 60 | -------------------------------------------------------------------------------- /t/00-load.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use Test::More; 6 | 7 | BEGIN { 8 | 9 | my @Modules = qw{ 10 | Mail::Milter::Authentication::App::Blocker::App::Command::list 11 | Mail::Milter::Authentication::App::Blocker::App::Command::delete 12 | Mail::Milter::Authentication::App::Blocker::App::Command::add 13 | Mail::Milter::Authentication::App::Blocker::App 14 | Mail::Milter::Authentication::Resolver 15 | Mail::Milter::Authentication::Net::Milter 16 | Mail::Milter::Authentication::HTDocs 17 | Mail::Milter::Authentication::Pragmas 18 | Mail::Milter::Authentication::Handler::TLS 19 | Mail::Milter::Authentication::Handler::IPRev 20 | Mail::Milter::Authentication::Handler::Blocker 21 | Mail::Milter::Authentication::Handler::DMARC 22 | Mail::Milter::Authentication::Handler::ReturnOK 23 | Mail::Milter::Authentication::Handler::DKIM 24 | Mail::Milter::Authentication::Handler::AddID 25 | Mail::Milter::Authentication::Handler::Auth 26 | Mail::Milter::Authentication::Handler::LocalIP 27 | Mail::Milter::Authentication::Handler::AbusixDataFeed 28 | Mail::Milter::Authentication::Handler::SPF 29 | Mail::Milter::Authentication::Handler::ARC 30 | Mail::Milter::Authentication::Handler::XGoogleDKIM 31 | Mail::Milter::Authentication::Handler::AlignedFrom 32 | Mail::Milter::Authentication::Handler::SenderID 33 | Mail::Milter::Authentication::Handler::TestTimeout 34 | Mail::Milter::Authentication::Handler::Sanitize 35 | Mail::Milter::Authentication::Handler::Size 36 | Mail::Milter::Authentication::Handler::PTR 37 | Mail::Milter::Authentication::Handler::BIMI 38 | Mail::Milter::Authentication::Handler::TrustedIP 39 | Mail::Milter::Authentication::Metric 40 | Mail::Milter::Authentication::Metric::Grafana 41 | Mail::Milter::Authentication::Config 42 | Mail::Milter::Authentication::Constants 43 | Mail::Milter::Authentication::Protocol::SMTP 44 | Mail::Milter::Authentication::Protocol::Milter 45 | Mail::Milter::Authentication::Tester::HandlerTester 46 | Mail::Milter::Authentication::Client 47 | Mail::Milter::Authentication::Exception 48 | Mail::Milter::Authentication::Tester 49 | Mail::Milter::Authentication::Handler 50 | Mail::Milter::Authentication 51 | }; 52 | 53 | plan tests => scalar @Modules; 54 | 55 | foreach my $Module ( @Modules ) { 56 | use_ok( $Module ) || print "Bail out!"; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /t/01-func-pipeline.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use lib 't'; 6 | use Test::More; 7 | use Test::File::Contents; 8 | use Net::DNS::Resolver::Mock; 9 | use AuthMilterTest; 10 | 11 | if ( ! -e 't/00-load.t' ) { 12 | die 'Could not find required files, are we in the correct directory?'; 13 | } 14 | 15 | chdir 't'; 16 | 17 | plan tests => 1; 18 | 19 | { 20 | #system 'rm -rf tmp'; 21 | mkdir 'tmp'; 22 | mkdir 'tmp/result'; 23 | 24 | AuthMilterTest::tools_pipeline_test(); 25 | 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /t/01-func-tools.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use lib 't'; 6 | use Test::More; 7 | use Test::File::Contents; 8 | use Net::DNS::Resolver::Mock; 9 | use AuthMilterTest; 10 | 11 | if ( ! -e 't/00-load.t' ) { 12 | die 'Could not find required files, are we in the correct directory?'; 13 | } 14 | 15 | chdir 't'; 16 | 17 | plan tests => 1; 18 | 19 | { 20 | #system 'rm -rf tmp'; 21 | mkdir 'tmp'; 22 | mkdir 'tmp/result'; 23 | 24 | AuthMilterTest::tools_test(); 25 | 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /t/02-unit-mail-milter-authentication-handler-rbl.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use lib 't'; 6 | use Test::More; 7 | 8 | use Net::IP; 9 | use AuthMilterTest; 10 | use Mail::Milter::Authentication::Handler; 11 | use Net::DNS::Resolver::Mock; 12 | 13 | if ( ! -e 't/00-load.t' ) { 14 | die 'Could not find required files, are we in the correct directory?'; 15 | } 16 | 17 | chdir 't'; 18 | 19 | open( STDERR, '>>', 'tmp/misc.err' ) || die "Cannot open errlog [$!]"; 20 | open( STDOUT, '>>', 'tmp/misc.err' ) || die "Cannot open errlog [$!]"; 21 | 22 | ## Set up a fake handler object 23 | my $prefix = 'config/normal.smtp'; 24 | $Mail::Milter::Authentication::Config::PREFIX = $prefix; 25 | $Mail::Milter::Authentication::Config::IDENT = 'test_authentication_milter_test'; 26 | my $Resolver = Net::DNS::Resolver::Mock->new(); 27 | $Resolver->zonefile_read( 'zonefile' ); 28 | $Mail::Milter::Authentication::Handler::TestResolver = $Resolver; 29 | 30 | my $Authentication = Mail::Milter::Authentication->new(); 31 | $Authentication->{'config'} = $Authentication->get_config(); 32 | my $Handler = Mail::Milter::Authentication::Handler->new( $Authentication ); 33 | 34 | is( $Handler->rbl_check_domain( 'messagingengine.com', 'domainwl.authmilter.org' ), '127.0.0.2', 'domain listed' ); 35 | is( $Handler->rbl_check_ip( Net::IP->new('66.111.4.25'), 'ipwl.authmilter.org' ), '127.0.0.2', 'ip listed' ); 36 | is( $Handler->rbl_check_ip( Net::IP->new('2404:6800:4006:80a::200e'), 'ipwl.authmilter.org' ), '127.0.0.2', 'ip6 listed' ); 37 | 38 | is( $Handler->rbl_check_domain( 'fastmail.com', 'domainwl.authmilter.org' ), 0, 'domain not listed' ); 39 | is( $Handler->rbl_check_ip( Net::IP->new('1.1.1.1'), 'ipwl.authmilter.org' ), 0, 'ip not listed' ); 40 | is( $Handler->rbl_check_ip( Net::IP->new('2405:6800:4006:80a::200e'), 'ipwl.authmilter.org' ), 0, 'ip6 not listed' ); 41 | 42 | done_testing(); 43 | -------------------------------------------------------------------------------- /t/03-func-milter.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use lib 't'; 6 | use Test::More; 7 | use Test::File::Contents; 8 | use Net::DNS::Resolver::Mock; 9 | use AuthMilterTest; 10 | 11 | if ( $ENV{SKIP_MILTER_TESTS} ) { 12 | plan( skip_all => "Tests skipped by environment" ); 13 | } 14 | 15 | if ( ! -e 't/00-load.t' ) { 16 | die 'Could not find required files, are we in the correct directory?'; 17 | } 18 | 19 | chdir 't'; 20 | 21 | plan tests => 39; 22 | 23 | { 24 | # system 'rm -rf tmp'; 25 | mkdir 'tmp'; 26 | mkdir 'tmp/result'; 27 | 28 | AuthMilterTest::run_milter_processing(); 29 | 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /t/03-func-smtp.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use lib 't'; 6 | use Test::More; 7 | use Test::File::Contents; 8 | use Net::DNS::Resolver::Mock; 9 | use AuthMilterTest; 10 | 11 | if ( $ENV{SKIP_SMTP_TESTS} ) { 12 | plan( skip_all => "Tests skipped by environment" ); 13 | } 14 | 15 | if ( ! -e 't/00-load.t' ) { 16 | die 'Could not find required files, are we in the correct directory?'; 17 | } 18 | 19 | chdir 't'; 20 | 21 | plan tests => 42; 22 | 23 | { 24 | # system 'rm -rf tmp'; 25 | mkdir 'tmp'; 26 | mkdir 'tmp/result'; 27 | 28 | AuthMilterTest::run_smtp_processing(); 29 | 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /t/04-unit-handler-aligned-from_dmarc.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use lib 't'; 6 | 7 | use Data::Dumper; 8 | 9 | use TestAlignedFromHandler; 10 | use Test::Exception; 11 | use Test::More; 12 | use JSON::XS; 13 | 14 | my $basedir = q{}; 15 | 16 | open( STDERR, '>>', $basedir . 't/tmp/misc.err' ) || die "Cannot open errlog [$!]"; 17 | #open( STDOUT, '>>', $basedir . 't/tmp/misc.err' ) || die "Cannot open errlog [$!]"; 18 | 19 | # Tester instance with access to a loaded DMARC Handler 20 | 21 | my $tester_dmarc = Mail::Milter::Authentication::Tester::HandlerTester->new({ 22 | 'prefix' => $basedir . 't/config/handler/etc', 23 | 'zonefile' => $basedir . 't/zonefile', 24 | 'handler_config' => { 25 | 'AlignedFrom' => {}, 26 | 'SPF' => { 27 | 'hide_none' => 0, 28 | }, 29 | 'DMARC' => { 30 | 'hide_none' => 0, 31 | 'detect_list_id' => 1, 32 | }, 33 | 'DKIM' => { 34 | 'hide_none' => 0, 35 | 'show_default_adsp' => 0, 36 | 'check_adsp' => 1, 37 | 'adsp_hide_none' => 0, 38 | }, 39 | }, 40 | }); 41 | 42 | subtest 'config' => sub { 43 | my $config = $tester_dmarc->{ 'authmilter' }->{ 'handler' }->{ 'AlignedFrom' }->default_config(); 44 | is_deeply( $config, {}, 'Returns correct config' ); 45 | }; 46 | 47 | subtest 'metrics' => sub { 48 | my $grafana_rows = $tester_dmarc->{ 'authmilter' }->{ 'handler' }->{ 'AlignedFrom' }->grafana_rows(); 49 | is( scalar @$grafana_rows, 1, '1 Grafana row returned' ); 50 | lives_ok( sub{ JSON::XS->new()->decode( $grafana_rows->[0] ); }, 'Metrics returns valid JSON' ); 51 | }; 52 | 53 | TestAlignedFromHandler::test_dmarc_or_not( $tester_dmarc ); 54 | TestAlignedFromHandler::test_dmarc( $tester_dmarc ); 55 | 56 | $tester_dmarc->close(); 57 | 58 | done_testing(); 59 | 60 | -------------------------------------------------------------------------------- /t/04-unit-handler-aligned-from_nodmarc.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use lib 't'; 6 | 7 | use Data::Dumper; 8 | 9 | use TestAlignedFromHandler; 10 | use Test::More; 11 | 12 | my $basedir = q{}; 13 | 14 | open( STDERR, '>>', $basedir . 't/tmp/misc.err' ) || die "Cannot open errlog [$!]"; 15 | #open( STDOUT, '>>', $basedir . 't/tmp/misc.err' ) || die "Cannot open errlog [$!]"; 16 | 17 | # Tester instance without access to a loaded DMARC Handler 18 | 19 | my $tester_no_dmarc = Mail::Milter::Authentication::Tester::HandlerTester->new({ 20 | 'prefix' => $basedir . 't/config/handler/etc', 21 | 'zonefile' => $basedir . 't/zonefile', 22 | 'handler_config' => { 23 | 'AlignedFrom' => {}, 24 | }, 25 | }); 26 | 27 | TestAlignedFromHandler::test_dmarc_or_not( $tester_no_dmarc ); 28 | TestAlignedFromHandler::test_no_dmarc( $tester_no_dmarc ); 29 | 30 | $tester_no_dmarc->close(); 31 | 32 | done_testing(); 33 | 34 | -------------------------------------------------------------------------------- /t/04-unit-handler-auth.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use lib 't'; 6 | 7 | use Data::Dumper; 8 | use Mail::Milter::Authentication::Tester::HandlerTester; 9 | use Mail::Milter::Authentication::Constants qw{ :all }; 10 | use Test::Exception; 11 | use Test::More; 12 | use JSON::XS; 13 | 14 | my $basedir = q{}; 15 | 16 | open( STDERR, '>>', $basedir . 't/tmp/misc.err' ) || die "Cannot open errlog [$!]"; 17 | #open( STDOUT, '>>', $basedir . 't/tmp/misc.err' ) || die "Cannot open errlog [$!]"; 18 | 19 | my $tester = Mail::Milter::Authentication::Tester::HandlerTester->new({ 20 | 'protocol' => 'milter', 21 | 'prefix' => $basedir . 't/config/handler/etc', 22 | 'zonedata' => '', 23 | 'handler_config' => { 24 | 'Auth' => {}, 25 | }, 26 | }); 27 | 28 | subtest 'config' => sub { 29 | my $config = $tester->{ 'authmilter' }->{ 'handler' }->{ 'Auth' }->default_config(); 30 | is_deeply( $config, {}, 'Returns correct config' ); 31 | }; 32 | 33 | subtest 'metrics' => sub { 34 | my $grafana_rows = $tester->{ 'authmilter' }->{ 'handler' }->{ 'Auth' }->grafana_rows(); 35 | is( scalar @$grafana_rows, 1, '1 Grafana row returned' ); 36 | lives_ok( sub{ JSON::XS->new()->decode( $grafana_rows->[0] ); }, 'Metrics returns valid JSON' ); 37 | }; 38 | 39 | { 40 | 41 | $tester->run({ 42 | 'connect_ip' => '1.2.3.4', 43 | 'connect_name' => 'mx.example.com', 44 | 'helo' => 'mx.example.com', 45 | 'mailfrom' => 'test@example.net', 46 | 'rcptto' => [ 'test@example.net' ], 47 | 'body' => 'From: test@example.net 48 | To: test@example.net 49 | Subject: This is a test 50 | 51 | Testing', 52 | }); 53 | 54 | my $header = $tester->get_authresults_header()->search({ 'key' => 'auth' }); 55 | is( scalar @{ $header->children() }, 0, 'No Entries' ); 56 | my $result = eval{ $header->children()->[0]->value(); } // q{}; 57 | is( $result, q{}, 'Unauthenticated' ); 58 | } 59 | 60 | { 61 | $tester->switch( '_new' ); 62 | $tester->connect( 'mx.example.com', '1.2.3.4' ); 63 | $tester->helo( 'mx.example.com' ); 64 | $tester->handler()->set_symbol('C', '{auth_authen}','testAuthUser'); 65 | $tester->mailfrom( 'test@example.net' ); 66 | $tester->rcptto( 'test@example.net' ); 67 | $tester->header( 'From', 'test@example.net' ); 68 | $tester->header( 'To', 'test@example.net' ); 69 | $tester->end_of_headers(); 70 | $tester->body( 'This is a test' ); 71 | $tester->end_of_message(); 72 | 73 | my $header = $tester->get_authresults_header()->search({ 'key' => 'auth' }); 74 | is( scalar @{ $header->children() }, 1, '1 Entry' ); 75 | my $result = eval{ $header->children()->[0]->value(); } // q{}; 76 | is( $result, 'pass', 'Authenticated' ); 77 | 78 | } 79 | 80 | done_testing(); 81 | 82 | -------------------------------------------------------------------------------- /t/bimi.zonefile: -------------------------------------------------------------------------------- 1 | _dmarc.example.com 10 IN TXT ( "v=DMARC1; p=reject; pct=100;" ) 2 | default._bimi.example.com 10 IN TXT ( "v=bimi1; l=https://bimi.example.com/test.svg" ) 3 | dkim1._domainkey.example.com 10 IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDErv0qLGKJ933gdhx2MUBqb/XhTloMjJhH0kdQsxkVuhRFzINgDzMGOq83xEwNEk4jC/J+E49fNQ+TSVymq+XGvrkeW7/7llEOTFosY6OGlwdeUZyyUCEM6SIYIBeHuIQn4Ohwhq7P0nZFfXNAG7Wrlxx1O+E881wTRhFOBxAjdQIDAQAB" ) 4 | dkim1._domainkey.one.example.com 10 IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDErv0qLGKJ933gdhx2MUBqb/XhTloMjJhH0kdQsxkVuhRFzINgDzMGOq83xEwNEk4jC/J+E49fNQ+TSVymq+XGvrkeW7/7llEOTFosY6OGlwdeUZyyUCEM6SIYIBeHuIQn4Ohwhq7P0nZFfXNAG7Wrlxx1O+E881wTRhFOBxAjdQIDAQAB" ) 5 | example.com 10 IN A 1.2.3.4 6 | example.com 10 IN TXT ( "v=spf1 ip4:1.2.3.4 -all" ) 7 | testsel._bimi.example.com 10 IN TXT ( "v=bimi1; l=https://bimi.example.com/test.svg" ) 8 | testselone._bimi.one.example.com 10 IN TXT ( "v=bimi1; l=https://bimi.example.com/test.svg" ) 9 | 10 | dkim1._domainkey.example.org 10 IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDErv0qLGKJ933gdhx2MUBqb/XhTloMjJhH0kdQsxkVuhRFzINgDzMGOq83xEwNEk4jC/J+E49fNQ+TSVymq+XGvrkeW7/7llEOTFosY6OGlwdeUZyyUCEM6SIYIBeHuIQn4Ohwhq7P0nZFfXNAG7Wrlxx1O+E881wTRhFOBxAjdQIDAQAB" ) 11 | 12 | _dmarc.nobimi.com 10 IN TXT ( "v=DMARC1; p=reject; pct=100;" ) 13 | dkim1._domainkey.nobimi.com 10 IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDErv0qLGKJ933gdhx2MUBqb/XhTloMjJhH0kdQsxkVuhRFzINgDzMGOq83xEwNEk4jC/J+E49fNQ+TSVymq+XGvrkeW7/7llEOTFosY6OGlwdeUZyyUCEM6SIYIBeHuIQn4Ohwhq7P0nZFfXNAG7Wrlxx1O+E881wTRhFOBxAjdQIDAQAB" ) 14 | nobimi.com 10 IN A 1.2.3.4 15 | nobimi.com 10 IN TXT ( "v=spf1 ip4:1.2.3.5 -all" ) 16 | 17 | dkim1._domainkey.arcsealed.com 10 IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDErv0qLGKJ933gdhx2MUBqb/XhTloMjJhH0kdQsxkVuhRFzINgDzMGOq83xEwNEk4jC/J+E49fNQ+TSVymq+XGvrkeW7/7llEOTFosY6OGlwdeUZyyUCEM6SIYIBeHuIQn4Ohwhq7P0nZFfXNAG7Wrlxx1O+E881wTRhFOBxAjdQIDAQAB" ) 18 | 19 | -------------------------------------------------------------------------------- /t/conf/blocker.toml: -------------------------------------------------------------------------------- 1 | [connect_test] 2 | callback = "connect" 3 | value = "192\.168\.0\.1" 4 | with = "451 4.7.28 flood policy violation (HOTtest)" 5 | percent = 100 6 | 7 | [connect_test_sampled] 8 | callback = "connect" 9 | value = "192\.168\.0\.2" 10 | with = "451 4.7.28 flood policy violation (HOTtest)" 11 | percent = 0 12 | 13 | [helo_test] 14 | callback = "helo" 15 | value = "helo.example.bad" 16 | with = "451 4.7.28 flood policy violation (HOTtest)" 17 | percent = 100 18 | 19 | [from_test] 20 | callback = "envfrom" 21 | value = "bad@example\.com" 22 | with = "451 4.7.28 flood policy violation (HOTtest)" 23 | percent = 100 24 | 25 | [to_test] 26 | callback = "envrcpt" 27 | value = "bad@example\.net" 28 | with = "451 4.7.28 flood policy violation (HOTtest)" 29 | percent = 100 30 | 31 | [header_test] 32 | callback = "header" 33 | value = "^BadHeader:" 34 | with = "451 4.7.28 flood policy violation (HOTtest)" 35 | percent = 100 36 | 37 | -------------------------------------------------------------------------------- /t/conf/blocker2.toml: -------------------------------------------------------------------------------- 1 | [connect_test2] 2 | callback = "connect" 3 | value = "192\.168\.0\.2" 4 | with = "500 5.0.0 Blocked" 5 | percent = 100 6 | 7 | -------------------------------------------------------------------------------- /t/conf/blocker3.toml: -------------------------------------------------------------------------------- 1 | [connect_test_null] 2 | callback = "connect" 3 | value = "192\.168\.0\.1" 4 | with = "451 4.7.28 flood policy violation (HOTtest)" 5 | percent = 100 6 | 7 | [connect_test_past] 8 | callback = "connect" 9 | value = "192\.168\.0\.2" 10 | with = "451 4.7.28 flood policy violation (HOTtest)" 11 | percent = 100 12 | until = 10 13 | 14 | [connect_test_future] 15 | callback = "connect" 16 | value = "192\.168\.0\.3" 17 | with = "451 4.7.28 flood policy violation (HOTtest)" 18 | percent = 100 19 | until = 3000000000 20 | 21 | [connect_test_zero] 22 | callback = "connect" 23 | value = "192\.168\.0\.4" 24 | with = "451 4.7.28 flood policy violation (HOTtest)" 25 | percent = 100 26 | until = 0 27 | 28 | -------------------------------------------------------------------------------- /t/config/dmarc_reject.smtp/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter smtp 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/smtp.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "protocol" : "smtp", 22 | "smtp" : { 23 | "sock_type" : "unix", 24 | "sock_path" : "tmp/authentication_milter_smtp_out.sock", 25 | "pipeline_limit" : "4", 26 | }, 27 | 28 | "listen_backlog" : 1, 29 | "min_children" : 1, 30 | "max_children" : 2, 31 | "min_spare_children" : 1, 32 | "max_spare_children" : 1, 33 | "max_requests_per_child" : 1000, 34 | 35 | "dns_resolvers" : [ "127.0.0.1" ], 36 | 37 | "handlers" : { 38 | "SPF" : { 39 | "hide_none" : 0 40 | }, 41 | "DMARC" : { 42 | "hard_reject" : 1, 43 | "hide_none" : 0, 44 | "whitelisted" : [ "99.0.0.0/8" ], 45 | "detect_list_id" : 1 46 | }, 47 | "DKIM" : { 48 | "hide_none" : 0, 49 | "show_default_adsp" : 0, 50 | "check_adsp" : 1, 51 | "adsp_hide_none" : 0 52 | }, 53 | "PTR" : {}, 54 | "SenderID" : { 55 | "hide_none" : 1 56 | }, 57 | "IPRev" : {}, 58 | "Auth" : {}, 59 | "LocalIP" : {}, 60 | "TrustedIP" : { 61 | "trusted_ip_list" : [ 62 | "123.123.12.3" 63 | ] 64 | }, 65 | "TLS" : {}, 66 | "!AddID" : {}, 67 | "!ReturnOK" : {}, 68 | "Sanitize" : { 69 | "hosts_to_remove" : [ 70 | "test.module" 71 | ], 72 | "remove_headers" : "yes" 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /t/config/dmarc_reject.smtp/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/dmarc_reject/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/milter.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "listen_backlog" : 1, 22 | "min_children" : 1, 23 | "max_children" : 2, 24 | "min_spare_children" : 1, 25 | "max_spare_children" : 1, 26 | "max_requests_per_child" : 1000, 27 | 28 | 29 | "handlers" : { 30 | "SPF" : { 31 | "hide_none" : 0 32 | }, 33 | "DMARC" : { 34 | "hard_reject" : 1, 35 | "hide_none" : 0, 36 | "whitelisted" : [ "99.0.0.0/8" ], 37 | "detect_list_id" : 1 38 | }, 39 | "DKIM" : { 40 | "hide_none" : 0, 41 | "show_default_adsp" : 0, 42 | "check_adsp" : 1, 43 | "adsp_hide_none" : 0 44 | }, 45 | "PTR" : {}, 46 | "SenderID" : { 47 | "hide_none" : 1 48 | }, 49 | "IPRev" : {}, 50 | "Auth" : {}, 51 | "LocalIP" : {}, 52 | "TrustedIP" : { 53 | "trusted_ip_list" : [ 54 | "123.123.12.3" 55 | ] 56 | }, 57 | "!AddID" : {}, 58 | "!ReturnOK" : {}, 59 | "Sanitize" : { 60 | "hosts_to_remove" : [ 61 | "test.module" 62 | ], 63 | "remove_headers" : "yes" 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /t/config/dmarc_reject/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/dmarc_reject_wl.smtp/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter smtp 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/smtp.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "protocol" : "smtp", 22 | "smtp" : { 23 | "sock_type" : "unix", 24 | "sock_path" : "tmp/authentication_milter_smtp_out.sock", 25 | "pipeline_limit" : "4" 26 | }, 27 | 28 | "listen_backlog" : 1, 29 | "min_children" : 1, 30 | "max_children" : 2, 31 | "min_spare_children" : 1, 32 | "max_spare_children" : 1, 33 | "max_requests_per_child" : 1000, 34 | 35 | "dns_resolvers" : [ "127.0.0.1" ], 36 | 37 | "handlers" : { 38 | "SPF" : { 39 | "hide_none" : 0 40 | }, 41 | "DMARC" : { 42 | "hard_reject" : 1, 43 | "hide_none" : 0, 44 | "whitelisted" : [ "99.0.0.0/8", "dkim:marcbradshaw.net" ], 45 | "detect_list_id" : 1 46 | }, 47 | "DKIM" : { 48 | "hide_none" : 0, 49 | "show_default_adsp" : 0, 50 | "check_adsp" : 1, 51 | "adsp_hide_none" : 0, 52 | "no_strict" : 1 53 | 54 | }, 55 | "PTR" : {}, 56 | "SenderID" : { 57 | "hide_none" : 1 58 | }, 59 | "IPRev" : {}, 60 | "Auth" : {}, 61 | "LocalIP" : {}, 62 | "TrustedIP" : { 63 | "trusted_ip_list" : [ 64 | "123.123.12.3" 65 | ] 66 | }, 67 | "TLS" : {}, 68 | "!AddID" : {}, 69 | "!ReturnOK" : {}, 70 | "Sanitize" : { 71 | "hosts_to_remove" : [ 72 | "test.module" 73 | ], 74 | "remove_headers" : "yes" 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /t/config/dmarc_reject_wl.smtp/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/dmarc_reject_wl/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/milter.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "listen_backlog" : 1, 22 | "min_children" : 1, 23 | "max_children" : 2, 24 | "min_spare_children" : 1, 25 | "max_spare_children" : 1, 26 | "max_requests_per_child" : 1000, 27 | 28 | 29 | "handlers" : { 30 | "SPF" : { 31 | "hide_none" : 0 32 | }, 33 | "DMARC" : { 34 | "hard_reject" : 1, 35 | "hide_none" : 0, 36 | "whitelisted" : [ "99.0.0.0/8", "dkim:marcbradshaw.net" ], 37 | "detect_list_id" : 1 38 | }, 39 | "DKIM" : { 40 | "hide_none" : 0, 41 | "show_default_adsp" : 0, 42 | "check_adsp" : 1, 43 | "adsp_hide_none" : 0, 44 | "no_strict" : 1 45 | }, 46 | "PTR" : {}, 47 | "SenderID" : { 48 | "hide_none" : 1 49 | }, 50 | "IPRev" : {}, 51 | "Auth" : {}, 52 | "LocalIP" : {}, 53 | "TrustedIP" : { 54 | "trusted_ip_list" : [ 55 | "123.123.12.3" 56 | ] 57 | }, 58 | "!AddID" : {}, 59 | "!ReturnOK" : {}, 60 | "Sanitize" : { 61 | "hosts_to_remove" : [ 62 | "test.module" 63 | ], 64 | "remove_headers" : "yes" 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /t/config/dmarc_reject_wl/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/dryrun.smtp/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter smtp dryrun 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 1, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/smtp.dryrun.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "protocol" : "smtp", 22 | "smtp" : { 23 | "sock_type" : "unix", 24 | "sock_path" : "tmp/authentication_milter_smtp_out.sock", 25 | }, 26 | 27 | "listen_backlog" : 1, 28 | "min_children" : 1, 29 | "max_children" : 2, 30 | "min_spare_children" : 1, 31 | "max_spare_children" : 1, 32 | "max_requests_per_child" : 1000, 33 | 34 | "handlers" : { 35 | "SPF" : { 36 | "hide_none" : 0 37 | }, 38 | "DMARC" : { 39 | "hide_none" : 0, 40 | "detect_list_id" : 1 41 | }, 42 | "DKIM" : { 43 | "hide_none" : 0, 44 | "show_default_adsp" : 0, 45 | "check_adsp" : 1, 46 | "adsp_hide_none" : 0 47 | }, 48 | "PTR" : {}, 49 | "SenderID" : { 50 | "hide_none" : 1 51 | }, 52 | "IPRev" : {}, 53 | "Auth" : {}, 54 | "LocalIP" : {}, 55 | "TrustedIP" : { 56 | "trusted_ip_list" : [ 57 | "123.123.12.3" 58 | ] 59 | }, 60 | "TLS" : {}, 61 | "!AddID" : {}, 62 | "!ReturnOK" : {}, 63 | "Sanitize" : { 64 | "hosts_to_remove" : [ 65 | ], 66 | "remove_headers" : "yes" 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /t/config/dryrun.smtp/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/dryrun/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter dryrun 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 1, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/milter.dryrun.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "listen_backlog" : 1, 22 | "min_children" : 1, 23 | "max_children" : 2, 24 | "min_spare_children" : 1, 25 | "max_spare_children" : 1, 26 | "max_requests_per_child" : 1000, 27 | 28 | 29 | "handlers" : { 30 | "SPF" : { 31 | "hide_none" : 0 32 | }, 33 | "DMARC" : { 34 | "hide_none" : 0, 35 | "detect_list_id" : 1 36 | }, 37 | "DKIM" : { 38 | "hide_none" : 0, 39 | "show_default_adsp" : 0, 40 | "check_adsp" : 1, 41 | "adsp_hide_none" : 0 42 | }, 43 | "PTR" : {}, 44 | "SenderID" : { 45 | "hide_none" : 1 46 | }, 47 | "IPRev" : {}, 48 | "Auth" : {}, 49 | "LocalIP" : {}, 50 | "TrustedIP" : { 51 | "trusted_ip_list" : [ 52 | "123.123.12.3" 53 | ] 54 | }, 55 | "!AddID" : {}, 56 | "!ReturnOK" : {}, 57 | "Sanitize" : { 58 | "hosts_to_remove" : [ 59 | ], 60 | "remove_headers" : "yes" 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /t/config/dryrun/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/handler/etc/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/hide_none.smtp/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter hide_none smtp 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/smtp.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "protocol" : "smtp", 22 | "smtp" : { 23 | "sock_type" : "unix", 24 | "sock_path" : "tmp/authentication_milter_smtp_out.sock", 25 | "pipeline_limit" : "4", 26 | }, 27 | 28 | "ip_map" : { 29 | "4.3.2.1" : { "ip" : "74.125.82.171" , "helo" : "mail-we0-f171.google.com" }, 30 | "5.4.3.0/24" : { "ip" : "74.125.82.171", "helo" : "mail-we0-f171.google.com" } 31 | }, 32 | 33 | "listen_backlog" : 1, 34 | "min_children" : 1, 35 | "max_children" : 2, 36 | "min_spare_children" : 1, 37 | "max_spare_children" : 1, 38 | "max_requests_per_child" : 1000, 39 | 40 | "authserv_id" : "mx.example.net", 41 | "hide_none" : 1, 42 | 43 | "handlers" : { 44 | "SPF" : { 45 | "hide_none" : 1 46 | }, 47 | "DMARC" : { 48 | "hide_none" : 1, 49 | "detect_list_id" : 1 50 | }, 51 | "XGoogleDKIM" : { 52 | "hide_none" : 1 53 | }, 54 | "DKIM" : { 55 | "hide_none" : 1, 56 | "show_default_adsp" : 0, 57 | "check_adsp" : 1, 58 | "adsp_hide_none" : 1 59 | }, 60 | "!PTR" : {}, 61 | "SenderID" : { 62 | "hide_none" : 1 63 | }, 64 | "!IPRev" : {}, 65 | "!Auth" : {}, 66 | "!LocalIP" : {}, 67 | "!TrustedIP" : { 68 | "trusted_ip_list" : [ 69 | "123.123.12.3" 70 | ] 71 | }, 72 | "!AddID" : {}, 73 | "!ReturnOK" : {}, 74 | "Sanitize" : { 75 | "hosts_to_remove" : [ 76 | "module" 77 | ], 78 | "remove_headers" : "yes" 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /t/config/hide_none.smtp/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/hide_none/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter hide_none 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/milter.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "ip_map" : { 22 | "4.3.2.1" : { "ip" : "74.125.82.171" , "helo" : "mail-we0-f171.google.com" }, 23 | "5.4.3.0/24" : { "ip" : "74.125.82.171", "helo" : "mail-we0-f171.google.com" } 24 | }, 25 | 26 | "listen_backlog" : 1, 27 | "min_children" : 1, 28 | "max_children" : 2, 29 | "min_spare_children" : 1, 30 | "max_spare_children" : 1, 31 | "max_requests_per_child" : 1000, 32 | 33 | "authserv_id" : "mx.example.net", 34 | "hide_none" : 1, 35 | 36 | "handlers" : { 37 | "SPF" : { 38 | "hide_none" : 1 39 | }, 40 | "DMARC" : { 41 | "hide_none" : 1, 42 | "detect_list_id" : 1 43 | }, 44 | "XGoogleDKIM" : { 45 | "hide_none" : 1 46 | }, 47 | "DKIM" : { 48 | "hide_none" : 1, 49 | "show_default_adsp" : 0, 50 | "check_adsp" : 1, 51 | "adsp_hide_none" : 1 52 | }, 53 | "!PTR" : {}, 54 | "SenderID" : { 55 | "hide_none" : 1 56 | }, 57 | "!IPRev" : {}, 58 | "!Auth" : {}, 59 | "!LocalIP" : {}, 60 | "!TrustedIP" : { 61 | "trusted_ip_list" : [ 62 | "123.123.12.3" 63 | ] 64 | }, 65 | "!AddID" : {}, 66 | "!ReturnOK" : {}, 67 | "Sanitize" : { 68 | "hosts_to_remove" : [ 69 | "example.com" 70 | ], 71 | "remove_headers" : "yes" 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /t/config/hide_none/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/normal.smtp/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter smtp 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/smtp.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "protocol" : "smtp", 22 | "smtp" : { 23 | "sock_type" : "unix", 24 | "sock_path" : "tmp/authentication_milter_smtp_out.sock", 25 | "pipeline_limit" : "4", 26 | }, 27 | 28 | "ip_map" : { 29 | "4.3.2.1" : { "ip" : "74.125.82.171" , "helo" : "mail-we0-f171.google.com" }, 30 | "5.4.3.0/24" : { "ip" : "74.125.82.171", "helo" : "mail-we0-f171.google.com" } 31 | }, 32 | 33 | "listen_backlog" : 1, 34 | "min_children" : 1, 35 | "max_children" : 2, 36 | "min_spare_children" : 1, 37 | "max_spare_children" : 1, 38 | "max_requests_per_child" : 1000, 39 | 40 | "dns_resolvers" : [ "127.0.0.1" ], 41 | 42 | "handlers" : { 43 | "SPF" : { 44 | "hide_none" : 0 45 | }, 46 | "DMARC" : { 47 | "hide_none" : 0, 48 | "detect_list_id" : 1 49 | }, 50 | "XGoogleDKIM" : { 51 | "hide_none" : 0 52 | }, 53 | "DKIM" : { 54 | "hide_none" : 0, 55 | "show_default_adsp" : 0, 56 | "check_adsp" : 1, 57 | "adsp_hide_none" : 0 58 | }, 59 | "PTR" : {}, 60 | "SenderID" : { 61 | "hide_none" : 1 62 | }, 63 | "IPRev" : {}, 64 | "Auth" : {}, 65 | "LocalIP" : {}, 66 | "TrustedIP" : { 67 | "trusted_ip_list" : [ 68 | "123.123.12.3" 69 | ] 70 | }, 71 | "TLS" : {}, 72 | "!AddID" : {}, 73 | "!ReturnOK" : {}, 74 | "Sanitize" : { 75 | "hosts_to_remove" : [ 76 | "module" 77 | ], 78 | "remove_headers" : "yes" 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /t/config/normal.smtp/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/normal/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 0, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/milter.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 55, 11 | "command_timeout" : 55, 12 | "content_timeout" : 595, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "ip_map" : { 22 | "4.3.2.1" : { "ip" : "74.125.82.171" , "helo" : "mail-we0-f171.google.com" }, 23 | "5.4.3.0/24" : { "ip" : "74.125.82.171", "helo" : "mail-we0-f171.google.com" } 24 | }, 25 | 26 | "listen_backlog" : 1, 27 | "min_children" : 1, 28 | "max_children" : 2, 29 | "min_spare_children" : 1, 30 | "max_spare_children" : 1, 31 | "max_requests_per_child" : 1000, 32 | 33 | "handlers" : { 34 | "SPF" : { 35 | "hide_none" : 0 36 | }, 37 | "DMARC" : { 38 | "hide_none" : 0, 39 | "detect_list_id" : 1 40 | }, 41 | "XGoogleDKIM" : { 42 | "hide_none" : 0 43 | }, 44 | "DKIM" : { 45 | "hide_none" : 0, 46 | "show_default_adsp" : 0, 47 | "check_adsp" : 1, 48 | "adsp_hide_none" : 0 49 | }, 50 | "PTR" : {}, 51 | "SenderID" : { 52 | "hide_none" : 1 53 | }, 54 | "IPRev" : {}, 55 | "Auth" : {}, 56 | "LocalIP" : {}, 57 | "TrustedIP" : { 58 | "trusted_ip_list" : [ 59 | "123.123.12.3" 60 | ] 61 | }, 62 | "!AddID" : {}, 63 | "!ReturnOK" : {}, 64 | "Sanitize" : { 65 | "hosts_to_remove" : [ 66 | "example.com" 67 | ], 68 | "remove_headers" : "yes" 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /t/config/normal/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/config/timeout/authentication_milter.json: -------------------------------------------------------------------------------- 1 | # Test configuration for auth milter dryrun 2 | { 3 | 4 | "debug" : 0, 5 | "dryrun" : 1, 6 | "logtoerr" : 1, 7 | "error_log" : "tmp/milter.dryrun.err", 8 | "connection" : "unix:tmp/authentication_milter_test.sock", 9 | "umask" : "0000", 10 | "connect_timeout" : 1, 11 | "command_timeout" : 1, 12 | "content_timeout" : 1, 13 | "tempfail_on_error" : 1, 14 | "tempfail_on_error_authenticated" : 1, 15 | "tempfail_on_error_local" : 1, 16 | "tempfail_on_error_trusted" : 1, 17 | 18 | "metric_connection" : "unix:tmp/authentication_milter_test_metrics.sock", 19 | "metric_umask" : "0000", 20 | 21 | "listen_backlog" : 1, 22 | "min_children" : 1, 23 | "max_children" : 2, 24 | "min_spare_children" : 1, 25 | "max_spare_children" : 1, 26 | "max_requests_per_child" : 1000, 27 | 28 | "handlers" : { 29 | "TestTimeout" : {} 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /t/config/timeout/mail-dmarc.ini: -------------------------------------------------------------------------------- 1 | ; This is YOU. DMARC reports include information about the reports. Enter it here. 2 | [organization] 3 | domain = test.example.com 4 | org_name = Module Test Example 5 | email = test@example.com 6 | extra_contact_info = http://example.com 7 | 8 | ; aggregate DMARC reports need to be stored somewhere. Any database 9 | ; with a DBI module (MySQL, SQLite, DBD, etc.) should work. 10 | ; SQLite and MySQL are tested. 11 | ; Default is sqlite. 12 | [report_store] 13 | backend = SQL 14 | dsn = dbi:SQLite:dbname=:memory: 15 | user = 16 | pass = 17 | 18 | ; backend can be perl or libopendmarc 19 | [dmarc] 20 | backend = perl 21 | 22 | [dns] 23 | timeout = 5 24 | public_suffix_list = 25 | 26 | [smtp] 27 | ; hostname is the external FQDN of this MTA 28 | hostname = 29 | cc = 30 | 31 | ; list IP addresses to whitelist (bypass DMARC reject/quarantine) 32 | ; see sample whitelist in share/dmarc_whitelist 33 | whitelist = /path/to/etc/dmarc_whitelist 34 | 35 | ; By default, we attempt to email directly to the report recipient. 36 | ; Set these to relay via a SMTP smart host. 37 | smarthost = 38 | smartuser = 39 | smartpass = 40 | 41 | [imap] 42 | server = mail.example.com 43 | user = 44 | pass = 45 | ; the imap folder where new dmarc messages will be found 46 | folder = dmarc 47 | ; the folders to store processed reports (a=aggregate, f=forensic) 48 | f_done = dmarc.forensic 49 | a_done = dmarc.aggregate 50 | 51 | [http] 52 | port = 8080 53 | 54 | [https] 55 | port = 8443 56 | ssl_crt = 57 | ssl_key = 58 | 59 | -------------------------------------------------------------------------------- /t/data/FM_BIMI.svg: -------------------------------------------------------------------------------- 1 | FM-Icon-RGB 2 | -------------------------------------------------------------------------------- /t/data/example/dmarc_multi.eml: -------------------------------------------------------------------------------- 1 | X-Disposition-Quarantine: Quarantined due to DMARC policy 2 | Authentication-Results: test.module; 3 | dkim=none (no signatures found); 4 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=quarantine policy.evaluated-disposition=reject policy.override-reason=local_policy (p=reject,d=quarantine,d.eval=reject,override=local_policy) policy.policy-from=p header.from=goestheweasel.com; 5 | dmarc=fail policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 6 | dmarc=none policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=example.com; 7 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 8 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 9 | x-google-dkim=none (no signatures found); 10 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 11 | Received-SPF: fail 12 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 13 | receiver=test.module; 14 | identity=mailfrom; 15 | envelope-from="test@goestheweasel.com"; 16 | helo=bad.name.google.com; 17 | client-ip=123.123.123.123 18 | From: test@goestheweasel.com 19 | From : test@marcbradshaw.net, test@example.com 20 | To: test@example.com 21 | Subject: This is a test 22 | 23 | This should have multiple dmarc entries 24 | -------------------------------------------------------------------------------- /t/data/example/dmarc_multi_2.eml: -------------------------------------------------------------------------------- 1 | X-Disposition-Quarantine: Quarantined due to DMARC policy 2 | Authentication-Results: test.module; 3 | dkim=none (no signatures found); 4 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=quarantine policy.evaluated-disposition=reject policy.override-reason=local_policy (p=reject,d=quarantine,d.eval=reject,override=local_policy) policy.policy-from=p header.from=goestheweasel.com; 5 | dmarc=fail policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 6 | dmarc=none policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=example.com; 7 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 8 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 9 | x-google-dkim=none (no signatures found); 10 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 11 | Received-SPF: fail 12 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 13 | receiver=test.module; 14 | identity=mailfrom; 15 | envelope-from="test@goestheweasel.com"; 16 | helo=bad.name.google.com; 17 | client-ip=123.123.123.123 18 | From: test@goestheweasel.com 19 | From : test@marcbradshaw.net, test@example.com 20 | To: test@example.com 21 | Subject: This is a test 22 | 23 | This should have multiple dmarc entries 24 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject.eml: -------------------------------------------------------------------------------- 1 | X-Disposition-Quarantine: Quarantined due to DMARC policy 2 | Authentication-Results: test.module; 3 | dkim=none (no signatures found); 4 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=quarantine policy.evaluated-disposition=reject policy.override-reason=local_policy (p=reject,d=quarantine,d.eval=reject,override=local_policy) policy.policy-from=p header.from=goestheweasel.com; 5 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 6 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 7 | x-google-dkim=none (no signatures found); 8 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 9 | Received-SPF: fail 10 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 11 | receiver=test.module; 12 | identity=mailfrom; 13 | envelope-from="test@goestheweasel.com"; 14 | helo=bad.name.google.com; 15 | client-ip=123.123.123.123 16 | From: test@goestheweasel.com 17 | To: test@example.com 18 | Subject: This is a test 19 | 20 | This should be a DMARC fail with a reject policy. 21 | 22 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=bad.name.google.com 3 | XFORWARD ADDR=123.123.123.123 4 | XFORWARD NAME=bad.name.google.com 5 | MAIL FROM:test@goestheweasel.com 6 | RCPT TO:marc@fastmail.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | X-Disposition-Quarantine: Quarantined due to DMARC policy 13 | Authentication-Results: server.example.com; 14 | dkim=none (no signatures found); 15 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=quarantine policy.evaluated-disposition=reject policy.override-reason=local_policy (p=reject,d=quarantine,d.eval=reject,override=local_policy) policy.policy-from=p header.from=goestheweasel.com; 16 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 17 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 18 | x-google-dkim=none (no signatures found); 19 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 20 | Received-SPF: fail 21 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 22 | receiver=server.example.com; 23 | identity=mailfrom; 24 | envelope-from="test@goestheweasel.com"; 25 | helo=bad.name.google.com; 26 | client-ip=123.123.123.123 27 | From: test@goestheweasel.com 28 | To: test@example.com 29 | Subject: This is a test 30 | 31 | This should be a DMARC fail with a reject policy. 32 | 33 | 34 | . 35 | QUIT 36 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject_case.eml: -------------------------------------------------------------------------------- 1 | X-Disposition-Quarantine: Quarantined due to DMARC policy 2 | Authentication-Results: test.module; 3 | dkim=none (no signatures found); 4 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=quarantine policy.evaluated-disposition=reject policy.override-reason=local_policy (p=reject,d=quarantine,d.eval=reject,override=local_policy) policy.policy-from=p header.from=goestheweasel.com; 5 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 6 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 7 | x-google-dkim=none (no signatures found); 8 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 9 | Received-SPF: fail 10 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 11 | receiver=test.module; 12 | identity=mailfrom; 13 | envelope-from="test@goestheweasel.com"; 14 | helo=bad.name.google.com; 15 | client-ip=123.123.123.123 16 | FROM: test@goestheweasel.com 17 | To: test@example.com 18 | Subject: This is a test 19 | 20 | This should be a DMARC fail with a reject policy. 21 | 22 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject_case.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=bad.name.google.com 3 | XFORWARD ADDR=123.123.123.123 4 | XFORWARD NAME=bad.name.google.com 5 | MAIL FROM:test@goestheweasel.com 6 | RCPT TO:marc@fastmail.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | X-Disposition-Quarantine: Quarantined due to DMARC policy 13 | Authentication-Results: server.example.com; 14 | dkim=none (no signatures found); 15 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=quarantine policy.evaluated-disposition=reject policy.override-reason=local_policy (p=reject,d=quarantine,d.eval=reject,override=local_policy) policy.policy-from=p header.from=goestheweasel.com; 16 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 17 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 18 | x-google-dkim=none (no signatures found); 19 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 20 | Received-SPF: fail 21 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 22 | receiver=server.example.com; 23 | identity=mailfrom; 24 | envelope-from="test@goestheweasel.com"; 25 | helo=bad.name.google.com; 26 | client-ip=123.123.123.123 27 | FROM: test@goestheweasel.com 28 | To: test@example.com 29 | Subject: This is a test 30 | 31 | This should be a DMARC fail with a reject policy. 32 | 33 | 34 | . 35 | QUIT 36 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject_hard.eml: -------------------------------------------------------------------------------- 1 | Message rejected with code : 550 5.7.0 DMARC policy violation -------------------------------------------------------------------------------- /t/data/example/dmarc_reject_hard_whitelisted.eml: -------------------------------------------------------------------------------- 1 | Authentication-Results: test.module; 2 | dkim=none (no signatures found); 3 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=none policy.evaluated-disposition=reject policy.override-reason=trusted_forwarder (p=reject,d=none,d.eval=reject,override=trusted_forwarder) policy.policy-from=p header.from=goestheweasel.com; 4 | iprev=fail smtp.remote-ip=99.123.123.123 (NOT FOUND); 5 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 6 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 7 | Received-SPF: fail 8 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 9 | receiver=test.module; 10 | identity=mailfrom; 11 | envelope-from="test@goestheweasel.com"; 12 | helo=bad.name.google.com; 13 | client-ip=99.123.123.123 14 | From: test@goestheweasel.com 15 | To: test@example.com 16 | Subject: This is a test 17 | 18 | This should be a DMARC fail with a reject policy. 19 | 20 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject_hard_whitelisted.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=bad.name.google.com 3 | XFORWARD ADDR=99.123.123.123 4 | XFORWARD NAME=bad.name.google.com 5 | MAIL FROM:test@goestheweasel.com 6 | RCPT TO:marc@fastmail.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Authentication-Results: server.example.com; 13 | dkim=none (no signatures found); 14 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=none policy.evaluated-disposition=reject policy.override-reason=trusted_forwarder (p=reject,d=none,d.eval=reject,override=trusted_forwarder) policy.policy-from=p header.from=goestheweasel.com; 15 | iprev=fail smtp.remote-ip=99.123.123.123 (NOT FOUND); 16 | spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; 17 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 18 | Received-SPF: fail 19 | (goestheweasel.com: Sender is not authorized by default to use 'test@goestheweasel.com' in 'mfrom' identity (mechanism '-all' matched)) 20 | receiver=server.example.com; 21 | identity=mailfrom; 22 | envelope-from="test@goestheweasel.com"; 23 | helo=bad.name.google.com; 24 | client-ip=99.123.123.123 25 | From: test@goestheweasel.com 26 | To: test@example.com 27 | Subject: This is a test 28 | 29 | This should be a DMARC fail with a reject policy. 30 | 31 | 32 | . 33 | QUIT 34 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject_wl.eml: -------------------------------------------------------------------------------- 1 | Authentication-Results: test.module; 2 | dkim-adsp=unknown (ADSP policy from goestheweasel.com); 3 | dkim=pass (2048-bit rsa key sha1) header.d=marcbradshaw.net header.i=@marcbradshaw.net header.b=S/mtomBF header.a=rsa-sha1 header.s=tfe2; 4 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=none policy.evaluated-disposition=reject policy.override-reason=trusted_forwarder (p=reject,d=none,d.eval=reject,override=trusted_forwarder) policy.policy-from=p header.from=goestheweasel.com; 5 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 6 | spf=softfail smtp.mailfrom=marc@marcbradshaw.net smtp.helo=bad.name.google.com; 7 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 8 | Received-SPF: softfail 9 | (marcbradshaw.net: Sender is not authorized by default to use 'marc@marcbradshaw.net' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) 10 | receiver=test.module; 11 | identity=mailfrom; 12 | envelope-from="marc@marcbradshaw.net"; 13 | helo=bad.name.google.com; 14 | client-ip=123.123.123.123 15 | DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=marcbradshaw.net; h=from 16 | :to:subject; s=tfe2; bh=Z1rObkCx8w01d7+aXVQFqtqal9Y=; b=S/mtomBF 17 | fMeLyRHW9vDS74LS8p2mwuIMcdO8KimZjCknRCoEJDOkcIBjRIi6D+FhThzBCnBn 18 | ddLSqbSnJ3Cj6HEm8fOAqOqaJDCXko41ig+d3FXkk9SEL7rgLmILh9h9pn1IBdG7 19 | kKGnOevLaEMBW8dPKYBbhI7f6hsJBZ8PAfbG3a381uvNAhwgPwtqqIc0UqxroFBD 20 | +yQ56muCQMfn0NA9syLhL1/lFY7OsQeapeCbRSr6AiTVOlAnmlZAiOZj+RP3HUfj 21 | vrc04lYjJNOnjBjQytHhxDGJENgOyii+iDMna6krEQc0BtF6KlBT2UYVr4uX5QD9 22 | olnyCKPw9uEqmA== 23 | From: test@goestheweasel.com 24 | To: test@example.com 25 | Subject: This is a test 26 | 27 | This should be a DMARC fail with a reject policy. 28 | 29 | 30 | -------------------------------------------------------------------------------- /t/data/example/dmarc_reject_wl.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=bad.name.google.com 3 | XFORWARD ADDR=123.123.123.123 4 | XFORWARD NAME=bad.name.google.com 5 | MAIL FROM:marc@marcbradshaw.net 6 | RCPT TO:marc@fastmail.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Authentication-Results: server.example.com; 13 | dkim-adsp=unknown (ADSP policy from goestheweasel.com); 14 | dkim=pass (2048-bit rsa key sha1) header.d=marcbradshaw.net header.i=@marcbradshaw.net header.b=S/mtomBF header.a=rsa-sha1 header.s=tfe2; 15 | dmarc=fail policy.published-domain-policy=reject policy.applied-disposition=none policy.evaluated-disposition=reject policy.override-reason=trusted_forwarder (p=reject,d=none,d.eval=reject,override=trusted_forwarder) policy.policy-from=p header.from=goestheweasel.com; 16 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 17 | spf=softfail smtp.mailfrom=marc@marcbradshaw.net smtp.helo=bad.name.google.com; 18 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 19 | Received-SPF: softfail 20 | (marcbradshaw.net: Sender is not authorized by default to use 'marc@marcbradshaw.net' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) 21 | receiver=server.example.com; 22 | identity=mailfrom; 23 | envelope-from="marc@marcbradshaw.net"; 24 | helo=bad.name.google.com; 25 | client-ip=123.123.123.123 26 | DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=marcbradshaw.net; h=from 27 | :to:subject; s=tfe2; bh=Z1rObkCx8w01d7+aXVQFqtqal9Y=; b=S/mtomBF 28 | fMeLyRHW9vDS74LS8p2mwuIMcdO8KimZjCknRCoEJDOkcIBjRIi6D+FhThzBCnBn 29 | ddLSqbSnJ3Cj6HEm8fOAqOqaJDCXko41ig+d3FXkk9SEL7rgLmILh9h9pn1IBdG7 30 | kKGnOevLaEMBW8dPKYBbhI7f6hsJBZ8PAfbG3a381uvNAhwgPwtqqIc0UqxroFBD 31 | +yQ56muCQMfn0NA9syLhL1/lFY7OsQeapeCbRSr6AiTVOlAnmlZAiOZj+RP3HUfj 32 | vrc04lYjJNOnjBjQytHhxDGJENgOyii+iDMna6krEQc0BtF6KlBT2UYVr4uX5QD9 33 | olnyCKPw9uEqmA== 34 | From: test@goestheweasel.com 35 | To: test@example.com 36 | Subject: This is a test 37 | 38 | This should be a DMARC fail with a reject policy. 39 | 40 | 41 | 42 | . 43 | QUIT 44 | -------------------------------------------------------------------------------- /t/data/example/google_apps_good.timeout.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: from mail-ua0-f173.google.com (mail-ua0-f173.google.com [209.85.217.173]) 3 | (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) 4 | (No client certificate requested) 5 | by mx5.messagingengine.com (Postfix) with ESMTPS 6 | for ; Thu, 1 Dec 2016 22:35:06 -0500 (EST) 7 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 8 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 9 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 10 | d=marcbradshaw.net; s=google; 11 | h=mime-version:date:message-id:subject:from:to:content-type; 12 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 13 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 14 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 15 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 16 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 17 | d=1e100.net; s=20130820; 18 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 19 | :content-type; 20 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 21 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 22 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 23 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 24 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 25 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 26 | x9EA== 27 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 28 | MIME-Version: 1.0 29 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 30 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 31 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 32 | Date: Sun, 25 Jan 2015 14:35:19 +1100 33 | Message-ID: 34 | Subject: Authentication Milter Test 35 | From: Marc Bradshaw 36 | To: marc@fastmail.com 37 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 38 | 39 | --089e01493adaf9a7a9050d71b56f 40 | Content-Type: text/plain; charset=UTF-8 41 | 42 | This is a test email from Google Apps 43 | 44 | -- 45 | *Marc Bradshaw* 46 | http://marcbradshaw.net/ 47 | 48 | --089e01493adaf9a7a9050d71b56f 49 | Content-Type: text/html; charset=UTF-8 50 | Content-Transfer-Encoding: quoted-printable 51 | 52 |
This is a test email from Google Apps

--
Marc = 54 | Bradshaw
=C2=A0http://marcbradshaw.net/
56 | 57 | 58 | --089e01493adaf9a7a9050d71b56f-- 59 | -------------------------------------------------------------------------------- /t/data/example/google_apps_good_case.local.eml: -------------------------------------------------------------------------------- 1 | Authentication-Results: test.module; 2 | dkim=pass (1024-bit rsa key sha256) header.d=marcbradshaw.net header.i=@marcbradshaw.net header.b=DU/QdEi3 header.a=rsa-sha256 header.s=google; 3 | x-google-dkim=pass (2048-bit rsa key) header.d=1e100.net header.i=@1e100.net header.b=aIL04w54; 4 | x-local-ip=pass 5 | Return-Path: 6 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 7 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 8 | dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 9 | d=marcbradshaw.net; s=google; 10 | h=mime-version:date:message-id:subject:from:to:content-type; 11 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 12 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 13 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 14 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 15 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 16 | d=1e100.net; s=20130820; 17 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 18 | :content-type; 19 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 20 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 21 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 22 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 23 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 24 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 25 | x9EA== 26 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 27 | MIME-Version: 1.0 28 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 29 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 30 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 31 | Date: Sun, 25 Jan 2015 14:35:19 +1100 32 | Message-ID: 33 | Subject: Authentication Milter Test 34 | From: Marc Bradshaw 35 | To: marc@fastmail.com 36 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 37 | 38 | --089e01493adaf9a7a9050d71b56f 39 | Content-Type: text/plain; charset=UTF-8 40 | 41 | This is a test email from Google Apps 42 | 43 | -- 44 | *Marc Bradshaw* 45 | http://marcbradshaw.net/ 46 | 47 | --089e01493adaf9a7a9050d71b56f 48 | Content-Type: text/html; charset=UTF-8 49 | Content-Transfer-Encoding: quoted-printable 50 | 51 |
This is a test email from Google Apps

--
Marc = 53 | Bradshaw
=C2=A0http://marcbradshaw.net/
55 | 56 | 57 | --089e01493adaf9a7a9050d71b56f-- 58 | -------------------------------------------------------------------------------- /t/data/example/google_apps_good_dryrun.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: from mail-ua0-f173.google.com (mail-ua0-f173.google.com [209.85.217.173]) 3 | (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) 4 | (No client certificate requested) 5 | by mx5.messagingengine.com (Postfix) with ESMTPS 6 | for ; Thu, 1 Dec 2016 22:35:06 -0500 (EST) 7 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 8 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 9 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 10 | d=marcbradshaw.net; s=google; 11 | h=mime-version:date:message-id:subject:from:to:content-type; 12 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 13 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 14 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 15 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 16 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 17 | d=1e100.net; s=20130820; 18 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 19 | :content-type; 20 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 21 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 22 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 23 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 24 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 25 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 26 | x9EA== 27 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 28 | MIME-Version: 1.0 29 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 30 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 31 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 32 | Date: Sun, 25 Jan 2015 14:35:19 +1100 33 | Message-ID: 34 | Subject: Authentication Milter Test 35 | From: Marc Bradshaw 36 | To: marc@fastmail.com 37 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 38 | 39 | --089e01493adaf9a7a9050d71b56f 40 | Content-Type: text/plain; charset=UTF-8 41 | 42 | This is a test email from Google Apps 43 | 44 | -- 45 | *Marc Bradshaw* 46 | http://marcbradshaw.net/ 47 | 48 | --089e01493adaf9a7a9050d71b56f 49 | Content-Type: text/html; charset=UTF-8 50 | Content-Transfer-Encoding: quoted-printable 51 | 52 |
This is a test email from Google Apps

--
Marc = 54 | Bradshaw
=C2=A0http://marcbradshaw.net/
56 | 57 | 58 | --089e01493adaf9a7a9050d71b56f-- 59 | -------------------------------------------------------------------------------- /t/data/example/google_apps_nodkim.eml: -------------------------------------------------------------------------------- 1 | Authentication-Results: test.module; 2 | dkim=none (no signatures found); 3 | dmarc=pass policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 4 | iprev=pass smtp.remote-ip=74.125.82.171 (mail-we0-f171.google.com); 5 | spf=pass smtp.mailfrom=marc@marcbradshaw.net smtp.helo=mail-we0-f171.google.com; 6 | x-google-dkim=none (no signatures found); 7 | x-ptr=pass smtp.helo=mail-we0-f171.google.com policy.ptr=mail-we0-f171.google.com 8 | Received-SPF: pass 9 | (marcbradshaw.net: Sender is authorized to use 'marc@marcbradshaw.net' in 'mfrom' identity (mechanism 'include:_spf.google.com' matched)) 10 | receiver=test.module; 11 | identity=mailfrom; 12 | envelope-from="marc@marcbradshaw.net"; 13 | helo=mail-we0-f171.google.com; 14 | client-ip=74.125.82.171 15 | Return-Path: 16 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 17 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 18 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 19 | MIME-Version: 1.0 20 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 21 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 22 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 23 | Date: Sun, 25 Jan 2015 14:35:19 +1100 24 | Message-ID: 25 | Subject: Authentication Milter Test 26 | From: Marc Bradshaw 27 | To: marc@fastmail.com 28 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 29 | 30 | --089e01493adaf9a7a9050d71b56f 31 | Content-Type: text/plain; charset=UTF-8 32 | 33 | This is a test email from Google Apps 34 | 35 | -- 36 | *Marc Bradshaw* 37 | http://marcbradshaw.net/ 38 | 39 | --089e01493adaf9a7a9050d71b56f 40 | Content-Type: text/html; charset=UTF-8 41 | Content-Transfer-Encoding: quoted-printable 42 | 43 |
This is a test email from Google Apps

--
Marc = 45 | Bradshaw
=C2=A0http://marcbradshaw.net/
47 | 48 | 49 | --089e01493adaf9a7a9050d71b56f-- 50 | -------------------------------------------------------------------------------- /t/data/example/google_apps_nodkim.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=mail-we0-f171.google.com 3 | XFORWARD ADDR=74.125.82.171 4 | XFORWARD NAME=mail-we0-f171.google.com 5 | MAIL FROM:marc@marcbradshaw.net 6 | RCPT TO:marc@fastmail.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Authentication-Results: server.example.com; 13 | dkim=none (no signatures found); 14 | dmarc=pass policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 15 | iprev=pass smtp.remote-ip=74.125.82.171 (mail-we0-f171.google.com); 16 | spf=pass smtp.mailfrom=marc@marcbradshaw.net smtp.helo=mail-we0-f171.google.com; 17 | x-google-dkim=none (no signatures found); 18 | x-ptr=pass smtp.helo=mail-we0-f171.google.com policy.ptr=mail-we0-f171.google.com 19 | Received-SPF: pass 20 | (marcbradshaw.net: Sender is authorized to use 'marc@marcbradshaw.net' in 'mfrom' identity (mechanism 'include:_spf.google.com' matched)) 21 | receiver=server.example.com; 22 | identity=mailfrom; 23 | envelope-from="marc@marcbradshaw.net"; 24 | helo=mail-we0-f171.google.com; 25 | client-ip=74.125.82.171 26 | Return-Path: 27 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 28 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 29 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 30 | MIME-Version: 1.0 31 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 32 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 33 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 34 | Date: Sun, 25 Jan 2015 14:35:19 +1100 35 | Message-ID: 36 | Subject: Authentication Milter Test 37 | From: Marc Bradshaw 38 | To: marc@fastmail.com 39 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 40 | 41 | --089e01493adaf9a7a9050d71b56f 42 | Content-Type: text/plain; charset=UTF-8 43 | 44 | This is a test email from Google Apps 45 | 46 | -- 47 | *Marc Bradshaw* 48 | http://marcbradshaw.net/ 49 | 50 | --089e01493adaf9a7a9050d71b56f 51 | Content-Type: text/html; charset=UTF-8 52 | Content-Transfer-Encoding: quoted-printable 53 | 54 |
This is a test email from Google Apps

--
Marc = 56 | Bradshaw
=C2=A0http://marcbradshaw.net/
58 | 59 | 60 | --089e01493adaf9a7a9050d71b56f-- 61 | 62 | . 63 | QUIT 64 | -------------------------------------------------------------------------------- /t/data/example/google_apps_nodkim_hide_none.eml: -------------------------------------------------------------------------------- 1 | Authentication-Results: mx.example.net; 2 | dmarc=pass policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 3 | spf=pass smtp.mailfrom=marc@marcbradshaw.net smtp.helo=mail-we0-f171.google.com 4 | Received-SPF: pass 5 | (marcbradshaw.net: Sender is authorized to use 'marc@marcbradshaw.net' in 'mfrom' identity (mechanism 'include:_spf.google.com' matched)) 6 | receiver=test.module; 7 | identity=mailfrom; 8 | envelope-from="marc@marcbradshaw.net"; 9 | helo=mail-we0-f171.google.com; 10 | client-ip=74.125.82.171 11 | Return-Path: 12 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 13 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 14 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 15 | MIME-Version: 1.0 16 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 17 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 18 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 19 | Date: Sun, 25 Jan 2015 14:35:19 +1100 20 | Message-ID: 21 | Subject: Authentication Milter Test 22 | From: Marc Bradshaw 23 | To: marc@fastmail.com 24 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 25 | 26 | --089e01493adaf9a7a9050d71b56f 27 | Content-Type: text/plain; charset=UTF-8 28 | 29 | This is a test email from Google Apps 30 | 31 | -- 32 | *Marc Bradshaw* 33 | http://marcbradshaw.net/ 34 | 35 | --089e01493adaf9a7a9050d71b56f 36 | Content-Type: text/html; charset=UTF-8 37 | Content-Transfer-Encoding: quoted-printable 38 | 39 |
This is a test email from Google Apps

--
Marc = 41 | Bradshaw
=C2=A0http://marcbradshaw.net/
43 | 44 | 45 | --089e01493adaf9a7a9050d71b56f-- 46 | -------------------------------------------------------------------------------- /t/data/example/google_apps_nodkim_hide_none.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=mail-we0-f171.google.com 3 | XFORWARD ADDR=74.125.82.171 4 | XFORWARD NAME=mail-we0-f171.google.com 5 | MAIL FROM: 6 | RCPT TO: 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Authentication-Results: mx.example.net; 13 | dmarc=pass policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 14 | spf=pass smtp.mailfrom=marc@marcbradshaw.net smtp.helo=mail-we0-f171.google.com 15 | Received-SPF: pass 16 | (marcbradshaw.net: Sender is authorized to use 'marc@marcbradshaw.net' in 'mfrom' identity (mechanism 'include:_spf.google.com' matched)) 17 | receiver=server.example.com; 18 | identity=mailfrom; 19 | envelope-from="marc@marcbradshaw.net"; 20 | helo=mail-we0-f171.google.com; 21 | client-ip=74.125.82.171 22 | Return-Path: 23 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 24 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 25 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 26 | MIME-Version: 1.0 27 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 28 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 29 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 30 | Date: Sun, 25 Jan 2015 14:35:19 +1100 31 | Message-ID: 32 | Subject: Authentication Milter Test 33 | From: Marc Bradshaw 34 | To: marc@fastmail.com 35 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 36 | 37 | --089e01493adaf9a7a9050d71b56f 38 | Content-Type: text/plain; charset=UTF-8 39 | 40 | This is a test email from Google Apps 41 | 42 | -- 43 | *Marc Bradshaw* 44 | http://marcbradshaw.net/ 45 | 46 | --089e01493adaf9a7a9050d71b56f 47 | Content-Type: text/html; charset=UTF-8 48 | Content-Transfer-Encoding: quoted-printable 49 | 50 |
This is a test email from Google Apps

--
Marc = 52 | Bradshaw
=C2=A0http://marcbradshaw.net/
54 | 55 | 56 | --089e01493adaf9a7a9050d71b56f-- 57 | 58 | . 59 | QUIT 60 | -------------------------------------------------------------------------------- /t/data/example/google_apps_nodkim_spf_fail.eml: -------------------------------------------------------------------------------- 1 | Authentication-Results: test.module; 2 | dkim=none (no signatures found); 3 | dmarc=fail policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 4 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 5 | spf=softfail smtp.mailfrom=marc@marcbradshaw.net smtp.helo=bad.name.google.com; 6 | x-google-dkim=none (no signatures found); 7 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 8 | Received-SPF: softfail 9 | (marcbradshaw.net: Sender is not authorized by default to use 'marc@marcbradshaw.net' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) 10 | receiver=test.module; 11 | identity=mailfrom; 12 | envelope-from="marc@marcbradshaw.net"; 13 | helo=bad.name.google.com; 14 | client-ip=123.123.123.123 15 | Return-Path: 16 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 17 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 18 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 19 | MIME-Version: 1.0 20 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 21 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 22 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 23 | Date: Sun, 25 Jan 2015 14:35:19 +1100 24 | Message-ID: 25 | Subject: Authentication Milter Test 26 | From: Marc Bradshaw 27 | To: marc@fastmail.com 28 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 29 | 30 | --089e01493adaf9a7a9050d71b56f 31 | Content-Type: text/plain; charset=UTF-8 32 | 33 | This is a test email from Google Apps 34 | 35 | -- 36 | *Marc Bradshaw* 37 | http://marcbradshaw.net/ 38 | 39 | --089e01493adaf9a7a9050d71b56f 40 | Content-Type: text/html; charset=UTF-8 41 | Content-Transfer-Encoding: quoted-printable 42 | 43 |
This is a test email from Google Apps

--
Marc = 45 | Bradshaw
=C2=A0http://marcbradshaw.net/
47 | 48 | 49 | --089e01493adaf9a7a9050d71b56f-- 50 | -------------------------------------------------------------------------------- /t/data/example/google_apps_nodkim_spf_fail.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=bad.name.google.com 3 | XFORWARD ADDR=123.123.123.123 4 | XFORWARD NAME=bad.name.google.com 5 | MAIL FROM:marc@marcbradshaw.net 6 | RCPT TO:marc@fastmail.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Authentication-Results: server.example.com; 13 | dkim=none (no signatures found); 14 | dmarc=fail policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=marcbradshaw.net; 15 | iprev=fail smtp.remote-ip=123.123.123.123 (NOT FOUND); 16 | spf=softfail smtp.mailfrom=marc@marcbradshaw.net smtp.helo=bad.name.google.com; 17 | x-google-dkim=none (no signatures found); 18 | x-ptr=fail smtp.helo=bad.name.google.com policy.ptr="" 19 | Received-SPF: softfail 20 | (marcbradshaw.net: Sender is not authorized by default to use 'marc@marcbradshaw.net' in 'mfrom' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) 21 | receiver=server.example.com; 22 | identity=mailfrom; 23 | envelope-from="marc@marcbradshaw.net"; 24 | helo=bad.name.google.com; 25 | client-ip=123.123.123.123 26 | Return-Path: 27 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 28 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 29 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 30 | MIME-Version: 1.0 31 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 32 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 33 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 34 | Date: Sun, 25 Jan 2015 14:35:19 +1100 35 | Message-ID: 36 | Subject: Authentication Milter Test 37 | From: Marc Bradshaw 38 | To: marc@fastmail.com 39 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 40 | 41 | --089e01493adaf9a7a9050d71b56f 42 | Content-Type: text/plain; charset=UTF-8 43 | 44 | This is a test email from Google Apps 45 | 46 | -- 47 | *Marc Bradshaw* 48 | http://marcbradshaw.net/ 49 | 50 | --089e01493adaf9a7a9050d71b56f 51 | Content-Type: text/html; charset=UTF-8 52 | Content-Transfer-Encoding: quoted-printable 53 | 54 |
This is a test email from Google Apps

--
Marc = 56 | Bradshaw
=C2=A0http://marcbradshaw.net/
58 | 59 | 60 | --089e01493adaf9a7a9050d71b56f-- 61 | 62 | . 63 | QUIT 64 | -------------------------------------------------------------------------------- /t/data/example/list.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=test.example.com 3 | XFORWARD ADDR=1.2.3.4 4 | XFORWARD NAME=test.example.com 5 | MAIL FROM:test@example.com 6 | RCPT TO:test@example.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Authentication-Results: server.example.com; 13 | dkim=none (no signatures found); 14 | dmarc=none policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,has-list-id=yes,d=none,d.eval=none) policy.policy-from=p header.from=example.com; 15 | iprev=fail smtp.remote-ip=1.2.3.4 (NOT FOUND); 16 | spf=fail smtp.mailfrom=test@example.com smtp.helo=test.example.com; 17 | x-google-dkim=none (no signatures found); 18 | x-ptr=fail smtp.helo=test.example.com policy.ptr="" 19 | Received-SPF: fail 20 | (example.com: Sender is not authorized by default to use 'test@example.com' in 'mfrom' identity (mechanism '-all' matched)) 21 | receiver=server.example.com; 22 | identity=mailfrom; 23 | envelope-from="test@example.com"; 24 | helo=test.example.com; 25 | client-ip=1.2.3.4 26 | From: test@example.com 27 | To: test@example.com 28 | List-ID: 29 | Subject: This is a test 30 | 31 | Email List Detection Test 32 | 33 | 34 | . 35 | QUIT 36 | -------------------------------------------------------------------------------- /t/data/example/spam_headers_hide_none.eml: -------------------------------------------------------------------------------- 1 | Received: from mailer.example.com (mailer.example.com [1.2.3.4]) 2 | (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) 3 | (No client certificate requested) 4 | by mx2.messagingengine.com (Postfix) with ESMTPS 5 | for ; Mon, 9 Jan 2017 21:15:20 -0500 (EST) 6 | Received: from mailer.fr.example.com ([2.3.4.5]) 7 | by mx2-fr with esmtps (TLSv1:DHE-RSA-AES256-SHA:256) 8 | (Exim 4.84) 9 | (envelope-from ) 10 | id 1cQF4M-0008Gi-9t 11 | for test@example.com; Sun, 08 Jan 2017 16:07:38 +0100 12 | Message-Id: <201701081507.v08F7TXC031048@ws5-fr.fr.example.net> 13 | MIME-Version: 1.0 14 | Content-Disposition: inline 15 | Content-Transfer-Encoding: binary 16 | Content-Type: text/plain; charset="utf-8" 17 | X-Mailer: MIME::Lite 3.027 (F2.74; T1.31; A2.06; B3.07; Q3.07) 18 | Date: Sun, 8 Jan 2017 15:07:29 +0000 19 | From: "Dear Customer 20 | 21 | Happy new Year Ray-Ban Sunglasses items on online shop. 22 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 23 | 99$ & Up To 87% OFF 24 | Welcome to check our website: http://www.example.com/ 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 | To: test@example.com 77 | Subject: Dear Customer 78 | 79 | Happy new Year Ray-Ban Sunglasses items on online shop. 80 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 81 | 99$ & Up To 87% OFF 82 | Welcome to check our website: http://www.example.com/ 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 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | =?UTF-8?Q?=20vous=20a=20envoy=C3=A9=20un=20li?==?UTF-8?Q?en?= 133 | 134 | -------------------------------------------------------------------------------- /t/data/example/spam_headers_hide_none.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=mail.example.org 3 | XFORWARD ADDR=123.123.123.123 4 | XFORWARD NAME=mail.example.org 5 | MAIL FROM: 6 | RCPT TO: 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Received: from mailer.example.com (mailer.example.com [1.2.3.4]) 13 | (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) 14 | (No client certificate requested) 15 | by mx2.messagingengine.com (Postfix) with ESMTPS 16 | for ; Mon, 9 Jan 2017 21:15:20 -0500 (EST) 17 | Received: from mailer.fr.example.com ([2.3.4.5]) 18 | by mx2-fr with esmtps (TLSv1:DHE-RSA-AES256-SHA:256) 19 | (Exim 4.84) 20 | (envelope-from ) 21 | id 1cQF4M-0008Gi-9t 22 | for test@example.com; Sun, 08 Jan 2017 16:07:38 +0100 23 | Message-Id: <201701081507.v08F7TXC031048@ws5-fr.fr.example.net> 24 | MIME-Version: 1.0 25 | Content-Disposition: inline 26 | Content-Transfer-Encoding: binary 27 | Content-Type: text/plain; charset="utf-8" 28 | X-Mailer: MIME::Lite 3.027 (F2.74; T1.31; A2.06; B3.07; Q3.07) 29 | Date: Sun, 8 Jan 2017 15:07:29 +0000 30 | From: "Dear Customer 31 | 32 | Happy new Year Ray-Ban Sunglasses items on online shop. 33 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 34 | 99$ & Up To 87% OFF 35 | Welcome to check our website: http://www.example.com/ 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 | To: test@example.com 88 | Subject: Dear Customer 89 | 90 | Happy new Year Ray-Ban Sunglasses items on online shop. 91 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 92 | 99$ & Up To 87% OFF 93 | Welcome to check our website: http://www.example.com/ 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | =?UTF-8?Q?=20vous=20a=20envoy=C3=A9=20un=20li?==?UTF-8?Q?en?= 144 | 145 | 146 | . 147 | QUIT 148 | -------------------------------------------------------------------------------- /t/data/example/spam_headers_spf_hide_none.eml: -------------------------------------------------------------------------------- 1 | Authentication-Results: mx.example.net; 2 | spf=pass smtp.mailfrom=marc@marcbradshaw.net smtp.helo=mail-we0-f171.google.com 3 | Received-SPF: pass 4 | (marcbradshaw.net: Sender is authorized to use 'marc@marcbradshaw.net' in 'mfrom' identity (mechanism 'include:_spf.google.com' matched)) 5 | receiver=test.module; 6 | identity=mailfrom; 7 | envelope-from="marc@marcbradshaw.net"; 8 | helo=mail-we0-f171.google.com; 9 | client-ip=74.125.82.171 10 | Received: from mailer.example.com (mailer.example.com [1.2.3.4]) 11 | (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) 12 | (No client certificate requested) 13 | by mx2.messagingengine.com (Postfix) with ESMTPS 14 | for ; Mon, 9 Jan 2017 21:15:20 -0500 (EST) 15 | Received: from mailer.fr.example.com ([2.3.4.5]) 16 | by mx2-fr with esmtps (TLSv1:DHE-RSA-AES256-SHA:256) 17 | (Exim 4.84) 18 | (envelope-from ) 19 | id 1cQF4M-0008Gi-9t 20 | for test@example.com; Sun, 08 Jan 2017 16:07:38 +0100 21 | Message-Id: <201701081507.v08F7TXC031048@ws5-fr.fr.example.net> 22 | MIME-Version: 1.0 23 | Content-Disposition: inline 24 | Content-Transfer-Encoding: binary 25 | Content-Type: text/plain; charset="utf-8" 26 | X-Mailer: MIME::Lite 3.027 (F2.74; T1.31; A2.06; B3.07; Q3.07) 27 | Date: Sun, 8 Jan 2017 15:07:29 +0000 28 | From: "Dear Customer 29 | 30 | Happy new Year Ray-Ban Sunglasses items on online shop. 31 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 32 | 99$ & Up To 87% OFF 33 | Welcome to check our website: http://www.example.com/ 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 | To: test@example.com 86 | Subject: Dear Customer 87 | 88 | Happy new Year Ray-Ban Sunglasses items on online shop. 89 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 90 | 99$ & Up To 87% OFF 91 | Welcome to check our website: http://www.example.com/ 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 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | =?UTF-8?Q?=20vous=20a=20envoy=C3=A9=20un=20li?==?UTF-8?Q?en?= 142 | 143 | -------------------------------------------------------------------------------- /t/data/example/tools_test.eml: -------------------------------------------------------------------------------- 1 | EHLO test.module 2 | XFORWARD NAME=test.connect.name 3 | XFORWARD ADDR=123.123.123.123 4 | XFORWARD HELO=test.helo.host 5 | MAIL FROM:test@mail.from 6 | RCPT TO:test@rcpt.to 7 | DATA 8 | Return-Path: 9 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 10 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 11 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 12 | d=marcbradshaw.net; s=google; 13 | h=mime-version:date:message-id:subject:from:to:content-type; 14 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 15 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 16 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 17 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 18 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 19 | d=1e100.net; s=20130820; 20 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 21 | :content-type; 22 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 23 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 24 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 25 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 26 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 27 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 28 | x9EA== 29 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 30 | MIME-Version: 1.0 31 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 32 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 33 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 34 | Date: Sun, 25 Jan 2015 14:35:19 +1100 35 | Message-ID: 36 | Subject: Authentication Milter Test 37 | From: Marc Bradshaw 38 | To: marc@fastmail.com 39 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 40 | 41 | --089e01493adaf9a7a9050d71b56f 42 | Content-Type: text/plain; charset=UTF-8 43 | 44 | This is a test email from Google Apps 45 | 46 | -- 47 | *Marc Bradshaw* 48 | http://marcbradshaw.net/ 49 | 50 | --089e01493adaf9a7a9050d71b56f 51 | Content-Type: text/html; charset=UTF-8 52 | Content-Transfer-Encoding: quoted-printable 53 | 54 | .. 55 | ... 56 | .... 57 | This. 58 | ..Is test 59 | 60 |
This is a test email from Google Apps

--
Marc = 62 | Bradshaw
=C2=A0http://marcbradshaw.net/
64 | 65 | 66 | --089e01493adaf9a7a9050d71b56f-- 67 | 68 | . 69 | QUIT 70 | -------------------------------------------------------------------------------- /t/data/example/transparency.smtp.eml: -------------------------------------------------------------------------------- 1 | EHLO server.example.com 2 | XFORWARD HELO=test.example.com 3 | XFORWARD ADDR=1.2.3.4 4 | XFORWARD NAME=test.example.com 5 | MAIL FROM:test@example.com 6 | RCPT TO:test@example.com 7 | DATA 8 | Received: from test.module (localhost [127.0.0.1]) 9 | by server.example.com (Authentication Milter) with ESMTP 10 | ############ 11 | ############ 12 | Authentication-Results: server.example.com; 13 | dkim=none (no signatures found); 14 | dmarc=none policy.published-domain-policy=none policy.applied-disposition=none policy.evaluated-disposition=none (p=none,d=none,d.eval=none) policy.policy-from=p header.from=example.com; 15 | iprev=fail smtp.remote-ip=1.2.3.4 (NOT FOUND); 16 | spf=fail smtp.mailfrom=test@example.com smtp.helo=test.example.com; 17 | x-google-dkim=none (no signatures found); 18 | x-ptr=fail smtp.helo=test.example.com policy.ptr="" 19 | Received-SPF: fail 20 | (example.com: Sender is not authorized by default to use 'test@example.com' in 'mfrom' identity (mechanism '-all' matched)) 21 | receiver=server.example.com; 22 | identity=mailfrom; 23 | envelope-from="test@example.com"; 24 | helo=test.example.com; 25 | client-ip=1.2.3.4 26 | From: test@example.com 27 | To: test@example.com 28 | Subject: This is a test 29 | 30 | Transparency test 31 | .. 32 | 33 | Testing 34 | Testing 35 | 1 36 | .. 37 | ..2 38 | ... 39 | 3! 40 | 41 | 42 | . 43 | QUIT 44 | -------------------------------------------------------------------------------- /t/data/metrics/milter_timeout.json: -------------------------------------------------------------------------------- 1 | { 2 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"abort\",type=\"timeout\"}" : "1", 3 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"body\",type=\"timeout\"}" : "1", 4 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"close\",type=\"timeout\"}" : "1", 5 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"connect\",type=\"timeout\"}" : "1", 6 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"envfrom\",type=\"timeout\"}" : "1", 7 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"eoh\",type=\"timeout\"}" : "1", 8 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"eom\",type=\"timeout\"}" : "1", 9 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"header\",type=\"timeout\"}" : "15", 10 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"helo\",type=\"timeout\"}" : "1", 11 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\",stage=\"rcptto\",type=\"timeout\"}" : "1", 12 | "authmilter_callback_error_total{ident=\"test_authentication_milter_test\"}" : "0", 13 | "authmilter_connect_total{ident=\"test_authentication_milter_test\"}" : "1", 14 | "authmilter_forked_children_total{ident=\"test_authentication_milter_test\"}" : 123456, 15 | "authmilter_mail_processed_total{ident=\"test_authentication_milter_test\"}" : "0", 16 | "authmilter_processes_processing{ident=\"test_authentication_milter_test\"}" : 123456, 17 | "authmilter_processes_waiting{ident=\"test_authentication_milter_test\"}" : 123456, 18 | "authmilter_reaped_children_total{ident=\"test_authentication_milter_test\"}" : "0", 19 | "authmilter_time_microseconds_total{ident=\"test_authentication_milter_test\"}" : "0", 20 | "authmilter_uptime_seconds_total{ident=\"test_authentication_milter_test\"}" : 123456 21 | } 22 | -------------------------------------------------------------------------------- /t/data/source/dmarc_multi.eml: -------------------------------------------------------------------------------- 1 | From: test@goestheweasel.com 2 | From : test@marcbradshaw.net, test@example.com 3 | To: test@example.com 4 | Subject: This is a test 5 | 6 | This should have multiple dmarc entries 7 | -------------------------------------------------------------------------------- /t/data/source/dmarc_reject.eml: -------------------------------------------------------------------------------- 1 | From: test@goestheweasel.com 2 | To: test@example.com 3 | Subject: This is a test 4 | 5 | This should be a DMARC fail with a reject policy. 6 | 7 | -------------------------------------------------------------------------------- /t/data/source/dmarc_reject_case.eml: -------------------------------------------------------------------------------- 1 | FROM: test@goestheweasel.com 2 | To: test@example.com 3 | Subject: This is a test 4 | 5 | This should be a DMARC fail with a reject policy. 6 | 7 | -------------------------------------------------------------------------------- /t/data/source/dmarc_reject_wl.eml: -------------------------------------------------------------------------------- 1 | DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=marcbradshaw.net; h=from 2 | :to:subject; s=tfe2; bh=Z1rObkCx8w01d7+aXVQFqtqal9Y=; b=S/mtomBF 3 | fMeLyRHW9vDS74LS8p2mwuIMcdO8KimZjCknRCoEJDOkcIBjRIi6D+FhThzBCnBn 4 | ddLSqbSnJ3Cj6HEm8fOAqOqaJDCXko41ig+d3FXkk9SEL7rgLmILh9h9pn1IBdG7 5 | kKGnOevLaEMBW8dPKYBbhI7f6hsJBZ8PAfbG3a381uvNAhwgPwtqqIc0UqxroFBD 6 | +yQ56muCQMfn0NA9syLhL1/lFY7OsQeapeCbRSr6AiTVOlAnmlZAiOZj+RP3HUfj 7 | vrc04lYjJNOnjBjQytHhxDGJENgOyii+iDMna6krEQc0BtF6KlBT2UYVr4uX5QD9 8 | olnyCKPw9uEqmA== 9 | From: test@goestheweasel.com 10 | To: test@example.com 11 | Subject: This is a test 12 | 13 | This should be a DMARC fail with a reject policy. 14 | 15 | 16 | -------------------------------------------------------------------------------- /t/data/source/google_apps_bad.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 3 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 4 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 5 | d=marcbradshaw.net; s=google; 6 | h=mime-version:date:message-id:subject:from:to:content-type; 7 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 8 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbsPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 9 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 10 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 11 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 12 | d=1e100.net; s=20130820; 13 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 14 | :content-type; 15 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 16 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 17 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 18 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nqRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 19 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 20 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 21 | x9EA== 22 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 23 | MIME-Version: 1.0 24 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 25 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 26 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 27 | Date: Sun, 25 Jan 2015 14:35:19 +1100 28 | Message-ID: 29 | Subject: Authentication Milter Test 30 | From: Marc Bradshaw 31 | To: marc@fastmail.com 32 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 33 | 34 | --089e01493adaf9a7a9050d71b56f 35 | Content-Type: text/plain; charset=UTF-8 36 | 37 | This is a test email from Google Apps 38 | 39 | -- 40 | *Marc Bradshaw* 41 | http://marcbradshaw.net/ 42 | 43 | --089e01493adaf9a7a9050d71b56f 44 | Content-Type: text/html; charset=UTF-8 45 | Content-Transfer-Encoding: quoted-printable 46 | 47 |
This is a test email from Google Apps

--
Marc = 49 | Bradshaw
=C2=A0http://marcbradshaw.net/
51 | 52 | 53 | --089e01493adaf9a7a9050d71b56f-- 54 | -------------------------------------------------------------------------------- /t/data/source/google_apps_bad_space.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 3 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 4 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 5 | d=marcbradshaw.net; s=google; 6 | h=mime-version:date:message-id:subject:from:to:content-type; 7 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 8 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 9 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 10 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 11 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 12 | d=1e100.net; s=20130820; 13 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 14 | :content-type; 15 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 16 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 17 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 18 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 19 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 20 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 21 | x9EA== 22 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 23 | MIME-Version: 1.0 24 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 25 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 26 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 27 | Date: Sun, 25 Jan 2015 14:35:19 +1100 28 | Message-ID: 29 | Subject: Authentication Milter Test 30 | From: Marc Bradshaw 31 | To: marc@fastmail.com 32 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 33 | 34 | --089e01493adaf9a7a9050d71b56f 35 | Content-Type: text/plain; charset=UTF-8 36 | 37 | This is a test email from Google Apps 38 | 39 | -- 40 | *Marc Bradshaw* 41 | http://marcbradshaw.net/ 42 | 43 | --089e01493adaf9a7a9050d71b56f 44 | Content-Type: text/html; charset=UTF-8 45 | Content-Transfer-Encoding: quoted-printable 46 | 47 |
This is a test email from Google Apps

--
Marc = 49 | Bradshaw
=C2=A0http://marcbradshaw.net/
51 | 52 | 53 | --089e01493adaf9a7a9050d71b56f-- 54 | -------------------------------------------------------------------------------- /t/data/source/google_apps_good.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: from mail-ua0-f173.google.com (mail-ua0-f173.google.com [209.85.217.173]) 3 | (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) 4 | (No client certificate requested) 5 | by mx5.messagingengine.com (Postfix) with ESMTPS 6 | for ; Thu, 1 Dec 2016 22:35:06 -0500 (EST) 7 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 8 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 9 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 10 | d=marcbradshaw.net; s=google; 11 | h=mime-version:date:message-id:subject:from:to:content-type; 12 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 13 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 14 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 15 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 16 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 17 | d=1e100.net; s=20130820; 18 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 19 | :content-type; 20 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 21 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 22 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 23 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 24 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 25 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 26 | x9EA== 27 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 28 | MIME-Version: 1.0 29 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 30 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 31 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 32 | Date: Sun, 25 Jan 2015 14:35:19 +1100 33 | Message-ID: 34 | Subject: Authentication Milter Test 35 | From: Marc Bradshaw 36 | To: marc@fastmail.com 37 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 38 | 39 | --089e01493adaf9a7a9050d71b56f 40 | Content-Type: text/plain; charset=UTF-8 41 | 42 | This is a test email from Google Apps 43 | 44 | -- 45 | *Marc Bradshaw* 46 | http://marcbradshaw.net/ 47 | 48 | --089e01493adaf9a7a9050d71b56f 49 | Content-Type: text/html; charset=UTF-8 50 | Content-Transfer-Encoding: quoted-printable 51 | 52 |
This is a test email from Google Apps

--
Marc = 54 | Bradshaw
=C2=A0http://marcbradshaw.net/
56 | 57 | 58 | --089e01493adaf9a7a9050d71b56f-- 59 | -------------------------------------------------------------------------------- /t/data/source/google_apps_good_case.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 3 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 4 | dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 5 | d=marcbradshaw.net; s=google; 6 | h=mime-version:date:message-id:subject:from:to:content-type; 7 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 8 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 9 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 10 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 11 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 12 | d=1e100.net; s=20130820; 13 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 14 | :content-type; 15 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 16 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 17 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 18 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 19 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 20 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 21 | x9EA== 22 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 23 | MIME-Version: 1.0 24 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 25 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 26 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 27 | Date: Sun, 25 Jan 2015 14:35:19 +1100 28 | Message-ID: 29 | Subject: Authentication Milter Test 30 | From: Marc Bradshaw 31 | To: marc@fastmail.com 32 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 33 | 34 | --089e01493adaf9a7a9050d71b56f 35 | Content-Type: text/plain; charset=UTF-8 36 | 37 | This is a test email from Google Apps 38 | 39 | -- 40 | *Marc Bradshaw* 41 | http://marcbradshaw.net/ 42 | 43 | --089e01493adaf9a7a9050d71b56f 44 | Content-Type: text/html; charset=UTF-8 45 | Content-Transfer-Encoding: quoted-printable 46 | 47 |
This is a test email from Google Apps

--
Marc = 49 | Bradshaw
=C2=A0http://marcbradshaw.net/
51 | 52 | 53 | --089e01493adaf9a7a9050d71b56f-- 54 | -------------------------------------------------------------------------------- /t/data/source/google_apps_headers.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 3 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 4 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 5 | d=marcbradshaw.net; s=google; 6 | h=mime-version:date:message-id:subject:from:to:content-type; 7 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 8 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 9 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 10 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 11 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 12 | d=1e100.net; s=20130820; 13 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 14 | :content-type; 15 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 16 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 17 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 18 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 19 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 20 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 21 | x9EA== 22 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 23 | MIME-Version: 1.0 24 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 25 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 26 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 27 | Date: Sun, 25 Jan 2015 14:35:19 +1100 28 | Message-ID: 29 | Subject: Authentication Milter Test 30 | From: Marc Bradshaw 31 | To: marc@fastmail.com 32 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 33 | 34 | --089e01493adaf9a7a9050d71b56f 35 | Content-Type: text/plain; charset=UTF-8 36 | 37 | This is a test email from Google Apps 38 | 39 | -- 40 | *Marc Bradshaw* 41 | http://marcbradshaw.net/ 42 | 43 | --089e01493adaf9a7a9050d71b56f 44 | Content-Type: text/html; charset=UTF-8 45 | Content-Transfer-Encoding: quoted-printable 46 | 47 |
This is a test email from Google Apps

--
Marc = 49 | Bradshaw
=C2=A0http://marcbradshaw.net/
51 | 52 | 53 | --089e01493adaf9a7a9050d71b56f-- 54 | -------------------------------------------------------------------------------- /t/data/source/google_apps_nodkim.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 3 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 4 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 5 | MIME-Version: 1.0 6 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 7 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 8 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 9 | Date: Sun, 25 Jan 2015 14:35:19 +1100 10 | Message-ID: 11 | Subject: Authentication Milter Test 12 | From: Marc Bradshaw 13 | To: marc@fastmail.com 14 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 15 | 16 | --089e01493adaf9a7a9050d71b56f 17 | Content-Type: text/plain; charset=UTF-8 18 | 19 | This is a test email from Google Apps 20 | 21 | -- 22 | *Marc Bradshaw* 23 | http://marcbradshaw.net/ 24 | 25 | --089e01493adaf9a7a9050d71b56f 26 | Content-Type: text/html; charset=UTF-8 27 | Content-Transfer-Encoding: quoted-printable 28 | 29 |
This is a test email from Google Apps

--
Marc = 31 | Bradshaw
=C2=A0http://marcbradshaw.net/
33 | 34 | 35 | --089e01493adaf9a7a9050d71b56f-- 36 | -------------------------------------------------------------------------------- /t/data/source/google_apps_noxgdkim.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: from mail-ua0-f173.google.com (mail-ua0-f173.google.com [209.85.217.173]) 3 | (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) 4 | (No client certificate requested) 5 | by mx5.messagingengine.com (Postfix) with ESMTPS 6 | for ; Thu, 1 Dec 2016 22:35:06 -0500 (EST) 7 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 8 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 9 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 10 | d=marcbradshaw.net; s=google; 11 | h=mime-version:date:message-id:subject:from:to:content-type; 12 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 13 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 14 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 15 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 16 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 17 | MIME-Version: 1.0 18 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 19 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 20 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 21 | Date: Sun, 25 Jan 2015 14:35:19 +1100 22 | Message-ID: 23 | Subject: Authentication Milter Test 24 | From: Marc Bradshaw 25 | To: marc@fastmail.com 26 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 27 | 28 | --089e01493adaf9a7a9050d71b56f 29 | Content-Type: text/plain; charset=UTF-8 30 | 31 | This is a test email from Google Apps 32 | 33 | -- 34 | *Marc Bradshaw* 35 | http://marcbradshaw.net/ 36 | 37 | --089e01493adaf9a7a9050d71b56f 38 | Content-Type: text/html; charset=UTF-8 39 | Content-Transfer-Encoding: quoted-printable 40 | 41 |
This is a test email from Google Apps

--
Marc = 43 | Bradshaw
=C2=A0http://marcbradshaw.net/
45 | 46 | 47 | --089e01493adaf9a7a9050d71b56f-- 48 | -------------------------------------------------------------------------------- /t/data/source/list.eml: -------------------------------------------------------------------------------- 1 | From: test@example.com 2 | To: test@example.com 3 | List-ID: 4 | Subject: This is a test 5 | 6 | Email List Detection Test 7 | 8 | -------------------------------------------------------------------------------- /t/data/source/spam_headers.eml: -------------------------------------------------------------------------------- 1 | Received: from mailer.example.com (mailer.example.com [1.2.3.4]) 2 | (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) 3 | (No client certificate requested) 4 | by mx2.messagingengine.com (Postfix) with ESMTPS 5 | for ; Mon, 9 Jan 2017 21:15:20 -0500 (EST) 6 | Received: from mailer.fr.example.com ([2.3.4.5]) 7 | by mx2-fr with esmtps (TLSv1:DHE-RSA-AES256-SHA:256) 8 | (Exim 4.84) 9 | (envelope-from ) 10 | id 1cQF4M-0008Gi-9t 11 | for test@example.com; Sun, 08 Jan 2017 16:07:38 +0100 12 | Message-Id: <201701081507.v08F7TXC031048@ws5-fr.fr.example.net> 13 | MIME-Version: 1.0 14 | Content-Disposition: inline 15 | Content-Transfer-Encoding: binary 16 | Content-Type: text/plain; charset="utf-8" 17 | X-Mailer: MIME::Lite 3.027 (F2.74; T1.31; A2.06; B3.07; Q3.07) 18 | Date: Sun, 8 Jan 2017 15:07:29 +0000 19 | From: "Dear Customer 20 | 21 | Happy new Year Ray-Ban Sunglasses items on online shop. 22 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 23 | 99$ & Up To 87% OFF 24 | Welcome to check our website: http://www.example.com/ 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 | To: test@example.com 77 | Subject: Dear Customer 78 | 79 | Happy new Year Ray-Ban Sunglasses items on online shop. 80 | All items are in new condition,and new style.Ray-Ban Sunglasses Just 19. 81 | 99$ & Up To 87% OFF 82 | Welcome to check our website: http://www.example.com/ 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 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | =?UTF-8?Q?=20vous=20a=20envoy=C3=A9=20un=20li?==?UTF-8?Q?en?= 133 | 134 | -------------------------------------------------------------------------------- /t/data/source/tools_test.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Received: by mail-we0-f171.google.com with SMTP id k11so1456187wes.2 3 | for ; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 4 | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 5 | d=marcbradshaw.net; s=google; 6 | h=mime-version:date:message-id:subject:from:to:content-type; 7 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 8 | b=DU/QdEi3GUUK1jz9pbH4A5UaeGhbPPzrPPTDAbqrn4EABY8kSBqxOVhl8xyIC08Chh 9 | 44rMiMlO8RigLW9cBoQybRnKSzviGwP+QuS4xTdVzemM/1Pdat9FteJPsz8MpbHlRrQ7 10 | EpwcaQdYRJRlnrGaQhn9dkPU7xcfN0w+nsabU= 11 | X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; 12 | d=1e100.net; s=20130820; 13 | h=x-gm-message-state:mime-version:date:message-id:subject:from:to 14 | :content-type; 15 | bh=7gvdmshMrcJRxJis+zHrBpu6zyqotJf8vROJvE5OcmA=; 16 | b=aIL04w54Mcpr7cMQUdQrqpI4aUs4gV0Ww5+iyWnf0nMNUlsITzqPY2+5TBL2/l/ob1 17 | nYRBLo+B01xb6HGTx1vATg/O/hrMPqK2pxICsTlIDvMBRpFsSDJbQpu0hQWpJXxF4cuQ 18 | 9QRyp3vYB0EWbn8Dxs9gm9V8G+b7nCRVG+X9YGFolXq00PPDRTIIB7adXmwDnHIdPx+u 19 | Gb0MegXHP92U3iGZeZsEO1Gq9P6P44tp/v+09h9usq4OhBunjXojilYiB461BoBBYkGx 20 | MC7vok22L8D9ssU+z0H6VzSbD/B0tzPuLFQOKmoCVnim22SUpZHzNo05Ui3Bro43J3T0 21 | x9EA== 22 | X-Gm-Message-State: ALoCoQk+WCmS7pcgC26VeCszzOVzmv40XekPP1BxHJ4oY6p8UbjDcdVNr8WFuchigs3toyPgqHDU 23 | MIME-Version: 1.0 24 | X-Received: by 10.194.175.39 with SMTP id bx7mr30495438wjc.22.1422156919049; 25 | Sat, 24 Jan 2015 19:35:19 -0800 (PST) 26 | Received: by 10.217.143.139 with HTTP; Sat, 24 Jan 2015 19:35:19 -0800 (PST) 27 | Date: Sun, 25 Jan 2015 14:35:19 +1100 28 | Message-ID: 29 | Subject: Authentication Milter Test 30 | From: Marc Bradshaw 31 | To: marc@fastmail.com 32 | Content-Type: multipart/alternative; boundary=089e01493adaf9a7a9050d71b56f 33 | 34 | --089e01493adaf9a7a9050d71b56f 35 | Content-Type: text/plain; charset=UTF-8 36 | 37 | This is a test email from Google Apps 38 | 39 | -- 40 | *Marc Bradshaw* 41 | http://marcbradshaw.net/ 42 | 43 | --089e01493adaf9a7a9050d71b56f 44 | Content-Type: text/html; charset=UTF-8 45 | Content-Transfer-Encoding: quoted-printable 46 | 47 | . 48 | .. 49 | ... 50 | This. 51 | .Is test 52 | 53 |
This is a test email from Google Apps

--
Marc = 55 | Bradshaw
=C2=A0http://marcbradshaw.net/
57 | 58 | 59 | --089e01493adaf9a7a9050d71b56f-- 60 | -------------------------------------------------------------------------------- /t/data/source/transparency.eml: -------------------------------------------------------------------------------- 1 | From: test@example.com 2 | To: test@example.com 3 | Subject: This is a test 4 | 5 | Transparency test 6 | . 7 | 8 | Testing 9 | Testing 10 | 1 11 | . 12 | .2 13 | .. 14 | 3! 15 | 16 | -------------------------------------------------------------------------------- /t/dev-boilerplate.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use Test::More; 6 | 7 | plan tests => 2; 8 | 9 | sub not_in_file_ok { 10 | my ($filename, %regex) = @_; 11 | open( my $fh, '<', $filename ) 12 | or die "couldn't open $filename for reading: $!"; 13 | 14 | my %violated; 15 | 16 | while (my $line = <$fh>) { 17 | while (my ($desc, $regex) = each %regex) { 18 | if ($line =~ $regex) { 19 | push @{$violated{$desc}||=[]}, $.; 20 | } 21 | } 22 | } 23 | 24 | if (%violated) { 25 | fail("$filename contains boilerplate text"); 26 | diag "$_ appears on lines @{$violated{$_}}" for keys %violated; 27 | } else { 28 | pass("$filename contains no boilerplate text"); 29 | } 30 | } 31 | 32 | sub module_boilerplate_ok { 33 | my ($module) = @_; 34 | not_in_file_ok($module => 35 | 'the great new $MODULENAME' => qr/ - The great new /, 36 | 'boilerplate description' => qr/Quick summary of what the module/, 37 | 'stub function definition' => qr/function[12]/, 38 | ); 39 | } 40 | 41 | TODO: { 42 | local $TODO = "Need to replace the boilerplate text"; 43 | 44 | not_in_file_ok(Changes => 45 | "placeholder date/time" => qr(Date/time) 46 | ); 47 | 48 | module_boilerplate_ok('lib/Mail/Milter/Authentication/Handler/ARC.pm'); 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /t/dev-critic.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | use 5.006; 3 | use strict; 4 | use warnings; 5 | use File::Spec; 6 | use Test::More; 7 | use English qw(-no_match_vars); 8 | 9 | if ( not $ENV{TEST_AUTHOR} ) { 10 | my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.'; 11 | plan( skip_all => $msg ); 12 | } 13 | 14 | eval { require Test::Perl::Critic; }; 15 | 16 | if ( $EVAL_ERROR ) { 17 | my $msg = 'Test::Perl::Critic required to criticise code'; 18 | plan( skip_all => $msg ); 19 | } 20 | 21 | my $rcfile = File::Spec->catfile( 't', 'perlcriticrc' ); 22 | Test::Perl::Critic->import( -profile => $rcfile ); 23 | all_critic_ok(); 24 | 25 | -------------------------------------------------------------------------------- /t/dev-manifest.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use Test::More; 6 | 7 | unless ( $ENV{RELEASE_TESTING} ) { 8 | plan( skip_all => "Author tests not required for installation" ); 9 | } 10 | 11 | my $min_tcm = 0.9; 12 | eval "use Test::CheckManifest $min_tcm"; 13 | plan skip_all => "Test::CheckManifest $min_tcm required" if $@; 14 | 15 | ok_manifest( 16 | { 17 | 'filter' => [ 18 | qr/\.git/, 19 | qr/\/tmp\//, 20 | qr/\/inc\/Module\/AutoInstall/, 21 | qr/\/inc\/Module\/Install/, 22 | qr/\.swp/, 23 | qr/\/local_files\//, 24 | qr/\/\.travis\.yml/, 25 | qr/\/cover_db/, 26 | ], 27 | } 28 | ); 29 | -------------------------------------------------------------------------------- /t/dev-pod.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | use Test::More; 6 | 7 | # Ensure a recent version of Test::Pod 8 | my $min_tp = 1.22; 9 | eval "use Test::Pod $min_tp"; 10 | plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; 11 | 12 | all_pod_files_ok(); 13 | -------------------------------------------------------------------------------- /t/get_record.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Net::DNS; 6 | use Data::Dumper; 7 | 8 | my $domain = $ARGV[0]; 9 | 10 | my $resolver = Net::DNS::Resolver->new(); 11 | 12 | my $queries = [ 13 | [ q{}, 'A' ], 14 | [ q{}, 'NS' ], 15 | [ q{}, 'AAAA' ], 16 | [ q{}, 'MX' ], 17 | [ '_dmarc.', 'TXT' ], 18 | [ q{}, 'TXT' ], 19 | ]; 20 | 21 | foreach my $query ( @$queries ) { 22 | my $domain_part = $query->[0] . $domain; 23 | my $type_part = $query->[1]; 24 | $resolver->query( $domain_part, $type_part ); 25 | } 26 | 27 | print Dumper( $resolver->get_static_data() ); 28 | 29 | 1; 30 | 31 | package # hide from pause 32 | Net::DNS::Resolver; 33 | 34 | use MIME::Base64; 35 | 36 | my $static_data = {}; 37 | sub get_static_data { 38 | return $static_data; 39 | } 40 | 41 | sub send { ## no critic 42 | my ( $self ) = shift; 43 | my @args = @_; 44 | return $self->cache_lookup( 'send', @args ); 45 | } 46 | 47 | sub query { 48 | my ( $self ) = shift; 49 | my @args = @_; 50 | return $self->cache_lookup( 'query', @args ); 51 | } 52 | 53 | sub search { 54 | my ( $self ) = shift; 55 | my @args = @_; 56 | return $self->cache_lookup( 'search', @args ); 57 | } 58 | 59 | sub cache_lookup { 60 | my $self = shift; 61 | my $type = shift; 62 | my @args = @_; 63 | my $key = join(":" , $type, @args); 64 | my $return; 65 | 66 | if ( $type eq 'search' ) { 67 | $return = $self->SUPER::search(@args); 68 | } 69 | elsif ( $type eq 'send' ) { 70 | $return = $self->SUPER::send(@args); 71 | } 72 | elsif ( $type eq 'query' ) { 73 | $return = $self->SUPER::query(@args); 74 | } 75 | else { 76 | die "Unknown lookup type $type\n"; 77 | } 78 | 79 | { 80 | my $string = q{}; 81 | if ( $return ) { 82 | $string = encode_base64( $return->data(), q{} ); 83 | } 84 | $static_data->{ $key } = [ $string, $self->errorstring() ]; 85 | } 86 | 87 | return $return; 88 | } 89 | 90 | 91 | 1; 92 | 93 | -------------------------------------------------------------------------------- /t/perlcriticrc: -------------------------------------------------------------------------------- 1 | severity = stern 2 | ; gentle stern harsh cruel brutal 3 | 4 | verbose = [%p] %m at line %l, column %c. %e. (Severity: %s)\n 5 | 6 | ; $PROGRAM_NAME should not be localized- 7 | [-Variables::RequireLocalizedPunctuationVars] 8 | 9 | [-ValuesAndExpressions::ProhibitConstantPragma] 10 | 11 | [Documentation::RequirePodSections] 12 | 13 | [-Modules::ProhibitMultiplePackages] 14 | 15 | [-Subroutines::RequireFinalReturn] 16 | [-Subroutines::ProhibitSubroutinePrototypes] 17 | -------------------------------------------------------------------------------- /weaver.ini: -------------------------------------------------------------------------------- 1 | [@CorePrep] 2 | 3 | [-SingleEncoding] 4 | 5 | [Name] 6 | [Version] 7 | 8 | [Region / prelude] 9 | 10 | [Generic / SYNOPSIS] 11 | [Generic / DESCRIPTION] 12 | [Generic / OVERVIEW] 13 | 14 | [Collect / ATTRIBUTES] 15 | command = attr 16 | 17 | [Collect / CONSTRUCTOR] 18 | command = constructor 19 | 20 | [Collect / METHODS] 21 | command = method 22 | 23 | [Collect / METRICS METHODS] 24 | command = metric_method 25 | 26 | [Collect / RBL METHODS ] 27 | command = rbl_method 28 | 29 | [Collect / TIMEOUT METHODS] 30 | command = timeout_method 31 | 32 | [Collect / CALLBACK METHODS] 33 | command = callback_method 34 | 35 | [Collect / HELPER METHODS] 36 | command = helper_method 37 | 38 | [Collect / LOGGING METHODS] 39 | command = log_method 40 | 41 | [Collect / LOW LEVEL METHODS] 42 | command = low_method 43 | 44 | [Collect / FUNCTIONS] 45 | command = func 46 | 47 | [Leftovers] 48 | 49 | [Region / postlude] 50 | 51 | [Authors] 52 | [Legal] 53 | 54 | --------------------------------------------------------------------------------