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

Ok, I tried making a contact form, which you can see below. I run a diagnostic and it shows it runs perfectly. There are no errors no sign of anything wrong. Only problem is, it doesn't email me the results. Can anyone see why? This is soooo confusing to me. Thanks!
#!/usr/bin/perl use strict; use CGI; use CGI::Carp 'fatalsToBrowser'; my $q = new CGI; print $q->header; &parsing; ########### Configure this section my $adminmail = "sulfericacid\@qwest.net"; my $subject = "enter subject here"; my $sendmail = "/usr/sbin/sendmail"; my %formdata; ########### End configurations. Unless you know what you are doing, d +o not edit below open (MAIL, $sendmail) or die "cannot open sendmail"; print MAIL "To: $adminmail\n"; print MAIL "From: admin\@everydayteens.net\n"; print MAIL "subject: $subject\n\n"; print MAIL "Name: $formdata{'name'}\n"; #### ERROR IS ON/NEAR THIS +LINE print MAIL "email: $formdata{'email'}\n"; print MAIL "message: $formdata{'message'}\n"; close(MAIL); sub parsing { my @fields = $q->param; foreach my $field (@fields){ $formdata{$field} = $q->param($field); } } print "Location: thanks.html" or die "cannot locate thanks.html";

Replies are listed 'Best First'.
Re: Contact Form 2
by Juerd (Abbot) on Mar 25, 2002 at 08:26 UTC

    my $sendmail = "/usr/sbin/sendmail";
    open (MAIL, $sendmail) or die "cannot open sendmail";

    You open sendmail for reading, which succeeds. The prints, however, do not succeed. It's not common to do, but you could write:

    print MAIL "To: Adminmail\n" or die $!;
    to find that out (I hate it, but when debugging, it can really aid)

    Instead, you will have to open sendmail as a write-only pipe.

    open MAIL, "| $sendmail" or die $!;
    or, better yet: (Perl 5.6+)
    open MAIL, '|', $sendmail or die $!;

    Sendmail expects the to-address on the command line, so it will still not work. You do NOT want that, so you're going to avoid it by putting "-t" on the command line instead. While you're at it, add "-oi" too, to avoid having to end with a single dot on a line.

    my $sendmail = '/usr/sbin/sendmail -t -oi'; open MAIL, '|', $sendmail or die $!;

    Of course, best is to use one of the many existing mailing modules instead.

    U28geW91IGNhbiBhbGwgcm90MTMgY
    W5kIHBhY2soKS4gQnV0IGRvIHlvdS
    ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
    geW91IHNlZSBpdD8gIC0tIEp1ZXJk
    

