Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Monks, the code works fine. When i get the input from the user for $text, i want to get the input with multiple lines. If the user gives enter after typing first line, the code starts running, i want to get the input even if the user gives enter key until he gives ctrl+c or ctrl+D or ctrl+z or some other option. How can i achieve this. Because in text part i want to print multiple lines. I tried by making input record separator undef, but it is not working as per my requirement

use Mail::Sender::Easy qw(email); print "Enter the From address with comma separator\n"; chomp ($from = <STDIN>); print "Enter the To address with comma separator\n"; chomp ($to = <STDIN>); print "Enter the cc address with comma separator\n"; chomp ($cc = <STDIN>); print "Enter the bcc address with comma separator\n"; chomp ($bcc = <STDIN>); print "Enter the subject\n"; chomp ($sub = <STDIN>); print "Enter the body part\n"; chomp ($text = <STDIN>); email({ 'from' => "$from", 'to' => "$to", 'cc' => "$cc", 'bcc' => "$bcc", 'subject' => "$sub", 'priority' => 2, # 1-5 high to low 'confirm' => 'delivery, reading', 'smtp' => '192.168.1.5', 'port' => 25, #'auth' => 'LOGIN', #'authid' => 'foo@bar.baz', 'authpwd' => 'protect_with_700_perms_or_get_it_from_input +', '_text' => "$text" }) or die "email() failed: $@";

Replies are listed 'Best First'.
Re: <STDIN> input
by xdg (Monsignor) on Apr 01, 2006 at 11:51 UTC

    When you assign <STDIN> to a scalar, you're asking for one line only. You could assign it to an array, which gets all lines until EOF:

    my @input = <STDIN>;

    Making the input separator undef should work, too. Are you sure you're setting the input separator $/ and not the output separator $\?

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: <STDIN> input
by graff (Chancellor) on Apr 02, 2006 at 04:40 UTC
    In order for the user to be typing interactively and have multiple lines assigned to a single scalar string, you have to tell the user to use some special string to indicate that the multi-line input is complete and it's time for the program to move on to the next task. If I wanted to do something like this, I would probably handle it as follows:
    my %email; my @parts = qw/From To Subject cc bcc body/; for my $part ( @parts ) { my $prompt = ( $part eq 'body' ) ? " (type EOT alone on a line to finish):\n" : ": "; print "Enter value for $part$prompt"; $email{$part} = <STDIN>; if ( $part ne 'body' ) { chomp $email{$part} } else { while ( $email{$part} !~ /EOT\s+$/ ) { $email{$part} .= <STDIN>; } s/EOT\s*$//; } } # add more parts to %email as you see fit (priority, port, etc) # (updated to fix logic so that chomp is applied where needed, # also fixed bad quotation mark and confusion in variable names, # and added deletion of "EOT" from $email{body})
    In other words, you have to implement the equivalent of a  << HERE block for user input from STDIN.

    Having said that, I have to admit that I really dislike this sort of interactive input to a perl script. It's so easy to make a mistake while typing to a script's STDIN, and so hard to allow for a mistake to be fixed once it has been made. Most of the time, the user has to interrupt the script and just start over, and unless there is a fairly good facility for line editing, copy/paste, etc (see Term::ReadLine and related modules), it may take several tries to get all the inputs right.

    It is much beetter to use the features already provided by the shell: pipes or files for multi-line input to a script, command-line args for essential parameters, and with the better shells (korn, bash) a very thorough handling of command line editing and ability to recall, modify and re-execute previous commands.

    This way, the user composes their multi-line email body with a text editor of their own choosing and stores this to a plain text file; then they run your script with args on the command line to set the "from", "to", "cc", "bcc" and "subject" fields as needed, and feed the message body via a pipeline (or just have the file name as a last command line arg), to be read inside the script with  while (<>). Problems with the message body will be worked out in a standard text editor; if the user makes any mistakes with the other parameters, those are all on the command line, and the shell makes them easy to fix.