Article Listing 1 aug2004.tar

Listing 1 Filter to append company disclaimer to all email messages

 #/usr/bin/perl 

 # Libraries we need for our filter
 use strict;
 use Sendmail::Milter; 

 # This tells Milter to pass information from the MAIL FROM and
 # body portions of the DATA call to our filter and to also call
 # eom_callback() at the end of the message. The abort callback
 # is to free the private thread data if the user aborts the
 # message
 my %callbacks = (
                  'envfrom'   =>  \&envfrom_callback,
                  'body'      =>  \&body_callback,
                  'eom'       =>  \&eom_callback,
                  'abort'     =>  \&abort_callback,
                ); 

 # Our callback to handle the MAIL FROM command, which we use
 # to setup our message data which is private to this thread
 sub envfrom_callback {
    my $ctx = shift;
    my $message = ''; 

    # Store a reference to the $message scalar which will hold
    # the text of our E-mail message in the body callback
    $ctx->setpriv(\$message); 

    # Tell Sendmail to continue processing the message
    return (SMFIS_CONTINUE);
}

# This function gathers each body chunk into our current threads
# private data
sub body_callback {
    my $ctx = shift;
    my $body_chunk = shift;
    my $message_ref = $ctx->getpriv();  # Pull in our thread specific data

    # Append this chunk onto our string
    ${$message_ref} .= $body_chunk; 

    # Reset our private data
    $ctx->setpriv($message_ref); 

    # Continue processing this message
    return (SMFIS_CONTINUE);
}

# This function is called at the end of the message which is
# where we'll add our line of text to it
sub eom_callback {
    my $ctx = shift;
    my $message_ref = $ctx->getpriv();  # Pull in our message text

    # Append a disclaimer
    ${$message_ref} .= "[This message has been filtered by a Milter]"; 

    # Replace the body of our message with our new one
    $ctx->replacebody( ${$message_ref} ); 

    # Set our private data to undefined to reclaim the memory used
    $ctx->setpriv(undef); 

    # Tell Sendmail to continue as normal
    return (SMFIS_CONTINUE);
}

# Free memory in case of abort
sub abort_callback {
    my $ctx = shift; 

    # Clear the data
    $ctx->setpriv(undef); 

    return (SMFIS_CONTINUE);
}

# This is standard boiler plate code that can be used for most
# filters, it tells the filter how to configure itself based on
# the information in your Sendmail configuration and handles
# cleaning up old socket files, etc.
BEGIN:
{
  # Print usage info if not called with arguments
  if( scalar(@ARGV) < 2 ) {
     print "Usage perl $0 <filter name> <path to sendmail.cf>\n";
     exit;
  }

  my $conn = Sendmail::Milter::auto_getconn($ARGV[0], $ARGV[1]); 

  if( !$conn ) {
      print "Failed to detect configuration information\n";
      exit;
  }

  # Remove socket if we're running locally
  if( $conn =~ /^local:(.+)$/ ) {
      my $unix_socket = $1; 

      if( -e $unix_socket ) {
          if( !unlink($unix_socket) ) {
              print "Cannot remove socket file\n";
              exit;
          }
      }
  }

  # Register our callbacks
  if( !Sendmail::Milter::register($ARGV[0], \%callbacks,
      SMFI_CURR_ACTS)) {
      print "Unable to register callbacks\n";
      exit;
  }

  # Start our main loop
  Sendmail::Milter::main(); 

}
# End of Filter