Re: Contact Form 2
by cjf (Parson) on Mar 25, 2002 at 08:42 UTC

    Untested code using Mail::Sendmail to give you an idea why using a module is far better :)

    #!/usr/bin/perl -wT use strict; use CGI; use Mail::Sendmail; my $q = new CGI; my $name = $q->param("name"); my $email = $q->param("email"); my $message = $q->param("message"); # Config my $adminmail = "admin\@yoursite.com"; my $from = "whoever\@whatever.com"; my $subject = "enter subject here"; # End config my %mail = ( To => "$adminmail", From => "$from", Subject => "$subject", Message => "$message" ); sendmail(%mail) or die $Mail::Sendmail::error; print $q->redirect("thanks.html") or die "Can't find thanks.html: $!\n +";

    Update: You should include Juerd's improvements listed below.

      "$adminmail"

      "$foo" is often very bad style. Consider it equal to '' . $foo . '', and just write it without quotes instead. Also, using single quotes allows you to write @ signs without escaping them (style advice: use double quotes only if you use their's specialties (read perlop)).
      You use %mail just once, and could have put that in the sub itself.

      In my style, this script would be:

      #!/usr/bin/perl -w # Well, to be completely honest: I don't like CGI.pm, and wouldn't use + it. # I will for now, because I'm just rewriting :) # You may have noticed I removed the tainting checks too. use strict; use CGI; use Mail::Sendmail; my $q = CGI->new(); # Updated as per particle's excellent observation my $name = $q->param('name'); # Note: used only once my $email = $q->param('email'); # Note: only used once my $message = $q->param('message'); # # Note: couldn't choose ;) # Config my $adminmail = 'admin@yoursite.com'; my $from = 'whoever@whatever.com'; my $subject = 'enter subject here'; # End config sendmail( To => $adminmail, From => $from, Subject => $subject, Message => $message ) or die $Mail::Sendmail::error; # Note: redirects should be absolute # (All modern browsers handle relative redirects, though) print $q->redirect('thanks.html') or die "Can't find thanks.html: $!\n +";

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

        umm... am i missing something, or should that my $q = CGI->; actually have a method call on the end, like my $q = CGI->new();?

        ~Particle ;Þ

      Thanks Juerd! I do have one question for you. How do you specify the location of SENDMAIL in your version? I cannot see where you are actually telling it where it is, all you do is call sendmail. Thanks! sulfericacid
Re: Contact Form 2
by webadept (Pilgrim) on Mar 25, 2002 at 08:20 UTC
    First check that your path is correct to the sendmail. That's not the path to mine, and if you are typing this out of a book, its probably not the path your ISP has. Check.. make sure

    Second, check that the user you have sending the email exists on the sever. You have admin@yourhost.com Make sure "admin" is a user, most ISP's won't allow you to send email from a non-existant account, to keep spamming down.

    Third " or die" is a valid end to a program. Have it log something on the die, so you got some kind of message to refer to. Nothing is being returned, so debugging something like this will be a bear if you don't get some type of responce from the program that everything went well, or what might have gone wrong.

    I rarely use || die on cgi's .. I have them log or return an error code. This keeps things nice and simple to maintain later.

    Lastly.. I don't think those single quotes should be there. I'm not sure why they are there, and I would try removing them. Change
    print MAIL "Name: $formdata{'name'}\n"; print MAIL "email: $formdata{'email'}\n"; print MAIL "message: $formdata{'message'}\n";
    to this
    print MAIL "Name: $formdata{name}\n"; print MAIL "email: $formdata{email}\n"; print MAIL "message: $formdata{message}\n";


    Hope that helps.

    Glenn H.

      Lastly.. I don't think those single quotes should be there. I'm not sure why they are there, and I would try removing them.

      A hash key is a string, so it can be quoted. It's actually an exception to strict's strictness that you can do without quotes (only if it's a valid unquoted string, of course (/^\w+\z/). Same goes for =>'s left operand. Without strict, you can use unquoted strings everywhere (but don't drop strict, and don't use unquoted strings when not a hash key, or =>'s left operand).

      /me prefers literal hash keys quoteless.

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

Re: Contact Form 2
by erikharrison (Deacon) on Mar 25, 2002 at 18:41 UTC

    While we're at it, here is some general comments about your code:

    • You declare a global in a subroutine. This sort of loose coupling is a big no-no, because it makes subtle bugs, and makes code more confusing. Consider returning the hash
    • You then take the %formdata hash and after generating it say my %formdata. Apart from the fact that Globals R Bad, this is a extraneous construct. You can get rid of it.
    • As has been mentioned, use a module to handle the sending of mail. It's more complicated than it looks (and it looks complicated). The module will save you the headache.
    • There is no need to iterate through each param to build your hash. CGI.pm provides a method which will give you a hash straight off, and thus be more efficient and let you get rid of the sub all together.
    • You use strict. Nice. But you also might want to use warnings, and most definately turn on -T for tainting, to ensure that your programs stay secure. You should do this at least for EVERY CGI program you write.
    • I also just want to say that you've come a long way since your early work you asked everyone in th CB to bugcheck. keep learning.

      Cheers,
      Erik
Re: Contact Form 2
by talexb (Chancellor) on Mar 25, 2002 at 14:57 UTC
    You could also check out the NMS web scripts site for scripts that do what you want.

    Looking at production code that was written by experts and that already works can be most illuminating.

    --t. alex

    "Here's the chocolates, and here's the flowers. Now how 'bout it, widder hen, will ya marry me?" --Foghorn Leghorn