#!/usr/bin/perl -w

# Masquerade.pl
# 
# An external filtering helper for replacing addresses in messages passing through.
#
# version 1.0 31-Mar-2018
#
# DATA
# [Submit Address] [is not] [PIPE*]
# ACTION
# [ExternalFilter] masquerade
#
# Mail your comments to support@communigate.ru



use strict;

####  YOU SHOLD REDEFINE THESE VARIABLES !!!

my @deleteHeaders = qw/
 Disposition-Notification-To
 Return-Receipt-To
 Bcc
 DKIM-Signature
/;

my @replaceHeaders = qw/
 From
 To
 Cc
 Reply-To
 Sender
/;

my %replaceAddresses = (
  '@branch.company.com' => '@company.com',

);


my $SubmittedDir= "Submitted"; # /var/CommuniGate/Submitted
my $useFork=1;

#### end of the customizeable variables list

$SIG{CHLD}='IGNORE' if($useFork);
$| = 1;
print "* masquerade.pl started.\n";

push(@deleteHeaders,"Envelope-To");

my $counter=0;

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

  } elsif($command eq 'QUIT') {
    print "$prefix OK\n";
    last; 
  } elsif($command eq 'KEY') {
    print "$prefix OK\n";
  } elsif($command eq 'FILE') {
    if($useFork) {  # process async
      unless(my $pid = fork) {
        die "cannot fork: $!" unless defined $pid;
        processFILE($prefix,$args[0]); 
        exit;  
      }
    } else {        # process synchronously 
       processFILE($prefix,$args[0]); 
    }

  } else {
    print "$prefix ERROR unexpected command: $command\n";
  }
}


print "* stoppig masquerade.pl\n";
exit(0);


sub inSet {
  my ($h,$set)=@_;
  foreach(@$set) {
    if($h=~/^$_\s*:/i) {
      return 1;
    }
  }
  0;
}

sub replaceEnv {
  my ($h)=@_;
  foreach(keys %replaceAddresses) {
    if($$h=~s/$_$/$replaceAddresses{$_}/i) {
      return 1;
    }
  }
  0;
}

sub replaceHdr {
  my ($h)=@_;
  foreach(keys %replaceAddresses) {
    if($$h=~s/$_/$replaceAddresses{$_}/ig) {
      return 1;
    }
  }
  0;
}


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

  unless( open (FILE,"$fileName")) {
    print "$prefix FAILURE can't open $fileName: $!\n"; 
    return undef;
  }

  my $returnPath="";
  my @recipients;
  while(<FILE>) {
    chomp;
    last if($_ eq '');
    my $address=(/\<(.*)\>/)[0];
    my $newAddr;
    replaceEnv(\$address) if($address);
    if(/^P/) { $returnPath=$address; }
    elsif(/^R/) { push(@recipients,$address);}
  } 

  my @messageText;
  while(<FILE>) { #read the mesage
    chomp;
    s/\015$//;
    push(@messageText,$_);
  }
  close(FILE);
    
  for(my $i=0;$i<scalar @messageText;$i++) {
    my $h=$messageText[$i];

    if(inSet($h,\@deleteHeaders)) {
      while($i+1<scalar @messageText && $messageText[$i+1]=~/^\s+(.*)/) {
        splice(@messageText,$i+1,1);
      }
      splice(@messageText,$i,1);
      $i--;
      next;
    }
    
    if(inSet($h,\@replaceHeaders)) {
      replaceHdr(\$messageText[$i]);
      while($i+1<scalar @messageText && $messageText[$i+1]=~/^\s+(.*)/) {
        replaceHdr(\$messageText[$i+1]);
        $i++;
      }
      next;
    } elsif($h eq '') { #stop at the end of header
      last;
    }    
  }
  
  
  my $subFileName;
  do {
    $subFileName=$SubmittedDir.'/v'.int(rand(100000))
  }while(-f "$subFileName.sub" || -f "$subFileName.tmp");
    
  unless( open(WFILE,">$subFileName.tmp")) {
    print "* ($prefix) Problem: can't create $subFileName.tmp: $!\n";
    print qq/$prefix OK\n/; 
    return undef;
  }

  print WFILE "Return-Path: <$returnPath>\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";
  }

  
  print WFILE "$_\n" foreach(@messageText);

  close(WFILE);  
  
  unless( rename("$subFileName.tmp","$subFileName.sub") ) {
    print qq/* can't rename open $subFileName.tmp to $subFileName.sub: $!\n/;
    unlink("$subFileName.tmp");
    return undef;
  }
  
  print qq/$prefix DISCARD\n/; 
  return undef; 
}#processFile


