-2

My question is about sending large amounts of text in email via Gmail.

I'm working on a simple application that needs to be able to do a HTTP GET request, and send the received HTML as text using a gmail account. I believe that I am using SSMTTP to send the text via gmail, and I used perl's LWP::UserAgent to do the GET request. When I execute my Perl code, I am getting the following error due to the large amount of text being sent:

Can't exec "/bin/sh": Argument list too long

My internet searches have found these sources:

This gives me a better understanding of the constraints, but it doesn't really solve my issue due to the following reasons:

  • I cannot recompile the kernel
  • I cannot "break it down into smaller pieces" using find or my own bash function, etc.

I am trying to get this to work as requested with large amounts of text.

Here an excerpt from my Perl code:

    # Uses ssmtp to send an email
    sub sendEmail{

     my ($destination, $subject, $body) = @_;

     #say $destination; say $subject;say $body;

     # Create the bash command
     my $command="echo \'$body\' | mail -s \'$subject\' $destination";

     say "\nExecuting shell command: $command";
     my $output = qx($command);
    }

I know that ideally I shouldn't be sending emails with html text. It's what I've been asked to do, so I'm attempting to do as requested.

halfer
  • 19,824
  • 17
  • 99
  • 186
Brett Holman
  • 743
  • 6
  • 18
  • 5
    Substituting unknown text into shell commands is *ridiculously* insecure. If your `body` contains `'$(rm -rf ~)'` (with literal quotes that ends the ones you started with `echo \'`, this could have utterly catastrophic results. – Charles Duffy Dec 02 '17 at 20:31
  • (If `$body` were expanded by the shell it'd be safe, but that's not the case in your original code -- it's expanded by Perl, *before* the shell is invoked.) – Charles Duffy Dec 02 '17 at 20:32
  • Woah @CharlesDuffy good point. I didn't think of that. I'm perl/bash newbie here still learning the semantics of the language. I was unaware that you could pass the variable to the shell before expanding it. Sorry if this is a dumb question, but could help me with the syntax for that? I just tried searching the internet and didn't find anything. – Brett Holman Dec 03 '17 at 04:41
  • 1
    Actually this would be another question. You need to escape the `$` as in `system("echo \$HOME");`. Then the shell would evaluate `$HOME` while in `system("echo $HOME");` Perl would evaluate it. But for this to work the `$HOME` must be known in either the shell or the Perl script. – PerlDuck Dec 03 '17 at 11:15
  • 2
    As PerlDuck says -- to pass variables for expansion by a shell, put them either as explicit argument-list vector members (and refer to them in the shell script as `$1`, `$2`, etc. w/ escaping appropriate to prevent perl from trying to expand them first) or in the environment. But neither of those will work here, since environment variables live in the same limited amount of space used for command-line arguments; tinita's answer as-edited, feeding content on stdin and avoiding a shell altogether, is the Right Thing. – Charles Duffy Dec 03 '17 at 15:34
  • Good to know, thank you. – Brett Holman Dec 04 '17 at 01:10
  • is there a good reason for the downvote on the question? – Brett Holman Mar 29 '18 at 17:07

1 Answers1

7

You don't need to pipe this via shell. Use perl's open:

open (my $pipe, "|-", "mail", "-s", $subject, $destination) or die "Could not run mail: $!";
print $pipe $body;
close $pipe or die $?;

Or try http://p3rl.org/IPC::Run or http://p3rl.org/IPC::Cmd for more control.

perldoc perlopentut

Edit: Replaced open with list form, as suggested by @chepner++. When you don't need any shell syntax like redirects, this is generally safer.

tinita
  • 3,987
  • 1
  • 21
  • 23
  • 4
    Better yet, use the list form (`open my $pipe, "|-", "mail", "-s", $subject, $destination`) when possible to avoid shell involvement entirely. – chepner Dec 02 '17 at 20:18