in reply to Trouble emailing zip file

the message just seems to go into cyberspace and not my inbox?

Does mailx work when you run it from the command line? If not, then maybe your mail system isn't configured properly? Have you checked your system's logs and checked your mailbox for bounced mails? If mailx does work from the command line, then note that you need to check the return value of system for errors - see its docs, but the bare minimum is system(...)==0 or die "\$?=$?";

I've put the curly braces around the variables to try to avoid interpolation

Sorry, that's not how that works, "${foo}" is just another way of writing "$foo". The best way to avoid interpolation is to use the form of system that does not call the shell, where you give system a list of arguments with more than one element. But if you don't go through the shell, you also won't get pipe I/O redirection, which you could solve by a two-step process where the file is first encoded into a temporary file (File::Temp). Or, you could use a module like IPC::Run, which supports I/O redirection. I wrote about this whole topic at length here.

However, I'd strongly recommend against shelling out in the first place. See Email::Stuffer, here's something adapted from its Synopsis:

use Email::Stuffer; Email::Stuffer->from('sender@example.com') ->to('user01@email.org')->subject("logs for $pkgname") ->text_body('Here's the log file.') ->attach_file("$logpath.zip") ->send;

Replies are listed 'Best First'.
Re^2: Trouble emailing zip file
by TonyNY (Beadle) on Jul 03, 2018 at 15:54 UTC

    Unfortunately I don't have any of the email modules installed so I will have to try to use the system with the args method

    and the File::Temp module. I've read the links that you have provided and I understand the system with the args but do not

    understand how to use the File::Temp module. Could you please post an example on how to encode the zip file into the temp file?

      Unfortunately I don't have any of the email modules installed

      Please see Yes, even you can use CPAN - if you can install Perl scripts on the server, then normally you can install modules there too, for example with local::lib.

      Could you please post an example on how to encode the zip file into the temp file?

      I initially thought that uuencode could write its output to a file, but I was mistaken, it apparently always writes to its standard output. Since I don't recommend qx//, capturing its output is not trivial - see the section "Use a Piped open" in that link for a way to do it with pure Perl. Alternatively, you don't have to shell out at all, since pack supports uuencoding - with thanks to the Perl Power Tools:

      # takes one argument, the filename to encode # returns one value, the filename of the temporary(!) output file use File::Temp qw/tempfile/; sub uuencode { my ($infile) = @_; my ($tfh,$tfn) = tempfile(UNLINK=>1); open my $fh, '<:raw', $infile or die "$infile: $!"; printf $tfh "begin %03o %s\n", ((stat($infile))[2] & 0666)||0644, $infile; my $buf; print $tfh pack 'u', $buf while read $fh, $buf, 45; print $tfh "`\n", "end\n"; close $fh; close $tfh; return $tfn; }

      That will return the filename of the temporary file that you can then pass to mailx - but make sure to use the "list" form of system, as I showed in the above link as well.

      By the way, in your original post, you said mailx -r $recipient1 - but the -r option sets the From address. Are you sure you've got your mailx command right?

        Hi haukex,

        I'm getting the following after running the code below"

        Can't exec "/usr/bin/mailx uuencode $zipfile $zipfile -r -s": No such file or directory at ./test-email.pl line 42.

        system /usr/bin/mailx uuencode $zipfile $zipfile -r -s logs user@email.com failed: -1 at ./test-email.pl line 42

        #!/opt/bin/perl use strict; use warnings; my $home = $ENV{"HOME"}; print "$home\n"; my $zipfile = "$home/file.zip"; print "$zipfile\n"; my $emailcmd = '/usr/bin/mailx uuencode $zipfile $zipfile -r -s'; print "$emailcmd\n"; my $subject = 'logs'; print "$subject\n"; my $recipient = 'user@email.com '; print "$recipient\n"; # takes one argument, the filename to encode # returns one value, the filename of the temporary(!) output file use File::Temp qw/tempfile/; sub uuencode { my ($infile) = @_; my ($tfh,$tfn) = tempfile(UNLINK=>1); open my $fh, '<:raw', $infile or die "$infile: $!"; printf $tfh "begin %03o %s\n", ((stat($infile))[2] & 0666)||0644, $infile; my $buf; print $tfh pack 'u', $buf while read $fh, $buf, 45; print $tfh "`\n", "end\n"; close $fh; close $tfh; return $tfn; } #call uuencode sub with param &uuencode($zipfile); my @args = ("$emailcmd", "$subject", "$recipient"); system(@args) == 0 or die "system @args failed: $?";

      The Archive::Zip documentation shows how to save a ZIP file to a given filename:

      # Save the Zip file unless ( $zip->writeToFileNamed('someZip.zip') == AZ_OK ) { die 'write error'; }

      The temp filename should be created through File::Temp:

      my ($tempfile, $name) = tempfile(); close $tempfile;

      I was able to get the following to send the zip file but it's corrupted

      Does anyone know why the zip file arrives corrupted but I can open the same zip file when using a shell script?

      use strict; use warnings; use MIME::Base64; use IO::File; my ($subject, $mach, $from, $to, $attachment, $fh, $content); $subject = "Test Mail"; $from = 'user@email.com'; $to = 'user@email.com'; $attachment = "test.zip"; $fh = "mailbody.txt"; open(FILE, '>', $fh) or die "Cannot open $fh: $!"; print FILE "This is a test"; close(FILE); open(MAIL, "|/usr/sbin/sendmail -t"); print MAIL "FROM: $from\n"; print MAIL "TO: $to\n"; print MAIL "Subject: $subject\n"; print MAIL "Content-Type: multipart/mixed; boundary=frontier\n"; print MAIL "--frontier\n"; print MAIL "Content-Type: text/plain; charset=us-ascii\n\n"; open(FILE, '<', $fh) or die "Cannot open $fh: $!"; print MAIL <FILE>; close(FILE); print MAIL "\n\n"; print MAIL "--frontier\n"; chomp(my $basename=`basename $attachment`); print MAIL "Content-Disposition: attachment; filename=$basename\n"; print MAIL "Content-Type: application/octet-stream; name=$attachment\n +\n"; print MAIL "encode_base64( read_file($attachment) )"; open(FILE, '<', $attachment) or die "Cannot open $attachment: $!"; print MAIL <FILE>; print MAIL "\n"; close(FILE); close(MAIL);
        open(FILE, '<', $attachment) or die "Cannot open $attachment: $!";

        You most likely want binmode:

        open(FILE, '<', $attachment) or die "Cannot open $attachment: $!"; binmode FILE; ...

        Also, you want to eliminate the use of `basename...` in favour of File::Basename::basename:

        use File::Basename 'basename';

        Also, please consider using a module to send mail, like MIME::Lite instead of talking to sendmail directly...

        Why the second print statement ?

        print MAIL "encode_base64( read_file($attachment) )"; open(FILE, '<', $attachment) or die "Cannot open $attachment: $!"; print MAIL <FILE>;

        Try replacing those 3 lines with

        open(FILE, '<', $attachment) or die "Cannot open $attachment: $!"; binmode FILE; while (read(FILE, my $buf, 60*57)) { print MAIL encode_base64($buf); }
        poj
Re^2: Trouble emailing zip file
by TonyNY (Beadle) on Jul 03, 2018 at 14:08 UTC

    Hi haukex,

    Thanks for your response and yes mailx works from the command line.