Re: Hand-rolled CGI mailto
by b10m (Vicar) on Dec 17, 2003 at 00:27 UTC
|
First of all welcome to perlmonks.org :) You can tell a thousand times that you're new to Perl, but that's not going to help you actually. There's nothing wrong with being new to Perl, but if you just posted this (with an appropriate title), the monks would figure out that you're new to Perl and probably are more likely to help. Nonetheless, I'll see what I can do to help ;)
Your script, as posted (please use <code> tags around your actual code, as described in Writeup Formatting Tips), takes for the $formdata hash for granted, yet you don't tell it how to fill it and with what data. The error you get, is Perl complaining about just this :)
I would suggest you take a look at CGI and while you're
reading, read about strict aswell. And -albeit a little old-,
http://www.cgi101.com might help you too :)
I'm pretty sure you can get it to work after reading the stuff mentioned above. Good luck!
| [reply] |
Re: Hand-rolled CGI mailto
by Gerard (Pilgrim) on Dec 17, 2003 at 00:36 UTC
|
Is this your entire script? I can't see you initializing $formdata anywhere, so there is nothing stored in it. try putting use strict at the top of your script, well as the second line.
You need to use something to collect the data from your form. Everyone around here recommends cgi.pm Here is a quick example. The documentation is included with the standard perl distribution.
use strict;
use cgi;
my $query = new CGI;
my $email = $query->param('email');
You can then go onto use the value of $email in your script. It should contain the data in the field named "email" when submitted to your script. Repeat for all paramaters you are interested in. Hope this helps. Regards,
Gerard
Update: I obviously spent too long typing this... seems b10m bet me to most of the info. | [reply] [d/l] [select] |
|
|
| [reply] |
|
|
No problem, cgi.pm - the pm part stands for perl module, and in this case it is a standard module. This means that it should be installed already on the machine that has perl on it. In some cases references will be made to non-standard modules, but this particular case you don't need to worry too much. Just put use cgi; at the top of your code and the perl interpreter will know where to look for it.
If you are interested, there are plenty of nodes on installing modules etc, right here at the monastery.
Hope this helps, Gerard. Update: in short, yes you do need both files, but you should already have cgi.pm there.
| [reply] [d/l] |
|
|
Re: Hand-rolled CGI mailto
by Nkuvu (Priest) on Dec 17, 2003 at 00:31 UTC
|
I'm not a web guru, but there are a few things to note. One, you'll want to read up on tainting. This script is leaving big security holes on your server. Taint mode can be read about via the perldoc perlsec command on your system. This isn't a short subject, but I think it's important.
I'd also suggest looking into the CGI module to make your life easier. Ovid has a very good CGI course.
Edit: I should also note that I didn't really address your question at all with the above info. But it seems to me that b1om covered that already.
| [reply] [d/l] |
Re: Hand-rolled CGI mailto
by tachyon (Chancellor) on Dec 17, 2003 at 01:02 UTC
|
The best solution to your current problem is NMS formmail. You will find a variety of well written Perl CGI widgets (including NMS formmail) ready to go here: http://nms-cgi.sourceforge.net/ DO NOT UNDER ANY CIRCUMSTANCES USE THE NON NMS VERSION OF FORMMAIL.
At the very least it will point you towards the basis of good Perl coding, but you will find that the formail does exactly what you are trying to do in a reliable and secure way. The main functional issue with your script as it exists is that you don't GET the form input into the formdata hash anywhere. You have been shown how to use the CGI module to do this above.
| [reply] |
Re: Hand-rolled CGI mailto
by defyance (Curate) on Dec 17, 2003 at 00:51 UTC
|
Looks like you are trying to get %formdata from a form on a webpage, yes? You might want to first, use CGI; and then try building an html form to get your users input, then your form values will be available in $query->param('value'). Example below:
#!perl -wT
use strict;
use CGI;
# Basic CGI.pm form usage.
my $query = new CGI;
print $query->header;
print $query->start_html("CGI.pm Basic form.");
print $query->start_form;
print "<b>To:</b>";
print $query->textfield('to');
print "<b>From:</b>";
print $query->textfield('from');
print "<b>Message:</b>";
print $query->textfield('body');
print "<p>",$query->reset;
print $query->submit('Action','Stumbit');
print $query->endform;
print "<hr>";
print "YOUR potential business is VERY IMPORTANT .... etc";
print $query->end_html;
# Later on parse your $to $from etc from $query->param('nameofvalues')
+ instead of $formdata{'nameofvalues'}
# and do your mailing, prefferably with a module from CPAN
There is much, much more that needs to be done to make sure that CGI script is secure and functional. You may want to consider checking out Ovid's CGI Course located here: Ovids CGI Course, and some of merlyn's colums located here: WT Colums by Randal.
--
A conclusion is simply the place where someone got tired of thinking.
UPDATE:Just a note, that code is un-tested. | [reply] [d/l] [select] |
Re: Hand-rolled CGI mailto
by davido (Cardinal) on Dec 17, 2003 at 05:41 UTC
|
I just wanted to add to what great advice you've already received with a few tips and pointers that jumped to mind:
First, as others have mentioned, use the CGI.pm module.
To do that, you'll start your program off like this:
#!/usr/bin/perl
use strict; # This is almost always a good idea.
use warnings; # ...as is this, particular when developing code.
use CGI; # This causes the CGI.pm module to be used.
But just including CGI.pm is only part of the story. You should definately have a look at the POD (that's monkspeak for 'Plain Old Documentation') for CGI.pm. Follow the highlighted link, or, find it on your own system as well. If you have Perl, you have CGI.pm. And if you have CGI.pm, you have the POD for it too.
CGI.pm does a lot of the dirty work for you; the stuff nobody in his right mind would bother re-inventing himself when there is already a good implementation out there. (That's my opinion, by the way.) What CGI.pm is really good at is figuring out how to decipher the CGI parameters passed to your script via either GET or POST method. If you try to do it yourself, you (the collective "you"'s in the world, which includes me) usually get it wrong, or fall short of a robust implementation. CGI.pm is your friend for this sort of thing.
As for the mail script itself.... You might be tempted to allow the HTML document to tell the CGI script what email address the mail should be sent to. Even if the end user isn't supposed to be able to name the email address to which the message is being sent, you might be tempted to pass it as a hidden field from the form on the HTML page to the CGI script. That is usually not a good idea. The reason is one of security. Just because your HTML page doesn't give the user the ability to manipulate the destination email address doesn't mean that a malicious user (or a spammer) couldn't just write his own HTML page that does send whatever destination email address he wants to your CGI script.
For that reason, it's a very good idea to control the destination email address yourself, never accepting it as a CGI parameter. Hardwire it into the CGI script, or store it in a configuration file that your script reads. That will prevent spammers from trying to use your mail-to form as a spam relay.
The next issue is that of keeping tainted data away from the shell, away from the OS, and away from anywhere that it might do harm. Start by using the "-T" switch on the shebang line of your CGI script. That will help you to identify where some of your problems with tainted data may be found. Properly untainting data and handling it safely is another lecture. ;)
Others' have referred you to Ovid's online CGI tutorial. I want to also recommend a book published by O'Reilly and Associates called CGI Programming with Perl, 2nd Ed. If you're going to be doing more than just a little CGI tinkering, the book will come in handy. Either buy a copy or check it out at the library. It's commonly known as The Mouse Book.
That book has a chapter that deals with mail form scripts. It also has a lot of good discussion on security concerns. It is a common error to think, "This is just for my personal use. Security isn't that important." But unless you operate in a vacuum, security should always be a concern. That small personal-use script could easily bring a server to its knees if a security hole is exploited. Unless you're the only one using that server, a mistake can cause trouble for lots of people. (Not to scare you or anything...)
Good luck on your dive into the Perl world. Welcome to the monastery. We're always happy to have a new face around here.
| [reply] [d/l] |
Re: Hand-rolled CGI mailto (use a module to send e-mail)
by grinder (Bishop) on Dec 17, 2003 at 08:49 UTC
|
People have explained what's wrong with your web code. Now I'll explain what's wrong with your mail code!
An SMTP message is made up of a series of headers, followed by a blank line, followed by the body of the message. Just putting a blank line in your Perl source code is not sufficient to put a blank line in the e-mail message...
By and large, you should avoid talking to sendmail directly. Use a Perl module instead to save you from having to worry about the nitty-gritty details. Here's how you could send the message with Mail::Sendmail:
use Mail::Sendmail;
sendmail(
To => $to,
From => $from,
Subject => $subject,
Body => <<END_OF_BODY,
Name: $name
EMail: $email
Address_line_1: $address1
Address_line_2: $address2
City: $city
State: $state
Zip: $zip
Home_Phone: $homephone
Work_Phone: $workphone
Type_of_Business: $business
Goals: $goals
Comments: $comments
END_OF_BODY
) or print "Failed to send message [$subject] to [$to]: $Mail::Sendmai
+l::error\n";
Hope this helps.
update: corrected a silly bug in the heredoc syntax (forgot the <<). | [reply] [d/l] [select] |
|
|
| [reply] [d/l] [select] |
|
|
An SMTP message is made up of a series of headers, followed by a blank line, followed by the body of the message. Just putting a blank line in your Perl source code is not sufficient to put a blank line in the e-mail message...
This is correct, but he does have two \n 's after his subject line, which would be sufficent. Otherwise excellent advice. Regards,
Gerard
| [reply] [d/l] |
|
|
Any particular advantage to Mail::Sendmail as opposed to Mail::Mailer? I started using Mail::Mailer after reading the FAQ on mail (I'm not sure which section it's in, I found it via peroldoc -q mail). I'm not familiar enough with either module to make a decent comparison.
| [reply] [d/l] [select] |
CGI mailto via code reuse (AKA the CPAN)
by jeffa (Bishop) on Dec 18, 2003 at 00:19 UTC
|
3 recommendations:
- use CGI to handle all things forms
- use MIME::Lite to send the email
- use abstraction ... let Perl do the work
use strict;
use warnings;
use CGI::Pretty qw(:standard);
use MIME::Lite;
my @FIELD = qw(
name email address1 address2 city state zip
homephone workphone business goals comments
);
print header;
if (param('mail_it')) {
my $data = join('', map "$_: " . param($_) . "\n", @FIELD);
my $msg = MIME::Lite->new(
From => 'webmaster@prowebdesigner.net',
To => 'webmaster@prowebdesigner.net',
Subject => 'Website Design Request',
Data => $data,
);
if ($msg->send) {
print start_html('The Thank You'),
p('
YOUR potential business is VERY IMPORTANT to
PRO WEB DESIGN. We will respond as soon as we can.
'),
;
print p('Here is what you submitted:'),
ul( li[map b("\u$_\E: ") . param($_), @FIELD]),
;
} else {
print start_html('The Oopsie'),
p('whoops! something went wrong!'),
}
} else {
print start_html('The Form'),
start_form,
(map "$_: ".textfield($_).br, @FIELD),
submit('mail_it'),
end_form,
;
}
print end_html;
I know that is a lot to grasp. But if you have the modules installed then by all means try it
out. The benefit of this code is that each field name is only listed in the code once. Plus,
the order that the fields are listed in is easily modified by changing the array @FIELD.
Feel free to ask any questions. ;)
| [reply] [d/l] |