CheckDisclaimer.pm
changeset 5 fe95803ba72d
parent 2 19a6588a44ed
child 6 4f955ca8e44f
equal deleted inserted replaced
4:304d2a09cba4 5:fe95803ba72d
       
     1 package Exim::Plugin::CheckDisclaimer;
       
     2 
       
     3 # For detailed information see the end of this
       
     4 # file.
       
     5 # Source: https://ssl.schlittermann.de/hg/exim-check-message-conformance
       
     6 # (c) 2015 Heiko Schlittermann
       
     7 
       
     8 use Fcntl qw/:seek/;
       
     9 use base 'Exporter';
       
    10 our @EXPORT  = qw(check_disclaimer);
       
    11 our $Verbose = 0;
       
    12 my $pattern;
       
    13 
       
    14 # Lets search for the disclaimer.
       
    15 # Usage: ${perl{check_disclaimer}{<disclaimer>}}
       
    16 #        ${perl{check_disclaimer}{<disclaimer>}{<file>}}
       
    17 #
       
    18 # The content of the <disclaimer> file is used as a regexp to be found
       
    19 # near the end of the <file>. If <file> is not specified, we use the
       
    20 # default file location:
       
    21 # $spool_directory/scan/$message_exim_id/$message_exim_id.eml
       
    22 
       
    23 sub check_disclaimer {
       
    24     my $pattern_file = shift;
       
    25     my $file = shift // Exim::expand_string(
       
    26         '$spool_directory/scan/$message_exim_id/$message_exim_id.eml');
       
    27 
       
    28     if (not defined $pattern) {
       
    29         open(my $fh, $pattern_file) or die "Can't open $pattern_file: $!\n";
       
    30         $_ = join '', <$fh>;
       
    31         $pattern = qr/$_/;
       
    32     }
       
    33 
       
    34     open(my $fh, $file) or die "Can't open $file: $!\n";
       
    35     seek($fh, -1024, SEEK_END)
       
    36       or die "Can't seek to -1024: $!\n"
       
    37       if -s $fh > 1024;
       
    38 
       
    39     $_ = join '', <$fh>;
       
    40 
       
    41     if (/$pattern/) {
       
    42         warn __PACKAGE__
       
    43           . ": signature pattern from $pattern_file matched in $file\n"
       
    44           if $Verbose;
       
    45         return 1;
       
    46     }
       
    47 
       
    48     warn __PACKAGE__
       
    49       . ": signature pattern from $pattern_file NOT matched in $file\n"
       
    50       if $Verbose;
       
    51     return 0;
       
    52 }
       
    53 
       
    54 1;
       
    55 
       
    56 __END__
       
    57 
       
    58 =head1 NAME
       
    59 
       
    60  check_disclaimer - check for an disclaimer pattern
       
    61 
       
    62 =head1 SYNOPSIS
       
    63 
       
    64  use Exim::Plugin::CheckDisclaimer;
       
    65  ${perl{check_disclaimer}{/etc/exim4/disclaimer}}
       
    66  ${perl{check_disclaimer}{/etc/exim4/disclaimer}{$mime_decoded_filename}
       
    67 
       
    68 =head1 DESCRIPTION
       
    69 
       
    70 This Plugin checks for the existence of a message disclaimer by matching
       
    71 the ends of the message parts with a pattern from a pattern file. The
       
    72 B<pattern file> needs to contain a Perl regular expression.
       
    73 
       
    74 To use it, add the following line to your Exim configuration:
       
    75 
       
    76     perl_startup = 
       
    77         use lib '/etc/exim4'; \
       
    78         use Exim::Plugin::CheckDisclaimer; \
       
    79         $Exim::Plugin::CheckDisclaimer::Verbose = 1
       
    80 
       
    81 The disclaimer may be part of the MIME coverletter or 
       
    82 at the end of the old school message body.
       
    83 
       
    84 Now you get a callable `check_disclaimer()` function.
       
    85 Your MIME ACL needs about the following code:
       
    86 
       
    87     acl_check_mime:
       
    88 
       
    89       accept condition = $acl_m_sig_found
       
    90 
       
    91       warn
       
    92         condition           = $mime_is_coverletter
       
    93         !condition          = $mime_is_rfc822
       
    94         decode              = default
       
    95         set acl_m_sig_found = ${perl{check_disclaimer}{/etc/exim4/disclaimer}{$mime_decoded_filename}}
       
    96 
       
    97     accept
       
    98 
       
    99 
       
   100     acl_check_data:
       
   101 
       
   102       warn 
       
   103         !condition          = $acl_m_sig_found
       
   104         # temporary workaround to get the mail spooled to the .eml file
       
   105         # this is NOT necessary if some malware or spam acl condition
       
   106         # was processed already
       
   107         regex               = ^
       
   108         set acl_m_sig_found = \
       
   109                 ${perl{check_disclaimer}{/etc/exim4/disclaimer}}
       
   110 
       
   111       deny !condition = $acl_m_sig_found
       
   112             message   = no signature/disclaimer found
       
   113 
       
   114 =head1 EXAMPLE
       
   115 
       
   116 The example signature pattern file might look:
       
   117 
       
   118  (?mix)          # multiline, case insensitive, extended
       
   119  ^--\x20\s+      # dash, dash, space
       
   120  ^\S+\s\S+\s+    # fist name, last name
       
   121 
       
   122 Or simply
       
   123 
       
   124   -- 
       
   125   \S+
       
   126 
       
   127 =head1 AUTHOR
       
   128 
       
   129 Heiko Schlittermann L<hs@schlittermann.de>
       
   130 
       
   131 =cut
       
   132 
       
   133 // vim:sts=2 sw=2 aw ai et