/[cvs]/cgi/mailback/mailback.pl

Contents of /cgi/mailback/mailback.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (hide annotations) (download)
Sun Feb 12 21:54:43 2006 UTC (4 years, 6 months ago) by erik
Branch: MAIN
Changes since 1.4: +2 -1 lines
File MIME type: text/plain
Sanitized subtag.
1 erik 1.1 #!/usr/local/bin/taintperl
2    
3 erik 1.5 # $Id: mailback.pl,v 1.5 2006/02/12 21:54:43 erik Exp $
4 erik 1.1 #
5     # Author: Erik C. Thauvin <erik@skytouch.com>
6     #
7     # Thanks to David Walker <dwalker@eskimo.com> and Robert Dinse
8     # <nanook@eskimo.com> for the great suggestions.
9     #
10     # This script will mail the content of any HTML form to its author.
11     #
12     # Based on "mailback.pl" by Phillip Moore <phil@erc.msstate.edu>
13     # Source available at http://www.erc.msstate.edu/~phil/src/mailback.pl
14     #
15     # Also based on "sendmail-cgi.pl" by Erik C. Thauvin <erik@skytouch.com>
16 erik 1.4 # Copyright (C) 1995-2006 Erik C. Thauvin. All rights reserved.
17 erik 1.1 #
18 erik 1.4 # Date: 2006-02-06
19 erik 1.1 #
20     # Usage: You must reference this script in your HTML forms with
21     # the method=POST option. Options are passed inside the
22     # the document with the input tag, as follows:
23     #
24     # <input name="variable-name" type="input-type" value="default-value">
25     #
26     # The variable-name represents parameters for this script.
27     # The following are reserved names used by the script and
28     # must be specified in your HTML documents/forms:
29     #
30     # mailitto (req) - Full internet mail address of mail recipient.
31     # This MUST be your email address on Eskimo.
32     #
33     # namefrom (req) - Name of the person the submission is from.
34     #
35     # mailfrom (req) - Email address of the person the submission
36     # is from.
37     #
38     # subject (req) - Subject of the email message.
39     #
40     # bcc - If defined, sends a blind carbon copy of the
41     # mail message to the person submitting the form.
42     #
43     # showreport - If defined, a mail status report is shown upon
44     # submission; otherwise a generic confirmation
45     # message is displayed.
46     #
47     # returngraphic - Inline image to be displayed at the bottom of
48     # the mail confirmation/status report.
49     #
50     # returntext - If "retrungraphic" is defined, the text is used
51     # as an alternate to the "returngraphic" for non-
52     # graphical browsers, such as lynx.
53     # If "returngraphic" is not defined, the text is
54     # displayed instead of the image.
55     #
56     # returnurl - The URL of "returngraphic" and/or "returntext".
57     # If not defined, the URL of the previous page is
58     # used.
59     #
60     # returnmsg - The actual confirmation message. If not defined,
61     # a generic message is used.
62     #
63     # returntitle - The confirmation message's title. If not defined,
64     # "Mail Confirmation" is used.
65     #
66     # returnpage - The URL of a custom "Mail Confirmation" page.
67     # Overrides "showreport", "returntext", "returnurl",
68     # "returngraphic", "returnmsg" and "returntitle".
69     #
70     # subtag - The name of one of the form's input tag. If valid,
71     # the tag's value will be affixed to the subject of
72     # the mail.
73     #
74     # bodytags - The HTML elements to be included in the <body> tag
75     # of the confirmation/error messages. Example:
76     #
77     # ... value="bgcolor=#FFFFFF vlink=#008000" ...
78     #
79     # base - The URL to be used in the <base> HTML tag of the
80     # confirmation/error messages.
81     #
82     # nozeros - Suppresses input tags whose values are 0.
83     #
84     # noblanks - Suppresses input tags whose values are blank.
85     #
86     # notags - Suppresses input tags from email message.
87     #
88     # senderinfo - Includes "namefrom" and "mailfrom" in the body
89     # of the email message.
90     #
91     # The ones with (req) are required but may be written into the HTML
92     # form so that users cannot change them. For example:
93     #
94     # <HTML>
95     # <TITLE>Mailback Sample Form</TITLE>
96     # <BODY>
97     # <FORM ACTION="http:/cgi-bin/mailback" METHOD="POST">
98     # <INPUT TYPE="HIDDEN" NAME="mailitto" VALUE="johndoe@eskimo.com">
99     # <INPUT TYPE="HIDDEN" NAME="returnurl" VALUE="/~johndoe/mypage.html">
100     # <INPUT TYPE="HIDDEN" NAME="returntext" VALUE="Back to my Home Page.">
101     # <INPUT TYPE="HIDDEN" NAME="notags">
102     # <INPUT TYPE="HIDDEN" NAME="showreport">
103     # Your Name: <INPUT TYPE="TEXT" NAME="namefrom" SIZE=35><BR>
104     # Your Email Address: <INPUT TYPE="TEXT" NAME="mailfrom" SIZE=35><BR>
105     # Subject: <INPUT TYPE="TEXT" NAME="subject" SIZE=35><P>
106     # Your Message:<BR>
107     # <TEXTAREA NAME="message" ROWS="10" COLS="60"></TEXTAREA><P>
108     # <INPUT TYPE="RESET" VALUE="Clear Form">
109     # <INPUT TYPE="SUBMIT" VALUE="Send Mail">
110     # </FORM>
111     # </BODY>
112     # </HTML>
113     #
114     # This software is provided "as is" without express or implied warranties.
115     #
116     # Permission is granted to use, copy, modify and distribute this software,
117     # provided this disclaimer and copyright are preserved on all copies. This
118     # software may not, however, be sold or distributed for profit, or included
119     # with other software which is sold or distributed for profit, without the
120     # permission of the author.
121     #
122    
123     $ENV{'PATH'} = '/bin:/usr/bin:/usr/lib';
124     $ENV{'IFS'} = '';
125    
126    
127     #
128     # Mail server address & port
129     #
130     $mailserv = 'mail.eskimo.com';
131     $mailport = 25;
132    
133    
134     #
135     # CRLF
136     #
137     $eol = "\015\012";
138    
139    
140     #
141     # Try SMTP?
142     #
143     $trysmtp = 0;
144    
145    
146     #
147     # Valid mail server hosts
148     #
149     @validhosts = ( 'eskimo.com', 'skytouch.com' );
150    
151    
152     #
153     # Print text/html error message
154     #
155     sub error
156     {
157     local($msg) = @_;
158    
159     &printheader('Error');
160     print "<h1><hr><font size=5>Error</font><hr></h1>\n<blockquote>\n$msg\n</blockquote>\n<p>\n";
161     &printfooter;
162     exit 1;
163     }
164    
165    
166     #
167     # Return error if mail could not be sent
168     #
169     sub mailerror
170     {
171     close(SOCK);
172     &error("An timeout error (ID=@_) occurred while sending mail. Please try "
173     . "again later or <a href=\"mailto:$posted{mailitto}\">notify</a> "
174     . "the creator of this page.\n<p>\n<p>\nThank you.");
175     }
176    
177    
178     #
179     # Print detailed text/html error message
180     #
181     sub notenoughinfo
182     {
183     local($msg) = @_;
184    
185     if ($infoerr == 0)
186     {
187     &printheader("Error");
188     print "<h1><hr><font size=5>Error</font><hr></h1>\n"
189     . "<h2>Not Enough Information:</h2>"
190     . "<blockquote>\n$msg\n</blockquote>\n";
191     }
192     else
193     {
194     print "<h3>And</h3>\n<blockquote>\n$msg\n</blockquote>\n";
195     }
196     $infoerr++;
197     }
198    
199    
200     #
201     # Print html header
202     #
203     sub printheader
204     {
205     local($title) = @_;
206    
207     print "Content-Type: text/html$eol$eol"
208     . "<html>\n<head>\n";
209    
210     if (defined($posted{base}))
211     {
212     print "<base href=\"$posted{base}\">\n";
213     }
214    
215     print "<title>$title</title>\n";
216    
217     if (defined($posted{bodytags}))
218     {
219     print "</head>\n<body $posted{bodytags}>\n";
220     }
221     else
222     {
223     print "</head>\n<body bgcolor=#ffffff>\n";
224     }
225     }
226    
227    
228     #
229     # Print html footer
230     #
231     sub printfooter
232     {
233     if (!defined($posted{skipRSLlink}))
234     {
235     print "<a href=\"http://www.skytouch.com/\"><img align=\"right\" alt=\"Designed by...\" src=\"http://www.skytouch.com/images/skytouch-mini.gif\" border=\"0\"></a>";
236     }
237     else
238     {
239     print "<a href=\"#\" onmouseover=\"window.status = 'Designed by SkyTouch Communications'; return(true);\"><img align=\"right\" alt=\"Designed by SkyTouch Communications\" src=\"http://www.skytouch.com/images/skytouch-mini.gif\"></a>";
240     }
241    
242     print "<hr>\n";
243    
244     if (defined($posted{returnurl}))
245     {
246     if (defined($posted{returngraphic}) && defined($posted{returntext}))
247     {
248     print "<a href=\"$posted{returnurl}\"><img src=\"$posted{returngraphic}\" alt=\"$posted{returntext}\"></a>\n";
249     }
250     elsif (defined($posted{returngraphic}))
251     {
252     print "<a href=\"$posted{returnurl}\"><img src=\"$posted{returngraphic}\"></a>\n";
253     }
254     elsif (defined($posted{returntext}))
255     {
256     print "<a href=\"$posted{returnurl}\">$posted{returntext}</a>\n";
257     }
258     else
259     {
260     print "Follow this <a href=\"$posted{returnurl}\">link</a> to continue.\n";
261     }
262     }
263     else
264     {
265     print "Back to the <a href=\"$ENV{HTTP_REFERER}\">previous</a> page.\n";
266     }
267    
268     print "</body>\n</html>";
269     }
270    
271    
272     #
273     # Get mail server result code
274     #
275     sub getresultcode
276     {
277     local($buff, $resultcode, $bits) = "";
278     local($timeout, $nbr) = 0;
279    
280     vec($bits, fileno(SOCK), 1) = 1;
281     LOOP: {
282     if ($timeout <= 2)
283     {
284     ($nfound, $bits) = select($bits, undef, undef, 3);
285     if ($nfound)
286     {
287     $nbr = sysread(SOCK, $buff, 1024);
288     if ($nbr > 0)
289     {
290     if (length($resultcode) < 3)
291     {
292     $resultcode .= substr($buff, 0, 3);
293     if ($resultcode == 220)
294     {
295     $timeout++;
296     redo LOOP;
297     }
298     }
299     if (substr($buff, -1, 1) ne "\012")
300     {
301     $timeout++;
302     redo LOOP;
303     }
304     }
305     }
306     else
307     {
308     $timeout++;
309     redo LOOP;
310     }
311     }
312     else
313     {
314     if ($resultcode != 220)
315     {
316     $resultcode = 554;
317     }
318     }
319     }
320     return $resultcode;
321     }
322    
323    
324     #
325     # Get host address
326     #
327     sub getaddress
328     {
329     local($host) = @_;
330     local(@addrs);
331    
332     @addrs = gethostbyname($host);
333     return(unpack("C4", $addrs[4]));
334     }
335    
336    
337     #
338     # Verify mail host validity
339     #
340     sub isvalidhost
341     {
342     local($email) = @_;
343     local($name, $host) = split('@', $email);
344    
345     foreach (@validhosts)
346     {
347 erik 1.2 if ( /$host/i )
348 erik 1.1 {
349     return 1;
350     }
351     }
352     return 0;
353     }
354    
355     #
356     # Ensure that the proper environment variables are defined
357     #
358     if (!defined($ENV{REQUEST_METHOD}) || $ENV{REQUEST_METHOD} ne "POST")
359     {
360     &error("This script should be referenced with a METHOD of POST. If you "
361     . "don't understand this, see the <a href=\"http://www.ncsa.uiuc.edu/SDG"
362     . "/Software/Mosaic/Docs/fill-out-forms/overview.html\">forms overview"
363     . "</a>.\n<p>\n<p>\nThank you.");
364     }
365    
366     #
367     # More environment variables
368     #
369     if (!defined($ENV{CONTENT_TYPE}) || $ENV{CONTENT_TYPE} ne "application/x-www-form-urlencoded")
370     {
371     &error("This script can only be used to decode form results.");
372     }
373    
374     #
375     # Read in the message based on the CONTENT_LENGTH in the header.
376     # If no CONTENT_LENGTH, complain about the error.
377     #
378     if (defined($ENV{CONTENT_LENGTH}) && $ENV{CONTENT_LENGTH} != 0)
379     {
380     $bytes = read(STDIN, $all, $ENV{CONTENT_LENGTH});
381     foreach $pair (split("&", $all))
382     {
383     ($key, $val) = split("=", $pair);
384     $val =~ tr/+/ /;
385     $val =~ s/%(..)/pack("c", hex($1))/eg;
386     # $val =~ s/\n/\n /g;
387    
388     if (defined($posted{$key}))
389     {
390     $posted{$key} = "$posted{$key}\n$val";
391     }
392     else
393     {
394     $posted{$key} = $val;
395     push(@keylist, $key) if ( $key ne "mailitto" &&
396     $key ne "errorsto" &&
397     $key ne "namefrom" &&
398     $key ne "mailfrom" &&
399     $key ne "subject" &&
400     $key ne "bcc" &&
401     $key ne "showreport" &&
402     $key ne "returnurl" &&
403     $key ne "returntext" &&
404     $key ne "returngraphic" &&
405     $key ne "skipRSLlink" &&
406     $key ne "returnmsg" &&
407     $key ne "returntitle" &&
408     $key ne "returnpage" &&
409     $key ne "subtag" &&
410     $key ne "bodytags" &&
411     $key ne "base" &&
412     $key ne "nozeros" &&
413     $key ne "noblanks" &&
414     $key ne "senderinfo" &&
415     $key ne "notags" );
416     }
417     }
418     }
419     else
420     {
421     &error("This script, the URL, or the fields given in the form returned "
422     . "an error. Please notify the creator of this page.\n<p>\n<p>\n"
423     . "Thank you.");
424     }
425    
426     #
427     # Check that each of the four required fields are entered properly
428     # Make sure user has entered "mailitto" , "mailfrom", "namefrom"
429     # and "subject"
430     #
431     ### To: ###
432     if (!defined($posted{mailitto}) || !&isvalidhost($posted{mailitto}))
433     {
434     &notenoughinfo("The creator of the form you are using failed to provide "
435     . "a valid e-mail address. Please try again later, or send "
436     . "mail to the person who created this form.<p>");
437     }
438    
439     ### From ###
440     if (!defined($posted{namefrom}) || $posted{namefrom} =~ /^\s*$/)
441     {
442     &notenoughinfo("Please provide your first and/or last name to help the "
443     . "reader of this message identify you.<p>");
444     }
445     else
446     {
447     $posted{namefrom} =~ s/^\s*//;
448     $posted{namefrom} =~ s/\s*$//;
449     }
450    
451     ### From: ###
452     if (!defined($posted{mailfrom}) ||
453     $posted{mailfrom} !~ /^[-._%!*\/+0-9A-Za-z]+@[-0-9A-Za-z.]+\.[A-Za-z][A-Za-z]+$/)
454     {
455     &notenoughinfo("Please provide a full internet mail address so the reader "
456     . "of this message may reply to you.<p>");
457     }
458     else
459     {
460     $posted{mailfrom} =~ s/^\s*//;
461     $posted{mailfrom} =~ s/\s*$//;
462     }
463    
464     ### Subject: ###
465     if (!defined($posted{subject}) || $posted{subject} =~ /^\s*$/)
466     {
467     &notenoughinfo("Please provide a subject to give the reader of this "
468     . "message some clue as to its content.<p>");
469     }
470     else
471     {
472     $posted{subject} =~ s/^\s*//;
473     $posted{subject} =~ s/\s*$//;
474 erik 1.4 $posted{subject} =~ s/(\r|\n)//g;
475 erik 1.1 }
476    
477     #
478     # As long as those four fields are non-empty, and in a valid format, send it
479     #
480     if ($infoerr > 0)
481     {
482     &printfooter;
483     exit 1;
484     }
485     else
486     {
487     #
488     # Connect to the mail server
489     #
490     local($sockaddr, $addr) = ("Snc4x8");
491     local($mailagent) = 'sendmail';
492    
493     if ($trysmtp)
494     {
495     $addr = pack($sockaddr, 2, $mailport, &getaddress($mailserv));
496    
497     if (socket(SOCK, 2, 1, 6))
498     {
499     if (connect(SOCK, $addr))
500     {
501     select(SOCK); $| = 1;
502     select(STDOUT); $| = 1;
503    
504 erik 1.3 if (&getresultcode == 220)
505 erik 1.1 {
506     $mailagent = 'smtp';
507     }
508     }
509     }
510     }
511    
512     #
513     # Send mail message
514     #
515     if ($mailagent eq 'sendmail')
516     {
517     close(SOCK);
518     open(SOCK, "| /usr/lib/sendmail -t");
519     }
520     else
521     {
522     print SOCK "HELO mailback$eol";
523     do { &mailerror(1200); } if (&getresultcode != 250);
524    
525     print SOCK "RSET$eol";
526     do { &mailerror(1300); } if (&getresultcode != 250);
527    
528     print SOCK "MAIL FROM:<>$eol";
529     do { &mailerror(1400); } if (&getresultcode != 250);
530    
531     print SOCK "RCPT TO:<$posted{mailitto}>$eol";
532     do { &mailerror(1500); } if (&getresultcode != 250);
533    
534     if (defined($posted{bcc}))
535     {
536     print SOCK "RCPT TO:<$posted{mailfrom}>$eol";
537     do { &mailerror(1500); } if (&getresultcode != 250);
538     }
539    
540     print SOCK "DATA$eol";
541     do { &mailerror(1600); } if (&getresultcode != 354);
542     }
543    
544     print SOCK "From: $posted{mailfrom} ($posted{namefrom})$eol"
545     . "To: $posted{mailitto}$eol";
546    
547     if (defined($posted{bcc}))
548     {
549     print SOCK "Bcc: $posted{mailfrom}$eol";
550     }
551    
552     if (defined($posted{$posted{subtag}}))
553     {
554 erik 1.5 $posted{$posted{subtag}} =~ s/(\r|\n)//g;
555 erik 1.1 print SOCK "Subject: $posted{subject} ($posted{$posted{subtag}})$eol";
556     }
557     else
558     {
559     print SOCK "Subject: $posted{subject}$eol";
560     }
561    
562 erik 1.4 if (defined($ENV{REMOTE_ADDR})) { print SOCK "X-Remote-Address: $ENV{REMOTE_ADDR}$eol"; }
563 erik 1.1 if (defined($ENV{REMOTE_HOST})) { print SOCK "X-Remote-Host: $ENV{REMOTE_HOST}$eol"; }
564     if (defined($ENV{REMOTE_IDENT})) { print SOCK "X-Remote-Ident: $ENV{REMOTE_IDENT}$eol"; }
565     if (defined($ENV{REMOTE_USER})) { print SOCK "X-Remote-User: $ENV{REMOTE_USER}$eol"; }
566     if (defined($ENV{HTTP_REFERER})) { print SOCK "X-URL: $ENV{HTTP_REFERER}$eol"; }
567 erik 1.3
568     print SOCK "X-Mailback-Agent: $mailagent$eol";
569 erik 1.1
570     if (defined($posted{senderinfo}))
571     {
572     if (defined($posted{notags}))
573     {
574     print SOCK "$eol$posted{namefrom}$eol"
575     . "$eol$posted{mailfrom}$eol";
576     }
577     else
578     {
579 erik 1.2 print SOCK "$eol--- Sender's Name ---$eol$posted{namefrom}$eol"
580     . "$eol--- Sender's Email Address ---$eol$posted{mailfrom}$eol";
581 erik 1.1 }
582     }
583    
584     foreach $key (@keylist)
585     {
586     $keyval = $posted{$key};
587    
588     if (!(defined($posted{noblanks}) && (length($keyval) == 0)))
589     {
590     $keyval =~ s/\012\.\015/\012\.\.\015/g;
591     $keyval =~ s/\012\.$/\012\.\./;
592    
593     if (!(defined($posted{nozeros}) && ($keyval eq "0")))
594     {
595     if (defined($posted{notags}))
596     {
597     print SOCK "$eol$keyval$eol";
598     }
599     else
600     {
601     print SOCK "$eol--- $key ---$eol$keyval$eol";
602     }
603     }
604     }
605     }
606    
607     print SOCK ".$eol";
608    
609     if ($mailagent eq 'smtp')
610     {
611     do { &mailerror(1700); } if (&getresultcode != 250);
612    
613     print SOCK "QUIT$eol";
614     }
615    
616     close(SOCK);
617     }
618    
619    
620     #
621     # If "returnpage" is defined...
622     #
623     if (defined($posted{returnpage}))
624     {
625     print "Location: $posted{returnpage}$eol$eol";
626     }
627     #
628     # If "showreport" is defined then show the mail report and have a link
629     # to return back to some page
630     #
631     elsif (defined($posted{showreport}))
632     {
633     &printheader("Mail Status Report");
634     print "<h1><hr><font size=5>Mail Status Report</font><hr></h1>\n\n<p>\n"
635     . "<b>From:</b> $posted{mailfrom} ($posted{namefrom})\n<br>\n"
636     . "<b>Sent To:</b> <a href=\"mailto:$posted{mailitto}\">"
637     . "$posted{mailitto}</a><br>\n";
638    
639     if (defined($posted{$posted{subtag}}))
640     {
641     print "<b>Subject:</b> $posted{subject} ($posted{$posted{subtag}})$eol";
642     }
643     else
644     {
645     print "<b>Subject:</b> $posted{subject}$eol";
646     }
647    
648     print "<blockquote>\n<pre>";
649    
650     foreach $key (@keylist)
651     {
652     $keyval = $posted{$key};
653    
654     if (!(defined($posted{noblanks}) && (length($keyval) == 0)))
655     {
656     $keyval =~ s/\&/\&amp\;/g;
657     $keyval =~ s/\</\&lt\;/g;
658     $keyval =~ s/\>/\&gt\;/g;
659    
660     if (!(defined($posted{nozeros}) && ($keyval eq "0")))
661     {
662     if (defined($posted{notags}))
663     {
664     print "$keyval\n";
665     }
666     else
667     {
668     print "$key: $keyval\n";
669     }
670     }
671     }
672     }
673     print "</pre></blockquote><h2>Thank You!</h2>\n";
674     &printfooter;
675     }
676     #
677     # If "showreport" is not defined then just show a message
678     # of confirmation and have a link to another page
679     #
680     else
681     {
682     if (defined($posted{returntitle}))
683     {
684     &printheader($posted{returntitle});
685     print "<h1><hr><font size=5>$posted{returntitle}</font><hr></h1>\n<p>\n";
686     }
687     else
688     {
689     &printheader("Mail Confirmation");
690     print "<h1><hr><font size=5>Mail Confirmation</font><hr></h1>\n<p>\n";
691     }
692    
693     if (defined($posted{returnmsg}))
694     {
695     print $posted{returnmsg};
696     }
697     else
698     {
699     print "<blockquote>\nYour message was sent to <b><a href=\"mailto:$posted{mailitto}\">"
700     . "$posted{mailitto}</a></b>\n</blockquote>\n<h2>Thank You!</h2>\n";
701     }
702     print "\n<p>\n";
703     &printfooter;
704     }
705 erik 1.4 exit 0;

Mail
ViewVC Help
cvs.thauvin.net
svn.thauvin.net
Powered by ViewVC 1.2-dev