Re^3: Trouble emailing zip file
by haukex (Archbishop) on Jul 04, 2018 at 10:04 UTC
|
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? | [reply] [d/l] [select] |
|
|
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: $?";
| [reply] [d/l] |
|
|
When using the LIST form of system() the first argument is the program to run, the rest of the arguments are the parameters for the program. I can almost guarantee you don't have a program called /usr/bin/mailx uuencode $zipfile $zipfile -r -s on your system. You probably have /usr/bin/mailx however. The other parts (uuencode $zipfile $zipfile -r -s) need to be passed as parameters to mailx.
my @emailcmd = ('/usr/bin/mailx', 'uuencode', $zipfile, $zipfile, '-r'
+, '-s');
#and later
my @args = (@emailcmd, $subject, $recipient);
system(@args) == 0
or die "system @args failed: $?";
This is of course assuming that the command /usr/bin/mailx uuencode file.zip file.zip -r -s Subject Recipient indeed works on the command line. | [reply] [d/l] [select] |
|
|
| [reply] [d/l] [select] |
|
|
|
|
|
|
Unfortunately, there are several issues with that code. As I documented in the comments, my sub uuencode returns a filename, but you're not using that return value anywhere. Instead, you seem to have just stuck the string "uuencode" into the command right after "mailx" and rearranged the command-line arguments - I'm not sure what you're trying to do there, since I'm pretty sure that doesn't work on the command line either. And Paladin has already identified the issue with your use of system (unfortunately poj's comment was misleading on that issue).
At this point I have to recommend taking a step back. I know that stuff not working can be frustrating. But on the other hand, guessing at syntax doesn't (always) get you further either. I'd have to suggest taking the time to reread perlintro and the documentation on things like system, as well as my node on that topic, as well as Yes, even you can use CPAN and perhaps A Guide to Installing Modules. Invest some time now into understanding those topics to save yourself time afterwards.
| [reply] [d/l] [select] |
Re^3: Trouble emailing zip file
by Corion (Patriarch) on Jul 04, 2018 at 07:22 UTC
|
# 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;
| [reply] [d/l] [select] |
Re^3: Trouble emailing zip file
by TonyNY (Beadle) on Jul 05, 2018 at 19:01 UTC
|
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);
| [reply] [d/l] |
|
|
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... | [reply] [d/l] [select] |
|
|
| [reply] |
|
|
|
|
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 | [reply] [d/l] [select] |
|
|
Thanks poj but the attachment is still arriving corrupted.
| [reply] |
|
|