/[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.4 - (show annotations) (download)
Mon Feb 6 18:03:49 2006 UTC (4 years, 7 months ago) by erik
Branch: MAIN
Changes since 1.3: +6 -5 lines
File MIME type: text/plain
Returns and newslines are now removed from the subject line.
1 #!/usr/local/bin/taintperl
2
3 # $Id: mailback.pl,v 1.4 2006/02/06 18:03:49 erik Exp $
4 #
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 # Copyright (C) 1995-2006 Erik C. Thauvin. All rights reserved.
17 #
18 # Date: 2006-02-06
19 #
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 if ( /$host/i )
348 {
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 $posted{subject} =~ s/(\r|\n)//g;
475 }
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 if (&getresultcode == 220)
505 {
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 print SOCK "Subject: $posted{subject} ($posted{$posted{subtag}})$eol";
555 }
556 else
557 {
558 print SOCK "Subject: $posted{subject}$eol";
559 }
560
561 if (defined($ENV{REMOTE_ADDR})) { print SOCK "X-Remote-Address: $ENV{REMOTE_ADDR}$eol"; }
562 if (defined($ENV{REMOTE_HOST})) { print SOCK "X-Remote-Host: $ENV{REMOTE_HOST}$eol"; }
563 if (defined($ENV{REMOTE_IDENT})) { print SOCK "X-Remote-Ident: $ENV{REMOTE_IDENT}$eol"; }
564 if (defined($ENV{REMOTE_USER})) { print SOCK "X-Remote-User: $ENV{REMOTE_USER}$eol"; }
565 if (defined($ENV{HTTP_REFERER})) { print SOCK "X-URL: $ENV{HTTP_REFERER}$eol"; }
566
567 print SOCK "X-Mailback-Agent: $mailagent$eol";
568
569 if (defined($posted{senderinfo}))
570 {
571 if (defined($posted{notags}))
572 {
573 print SOCK "$eol$posted{namefrom}$eol"
574 . "$eol$posted{mailfrom}$eol";
575 }
576 else
577 {
578 print SOCK "$eol--- Sender's Name ---$eol$posted{namefrom}$eol"
579 . "$eol--- Sender's Email Address ---$eol$posted{mailfrom}$eol";
580 }
581 }
582
583 foreach $key (@keylist)
584 {
585 $keyval = $posted{$key};
586
587 if (!(defined($posted{noblanks}) && (length($keyval) == 0)))
588 {
589 $keyval =~ s/\012\.\015/\012\.\.\015/g;
590 $keyval =~ s/\012\.$/\012\.\./;
591
592 if (!(defined($posted{nozeros}) && ($keyval eq "0")))
593 {
594 if (defined($posted{notags}))
595 {
596 print SOCK "$eol$keyval$eol";
597 }
598 else
599 {
600 print SOCK "$eol--- $key ---$eol$keyval$eol";
601 }
602 }
603 }
604 }
605
606 print SOCK ".$eol";
607
608 if ($mailagent eq 'smtp')
609 {
610 do { &mailerror(1700); } if (&getresultcode != 250);
611
612 print SOCK "QUIT$eol";
613 }
614
615 close(SOCK);
616 }
617
618
619 #
620 # If "returnpage" is defined...
621 #
622 if (defined($posted{returnpage}))
623 {
624 print "Location: $posted{returnpage}$eol$eol";
625 }
626 #
627 # If "showreport" is defined then show the mail report and have a link
628 # to return back to some page
629 #
630 elsif (defined($posted{showreport}))
631 {
632 &printheader("Mail Status Report");
633 print "<h1><hr><font size=5>Mail Status Report</font><hr></h1>\n\n<p>\n"
634 . "<b>From:</b> $posted{mailfrom} ($posted{namefrom})\n<br>\n"
635 . "<b>Sent To:</b> <a href=\"mailto:$posted{mailitto}\">"
636 . "$posted{mailitto}</a><br>\n";
637
638 if (defined($posted{$posted{subtag}}))
639 {
640 print "<b>Subject:</b> $posted{subject} ($posted{$posted{subtag}})$eol";
641 }
642 else
643 {
644 print "<b>Subject:</b> $posted{subject}$eol";
645 }
646
647 print "<blockquote>\n<pre>";
648
649 foreach $key (@keylist)
650 {
651 $keyval = $posted{$key};
652
653 if (!(defined($posted{noblanks}) && (length($keyval) == 0)))
654 {
655 $keyval =~ s/\&/\&amp\;/g;
656 $keyval =~ s/\</\&lt\;/g;
657 $keyval =~ s/\>/\&gt\;/g;
658
659 if (!(defined($posted{nozeros}) && ($keyval eq "0")))
660 {
661 if (defined($posted{notags}))
662 {
663 print "$keyval\n";
664 }
665 else
666 {
667 print "$key: $keyval\n";
668 }
669 }
670 }
671 }
672 print "</pre></blockquote><h2>Thank You!</h2>\n";
673 &printfooter;
674 }
675 #
676 # If "showreport" is not defined then just show a message
677 # of confirmation and have a link to another page
678 #
679 else
680 {
681 if (defined($posted{returntitle}))
682 {
683 &printheader($posted{returntitle});
684 print "<h1><hr><font size=5>$posted{returntitle}</font><hr></h1>\n<p>\n";
685 }
686 else
687 {
688 &printheader("Mail Confirmation");
689 print "<h1><hr><font size=5>Mail Confirmation</font><hr></h1>\n<p>\n";
690 }
691
692 if (defined($posted{returnmsg}))
693 {
694 print $posted{returnmsg};
695 }
696 else
697 {
698 print "<blockquote>\nYour message was sent to <b><a href=\"mailto:$posted{mailitto}\">"
699 . "$posted{mailitto}</a></b>\n</blockquote>\n<h2>Thank You!</h2>\n";
700 }
701 print "\n<p>\n";
702 &printfooter;
703 }
704 exit 0;

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