CheckDisclaimer.pm
changeset 5 fe95803ba72d
parent 2 19a6588a44ed
child 6 4f955ca8e44f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CheckDisclaimer.pm	Wed Jul 08 07:38:26 2015 +0200
@@ -0,0 +1,133 @@
+package Exim::Plugin::CheckDisclaimer;
+
+# For detailed information see the end of this
+# file.
+# Source: https://ssl.schlittermann.de/hg/exim-check-message-conformance
+# (c) 2015 Heiko Schlittermann
+
+use Fcntl qw/:seek/;
+use base 'Exporter';
+our @EXPORT  = qw(check_disclaimer);
+our $Verbose = 0;
+my $pattern;
+
+# Lets search for the disclaimer.
+# Usage: ${perl{check_disclaimer}{<disclaimer>}}
+#        ${perl{check_disclaimer}{<disclaimer>}{<file>}}
+#
+# The content of the <disclaimer> file is used as a regexp to be found
+# near the end of the <file>. If <file> is not specified, we use the
+# default file location:
+# $spool_directory/scan/$message_exim_id/$message_exim_id.eml
+
+sub check_disclaimer {
+    my $pattern_file = shift;
+    my $file = shift // Exim::expand_string(
+        '$spool_directory/scan/$message_exim_id/$message_exim_id.eml');
+
+    if (not defined $pattern) {
+        open(my $fh, $pattern_file) or die "Can't open $pattern_file: $!\n";
+        $_ = join '', <$fh>;
+        $pattern = qr/$_/;
+    }
+
+    open(my $fh, $file) or die "Can't open $file: $!\n";
+    seek($fh, -1024, SEEK_END)
+      or die "Can't seek to -1024: $!\n"
+      if -s $fh > 1024;
+
+    $_ = join '', <$fh>;
+
+    if (/$pattern/) {
+        warn __PACKAGE__
+          . ": signature pattern from $pattern_file matched in $file\n"
+          if $Verbose;
+        return 1;
+    }
+
+    warn __PACKAGE__
+      . ": signature pattern from $pattern_file NOT matched in $file\n"
+      if $Verbose;
+    return 0;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ check_disclaimer - check for an disclaimer pattern
+
+=head1 SYNOPSIS
+
+ use Exim::Plugin::CheckDisclaimer;
+ ${perl{check_disclaimer}{/etc/exim4/disclaimer}}
+ ${perl{check_disclaimer}{/etc/exim4/disclaimer}{$mime_decoded_filename}
+
+=head1 DESCRIPTION
+
+This Plugin checks for the existence of a message disclaimer by matching
+the ends of the message parts with a pattern from a pattern file. The
+B<pattern file> needs to contain a Perl regular expression.
+
+To use it, add the following line to your Exim configuration:
+
+    perl_startup = 
+        use lib '/etc/exim4'; \
+        use Exim::Plugin::CheckDisclaimer; \
+        $Exim::Plugin::CheckDisclaimer::Verbose = 1
+
+The disclaimer may be part of the MIME coverletter or 
+at the end of the old school message body.
+
+Now you get a callable `check_disclaimer()` function.
+Your MIME ACL needs about the following code:
+
+    acl_check_mime:
+
+      accept condition = $acl_m_sig_found
+
+      warn
+        condition           = $mime_is_coverletter
+        !condition          = $mime_is_rfc822
+        decode              = default
+        set acl_m_sig_found = ${perl{check_disclaimer}{/etc/exim4/disclaimer}{$mime_decoded_filename}}
+
+    accept
+
+
+    acl_check_data:
+
+      warn 
+        !condition          = $acl_m_sig_found
+        # temporary workaround to get the mail spooled to the .eml file
+        # this is NOT necessary if some malware or spam acl condition
+        # was processed already
+        regex               = ^
+        set acl_m_sig_found = \
+                ${perl{check_disclaimer}{/etc/exim4/disclaimer}}
+
+      deny !condition = $acl_m_sig_found
+            message   = no signature/disclaimer found
+
+=head1 EXAMPLE
+
+The example signature pattern file might look:
+
+ (?mix)          # multiline, case insensitive, extended
+ ^--\x20\s+      # dash, dash, space
+ ^\S+\s\S+\s+    # fist name, last name
+
+Or simply
+
+  -- 
+  \S+
+
+=head1 AUTHOR
+
+Heiko Schlittermann L<hs@schlittermann.de>
+
+=cut
+
+// vim:sts=2 sw=2 aw ai et