Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Sending HTML email and a slightly related 500 error

by FoncÚ (Scribe)
on May 15, 2003 at 18:27 UTC ( #258483=perlquestion: print w/replies, xml ) Need Help??

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

This is essentially a two-parter.

1. I've got a form that allows our salesmen to simply fill it out and then click send and it sends a copy to each the boss and the secretary. It also shoots a copy back at the salesman. The email addresses of the boss and secretary (and whoever else wants one, such as the owner) are stored in @cc and the email address of the salesman who is using the form comes from $FORM{user}. First problem is this: how can I change the following code so I can send an HTML email rather than plain text?

# Open The Mail open (MAIL, "|$mailprog -t") || &safe_die("Can't open $mailprog!\n"); print MAIL "From: $rn\n"; print MAIL "Reply-To: $uname\n"; print MAIL "To: $uname\n"; print MAIL "Subject: $FORM{'subject'}\n\n"; print MAIL "Below is the information submitted on $date\n"; print MAIL "------------------------------\n\n"; print MAIL qq~ *** omitting the irrelevant body stuff *** ~ close (MAIL);

2. The other problem is that, although with the code I'm posting below not all of the emails send. Then I get a 500 error instead of the "message sent" page to which it is supposed to go. Also, I'd like to get rid of the sloppiness of having two mail send routines since there's one for the array and one for the salesman (which is selected on the form). If I can get the array to work, I can just add to address from the form to it and use one routine only. Here's the relevant code:

$count = 0; foreach (@cc) { $count += 1; # Open The Mail open (MAIL, "|$mailprog -t") || &safe_die("Can't open $mailprog!\n"); print MAIL "From: $rn\n"; print MAIL "Reply-To: $uname\n"; print MAIL "To: $cc[$count]\n"; print MAIL "Subject: $FORM{'subject'}\n\n"; print MAIL "Below is the information submitted on $date\n"; print MAIL "-----------------------------\n\n"; print MAIL qq~ *** more irrelevant HTML *** ~ close (MAIL); }
I was thinking something along the lines of this:
foreach (@cc) { $count += 1; # Open The Mail open (MAIL, "|$mailprog -t") || &safe_die("Can't open $mailprog!\n"); print MAIL "From: $rn\n"; print MAIL "Reply-To: $uname\n"; print MAIL "To: $cc[$_]\n"; print MAIL "Subject: $FORM{'subject'}\n\n"; print MAIL "Below is the information submitted on $date\n"; print MAIL "-----------------------------\n\n"; print MAIL qq~ *** more irrelevant HTML *** ~ close (MAIL); }
...but that doesn't work. I'm not entirely sure if $_ is the number or the actual address being stored in the array, so...help, please?

FoncÚ

Replies are listed 'Best First'.
Re: Sending HTML email and a slightly related 500 error
by Jenda (Abbot) on May 15, 2003 at 18:50 UTC

    You could print the "MIME-version: 1.0\nContent-type: text/html\n" headers there and hope, but you'd really rather use a module. MIME::Lite or Mail::Sender would make sending the email much easier.

    Jenda
    Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
       -- Rick Osborne

    Edit by castaway: Closed small tag in signature

Re: Sending HTML email and a slightly related 500 error
by cees (Curate) on May 15, 2003 at 20:36 UTC

    Use the very excellent MIME::Entity module to create an HTML email message. The following bit of untested code will build a message with a 'multipart/mixed" content-type which will allow the mail client to decide if it wants to display HTML content or text content. Personally I never open HTML only email (it's almost guaranteed to be spam).

    use MIME::Entity; my $msg = MIME::Entity->build( Type => 'multipart/mixed', From => 'me\@domain.com', To => $recipient, Cc => \@cc, Subject => 'the subject', Encoding => '8bit', ); $msg->attach(Data => $text_message, Type => 'text/plain', Encoding => '8bit', ); $msg->attach(Data => $html_message, Type => 'text/html', Encoding => '8bit', ); ### Send it: open MAIL, "| /usr/sbin/sendmail -t -oi -oem" or die "open: $!"; $msg->print(\*MAIL); close MAIL;

    Also, if you are sending the same message to all recipients, why are you sending them out separately. Just send out one email to all of them at once. That is what the Cc header is for.

    One more note on your last question. You are mixing up the foreach syntax ( foreach (@array) ) with the for syntax ( for (my $i-0; $i < $max; $i++) ). With the foreach example $_ will contain the element that is in the array, not the index of the element. The following achieve the same result:

    my @data = ('one', 'two', 'three'); foreach (@data) { print "$_\n"; } for (my $i=0; $i < @data; $i++) { print "$data[$i]\n"; } __output__ one two three one two three
      Taking ideas from both of you, I rewrote the code and came up with the following, which does not work, but I assume is pretty close to doing so. Here's the programme in its entirety:
      #!/usr/bin/perl ####################################### # Custom Modified Form Mailer # Based on fmail.pl # All due credit hereby granted to original authors/editors # Created 7/8/02 Last Modified 5/14/03 # Version 3.22 ####################################### use MIME::Lite; MIME::Lite->send('sendmail', "/bin/sendmail"); ###################### # A date for those with no /bin/date # @junk = localtime(time); $date = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$junk[4]]; $junk[5] += 1900; $date .= "-" . $junk[3] . "-" . $junk[5]; $date .= " " . $junk[2] . ":" . $junk[1] . " EST"; $datafile = '/etc/hosts'; ###################### ######################## # A subroutine to die gracefully under html ######################## sub safe_die { print "Content-type: text/plain\n\n"; print @_,"\n"; exit(0); } read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); $finddomain = $ENV{'HTTP_REFERER'}; if ($finddomain eq "") { &safe_die("This script requires data via an HTML form. It can +not run independently."); } $finddomain = lc($finddomain); $finddomain =~ s/^http:\/\///; $finddomain =~ s/^www\.//; ($finddomain, $junk) = split(/\//, $finddomain, 2); &check_exists($finddomain); # Split the name-value pairs @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); # Un-Webify plus signs and %-encoding $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORM{$name} = $value; } ###### Dealing with the recipient and user's real name ###### $salesman = $FORM{user}; @sman[1] = "*** name of user ***"; @sman[2] = "*** name of user ***"; @addy[1] = 'mail@company.com'; @addy[2] = 'testmail@company.com'; #@addy[2] = 'realothermail@company.com'; $rn = $sman[$salesman]; $uname = $addy[$salesman]; ######## Send mail to the Salesman ######## $msg = MIME::Lite->new ( To =>'$uname', Cc =>'ccrecip@company.com', Subject =>$FORM{'subject'}, Type =>'multipart/mixed' ); $msg->attach(Type => 'text/html', Data => qq~ <html> <body> <table> <tr> <td width=500> <h3>Daily Salesman's Report</h3><br><br> Salesman: $rn<br><br> <table border=0> <tr> <td> Bakery:<br><br> Location: </td><td> <input name="bakery" value="$FORM{bakery}"><br><br> <input name="location" value="$FORM{location}"> </td> <td width=30> </td> <td> Date:<br><br> 1st Visit?: </td> <td> <input name="date" size=8 value="$FORM{date}"><br><br> <input name="visit" value="$FORM{visit}"> </td> </tr> <tr> <td>Contacts:</td> <td></td> <td></td> </tr> <tr> <td align=right> 1.<br> 2.<br> 3.<br> </td> <td> <input name="contact_1" value="$FORM{contact_1}"><br> <input name="contact_2" value="$FORM{contact_2}"><br> <input name="contact_3" value="$FORM{contact_3}"> </td> <td width=30> </td> <td colspan=2> In Office Use (Route to):<br> &nbsp;&nbsp;&nbsp;Sales <input type="radio" name="route_to" value="sa +les"> &nbsp;&nbsp;Acct <input type="radio" name="route_to" value="accountin +g"><br> &nbsp;&nbsp;&nbsp;Eng&nbsp;&nbsp;&nbsp;<input type="radio" name="route +_to" value="engineering"> &nbsp;&nbsp;Mfg&nbsp;&nbsp;<input type="radio" name="route_to" value= +"manufacturing"> </td> </tr> </table> Topics discussed:<br> <textarea wrap=physical name="topics_discussed" rows=8 cols=80 value=" +$FORM{topics_discussed}"></textarea> <br><br> Action Taken:<br> <textarea wrap=physical name="action_taken" rows=8 cols=80 value="$FOR +M{action_taken}"></textarea> <br><br> Action Needed:<br> <textarea wrap=physical name="action_needed" rows=8 cols=80 value="$FO +RM{action_needed}"></textarea> <br><br> Follow Up Needed:<br> <textarea wrap=physical name="follow_up" rows=8 cols=80 value="$FORM{f +olow_up}"></textarea> <br><br> Other:<br> <textarea wrap=physical name="first_visit_info" rows=8 cols=80 value=" +$FORM{first_visit_info}"></textarea> <hr> </td> </tr> </table> </body> </html> ~); $msg->send; ######## SUB for checking if domain exists ######## sub check_exists { $chkdomain = shift; $found = 0; open(DB, "<$datafile") || &safe_die("Cannot open data file"); while ($lin = <DB>) { chop($lin); ($rest,$tmpdomain) = split(/\s/, $lin, 3); $tmpdomain=~s/\s+//g; if ($tmpdomain eq $chkdomain) { $found = 1; last; } if ($chkdomain eq "https:") { $found = 1; last; } next; } close(DB); if ($found == 0) { &safe_die("$chkdomain Domain does not exist on this server"); } }
      Any ideas as to what's wrong? It passes a script checker as far as syntax and such.

      FoncÚ
        Define "doesn't work". That phrase is the most unhelpful thing you can ever say about a piece of code. What does it do that you didn't expect, or what doesn't it do that you expected?
            -- Jeff 'japhy' Pinyan <japhy@pobox.com>

        I've noticed you are parsing the CGI query/posted data yourself. You definitely should not. Sorry to say almost the same I said before again but ... please use a module. CGI, CGI::Lite, maybe even CGI::Deurl, but please do not use your own code for this.

        Jenda
        Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
           -- Rick Osborne

        Edit by castaway: Closed small tag in signature

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://258483]
Approved by Jenda
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (1)
As of 2023-03-21 18:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which type of climate do you prefer to live in?






    Results (60 votes). Check out past polls.

    Notices?