#!/usr/bin/perl -w

=head1 NAME

resubmitter.pl
 v1.0  7-Jul-2013
 v1.1 22-Jul-2022

=head1 DESCRIPTION

This script is used to resubmit incoming messages to an external
virus scanner which works as SMTP relay.


Set up the script as a Content Filtering helper:
  Name: resubmitter
  Program path: /usr/bin/perl /var/CommuniGate/resubmitter.pl
  Log Level: All Info

Invoke the helper from CommuniGate Pro Rule, such as:
  Data:
    [Any Route] [is] 'LOCAL*'
    [Submit Address] [not in] 'SMTP [8.8.8.201*,SMTP [8.8.8.202*'
    [Submit Address] [is not] 'PIPE*'
  Action:
    [ExternalFilter] [resubmitter]

Note that additional checks should be made to prevent
resubmitting messages coming from the scanner back to the scanner.


=head1 AUTHORS

Roman Prokhorov <roma@communigatepro.ru>

=cut

use strict;
use POSIX qw(strftime);


## BEGIN CONFIG

# Here you specify the scanner IPs or hostnames
# You can specify one or multiple names for round-robin load balancing

my @ScannerAddresses = (
'8.8.8.201',
'8.8.8.202',
);


my $verbose = 0;    # debug option
my $quitCounter = 0;    # if >0, feed this number then quit
my $SubmittedDir= "Submitted";

## END CONFIG

$| = 1;

myLog("* resubmitter.pl started");
print "* resubmitter.pl started.\n";

my $msgCounter=0;
my $scannerCounter=0;

while(<STDIN>) {
chomp;
my ($prefix,$command,@args) = split(/ /);
myLog("Cmd: $_") if $verbose;
if($command eq 'INTF') {
  print "$prefix INTF 3\n";

} elsif($command eq 'QUIT') {
  myLog("QUIT command received");
  print "$prefix OK\n";
  last;
} elsif($command eq 'KEY') {
  myLog("KEY command received") if $verbose;
  print "$prefix OK\n";
} elsif($command eq 'FILE') {
  processFILE($prefix,$args[0]);
} else {
  print "$prefix ERROR unexpected command: $command\n";
  myLog("Error: unexpected command: $command") if $verbose;

}
if($quitCounter>0) {
  if(--$quitCounter==0) {
    print "* time to quit and to be restarted\n";
    myLog("* time to quit and to be restarted") if $verbose;
    last;
  }
}
}

print "* stopping the resubmitter plugin\n";
myLog("* stopping the plugin");
exit(0);

# Subs

sub processFILE {
my ($prefix,$fileName) = @_;

myLog("processing: $prefix FILE $fileName");
unless( open (FILE,"$fileName")) {
  print qq/$prefix REJECTED can't open $fileName: $!\n/;
  myLog("ERROR: REJECTED: can't open $fileName: $!");
  return undef;
}


my $returnPath="";
my @recipients;
while(<FILE>) {
  chomp;
  last if($_ eq '');
  my $address=(/\<(.*?)\>/)[0];
  if(/^P/) {
    $returnPath=$address;
    myLog("returnPath: $returnPath") if $verbose;
  }
  elsif(/^R/) {
    $address =~ s/\@/\%/g;
    $address.='@'.$ScannerAddresses[$scannerCounter];
    myLog("recipient: $address") if $verbose;
    push(@recipients,$address);
  }
  
}
$scannerCounter=0 if(++$scannerCounter>=scalar(@ScannerAddresses));
$fileName=~/(\d+)\./;
my $subFileName=$SubmittedDir.'/'.$1;
myLog("Submitted file name: $subFileName") if $verbose;

unless( open(WFILE,">$subFileName.tmp")) {
  print qq/$prefix REJECTED can't create $subFileName.tmp: $!\n/;
  myLog("ERROR: REJECTED: can't create $subFileName.tmp: $!");
  close(FILE);
  return undef;
}

print WFILE "Return-Path: <$returnPath>\n";

#print WFILE "Envelope-To: ".join(",",@recipients)."\n";
  my $line='Envelope-To: ';
  for(my $idx=0;$idx<@recipients;$idx++) {
    $line.=$recipients[$idx];
    $line.="," if($idx<@recipients-1);
    if(length($line)>900) {
      print WFILE "$line\n";
      $line=' ';
    }
  }
  if(length($line)>2) {
    print WFILE "$line\n";
  }


while(<FILE>) {
  next if(/^Envelope-to:/i);
  print WFILE $_;
}

close(WFILE);
close(FILE);

unless( rename("$subFileName.tmp","$subFileName.sub") ) {
  print qq/$prefix REJECTED can't rename open $subFileName.tmp to $subFileName.sub: $!\n/;
  myLog("ERROR: REJECTED: can't rename open $subFileName.tmp to $subFileName.sub: $!");
  unlink("$subFileName.tmp");
  return undef;
}

myLog("done $prefix $fileName, discarding");
print qq/$prefix DISCARD\n/;

undef;
}

sub myLog {
   my ($data)=@_;

   $data =~ s/[\015\012]//g;
   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
   my $fName=sprintf("SystemLogs/%04d-%02d-%02d_resubmitter.log",$year+1900,$mon+1,$mday);
   my $tmstr=sprintf("%02d:%02d:%02d",$hour,$min,$sec);

   unless (open LOG,">>$fName") {
       print "* can't append to $fName: $!\n";
       return;
   }

#    LOG->autoflush(1);

   print LOG "$tmstr 1 $data\n";
   close LOG;
}

__END__
