Search notes:

Emailing executables

Some companies have a policy that wouldn't allow to receive or send executables (such as *.dll, *.exe, *.bat etc.) via e-mail. Such attachments are filtered by some filtering mechanisms.
Sometimes, the filter can be circumvented by sending the attachments in a zip file. However, as the filters get smarters, they will even check the content of a *.zip file and block the transmission if it contains such an executable.
The solution to this problem is to rename the suffix of the attachments so that the filter won't become suspicous.
This is done by the Perl script send_directory_via_mail.pl which must be called like so:
send_directory_via_mail.pl c:\path\to\directory sender.email@somewhere.foo mail.server.foo receiver.email@somewhere.else.bar authenticationForMailServer
The receiver of the mail then uses receive_directory_from_outlook.pl to unzip the sent attachment and restore the suffixes to the original names.

send_directory_via_mail.pl

use warnings;
use strict;

use Archive::Zip qw(:ERROR_CODES :CONSTANTS);

use File::Spec::Functions qw(tmpdir abs2rel);
use File::Basename;
use File::Find;

use Email::Stuffer;
use Email::Sender::Transport::SMTP;

my $file_or_dir_to_send    = shift;

my $sender_mail_address    = shift;
my $smtp_server            = shift;
my $recipient_mail_address = shift;
my $auth_passwd            = shift;

my $subject                = 'yyoouu ggoott mmaaiill';

die "$file_or_dir_to_send does not exist" unless -e $file_or_dir_to_send;

my $zip = new Archive::Zip;

if    (-f $file_or_dir_to_send) {
  $zip -> addFile($file_or_dir_to_send);
}
elsif (-d $file_or_dir_to_send) {
  add_files_recursively($zip, $file_or_dir_to_send);
}

my $zip_file_name = tmpdir . '\file_to_send.zip';
$zip -> writeToFileNamed ($zip_file_name) == AZ_OK or die "Could not write $zip_file_name";

print "\n  $zip_file_name written\n";

send_($sender_mail_address   ,  # from
      $recipient_mail_address,  # to
      $subject               ,  # subject
      $smtp_server           ,  # host
      $sender_mail_address   ,  # sasl_user
      $auth_passwd           ,  # sasl_pd
      $zip_file_name            # attachment
);

print "\n  Mail sent\n";



sub add_files_recursively { # {{{

  my $zip = shift;
  my $dir = shift;

  find (sub {

    return unless -f $File::Find::name;

    my $relative_file_name = abs2rel($File::Find::name, $dir);

    $relative_file_name =~ s/\.exe$/.eggse/;
    $relative_file_name =~ s/\.dll$/.dee-ell-ell/;
    $relative_file_name =~ s/\.pl$/.pee-ell/;
    $relative_file_name =~ s/\.bat$/.6at/;

    my $zip_member = $zip -> addFile($File::Find::name, $relative_file_name);

    $zip_member -> desiredCompressionLevel(COMPRESSION_LEVEL_BEST_COMPRESSION);

  }, $dir);
    
} # }}}

sub send_ { # {{{

    my $from       = shift;
    my $to         = shift;
    my $subject    = shift;
    my $host       = shift;
    my $sasl_user  = shift;
    my $sasl_pw    = shift;
    my $attachment = shift;


    Email::Stuffer ->
      from       ( $from                    ) -> 
      to         ( $to                      ) ->
      subject    ( $subject                 ) ->
      text_body  ("Hi\n\nAttached is a file") ->
      attach_file( $attachment              ) ->
      transport  ( Email::Sender::Transport::SMTP -> new ({
                     host             => $host,
                   # port             =>  25,
                     sasl_username    => $sasl_user, # ?
                     sasl_password    => $sasl_pw })
                 )
    ->send or die "could not send message $!";

    
} # }}}
Github repository SendDirectoryWithMail, path: /send_directory_via_mail.pl

receive_directory_from_outlook.pl

use warnings;
use strict;

use Win32::OLE; # qw (in with)
use Win32::OLE::Const 'Microsoft Outlook';
use Win32::OLE::Variant;

use File::Copy;
use File::Spec::Functions qw(tmpdir);
use File::Find;

use Archive::Extract;

my $dest_dir = shift or die "Missing destination directory";

die "$dest_dir already exists" if -e $dest_dir;

my $OL = Win32::OLE->GetActiveObject('Outlook.Application') || Win32::OLE->new('Outlook.Application', 'Quit');

die unless $OL;

my $NameSpace = $OL->GetNameSpace("MAPI") or die;

my $Folder = $NameSpace->GetDefaultFolder(olFolderInbox);

foreach my $msg (reverse Win32::OLE::in($Folder->{Items})) { # {{{ Find newest message with desired attachment


  if ($msg->{subject} =~ /yyoouu ggoott mmaaiill/) {
     print "\n  Found $msg->{subject} of $msg->{Creationtime}\n";

     process_attachment($msg, $dest_dir);
     exit;
  }

} # }}}

sub process_attachment { # {{{

    my $msg      = shift;
    my $dest_dir = shift;


  # There should be only one attachment, so instead of iterating
  # over the array returned by *...in, we just get the first
  #(and only?) attachment:

    my $attachment = (Win32::OLE::in($msg->{Attachments}))[0];
    my $zip_dest   = tmpdir . "\\" . $attachment->{Filename};


    $attachment -> SaveAsFile($zip_dest);

    print "\n  $zip_dest written\n";

    my $unzip = new Archive::Extract(archive => $zip_dest);
    $unzip->extract(to=>$dest_dir) or die "Could not extract $zip_dest to $dest_dir!";

    print "\n  $zip_dest extracted to $dest_dir\n";

      
    find (sub {

       return unless -f $File::Find::name;

       my $new_file_name = $File::Find::name;

       $new_file_name =~ s/\.eggse$/.exe/;
       $new_file_name =~ s/\.dee-ell-ell/.dll/;
       $new_file_name =~ s/\.pee-ell/.pl/;
       $new_file_name =~ s/\.6at/.bat/;

       if ($File::Find::name ne $new_file_name) {
#        printf "%60s -> %60s\n", $File::Find::name , $new_file_name;
         move ($File::Find::name, $new_file_name);
       }

    }, $dest_dir);

    print "\n  suffixes reset\n";

    
} # }}}
Github repository SendDirectoryWithMail, path: /receive_directory_from_outlook.pl

See also

Outlook

Index