Contents of file 'emailform.php':
1 <?php
2 //============================================================================
3 // File: emailform.php [PHP script]
4 // Created: April 29, 2006 [v.1.0]
5 // Last change: April 22, 2009 [v.1.26]
6 // Author: Fredrik Jonsson <http://jonsson.eu/>
7 //
8 // DESCRIPTION
9 // The EMAILFORM script generates (X)HTML code for a form for delivering
10 // messages as emails. The parameters supplied via the fields of the form
11 // are posted by the script to itself, in the second run performing tasks
12 // as spam checking etc., hence providing a self-consistent and simple way
13 // of handling checking of user input and guidance messages. The script
14 // employs either an intrinsic sendmail functionality, such as in Apache
15 // servers shipped natively with Apple's OS X, or the SMTP mail instance of
16 // the PEAR extension of PHP. Currently, the script supports dynamic switching
17 // between two languages: English (default) and Swedish. In order to provide
18 // headers, labels or help messages in other languages, a few easily
19 // identifiable strings in the code need to be translated into the desired
20 // language.
21 // Before sending any message, the EMAILFORM script constructs a simple
22 // test form which the user needs to pass, in order to separate real user
23 // from web crawlers and robots. This way the spam is considerably reduced,
24 // if not to say entirely eliminated.
25 // In addition to merely sending email messages, the script also performs
26 // checks to determine whether the message is to be considered as spam or
27 // not, and in the footer of the sent emails, a link for looking up the
28 // sender's IP address in the RIPE.net whois server is provided. Typically,
29 // this feature is useful for identifying addresses behind malicious intrusion
30 // or spam attempts.
31 // The (X)HTML code generated by the EMAILFORM script conforms to the
32 // XHTML 1.0 Strict specification. According to the XHTML 1.0 Strict document
33 // type definition (DTD) no <input> elements are allowed as direct descendants
34 // within <form> block, for some strange reason. Therefore, any <input> block
35 // is here wrapped up within a <p> (paragraph) block, in spite of that some of
36 // the <input> being hidden. The wrapping within <p> blocks is here a bit odd,
37 // as the <input> blocks clearly have a place within <form>, while the <input>
38 // blocks hardly could be considered as paragraphs. The only reason for this
39 // construction, as far as I have found it, is to make the code pass the XHTML
40 // 1.0 Strict validation, which it clearly does.
41 //
42 // PARAMETERS
43 // The user-end interface to the routines included in the group of scripts
44 // of the EMAILFORM is the function emailform ($lang), listed at the very end
45 // of emailform.php. The $lang parameter input to this function specifies
46 // which language to use for headers, help messages etc. Currently only two
47 // choices are valid: $lang="en" (English) or $lang="sv" (Swedish).
48 //
49 // CONFIGURATION
50 // In the emailform($lang) function, there are a few settings which need to be
51 // modified in order to configure EMAILFORM to operate properly on your web
52 // particular server. These parameters determine the way EMAILFORM reponds to
53 // user input and how it delivers the messages.
54 //
55 // The following variables determine the required fields of the form,
56 // to which additional checks will be applied before any email is sent.
57 // Each field can be individually enabled or disabled as required.
58 //
59 // First of all, define which fields to display at all. Any of these boolean
60 // switches which take the value "false" will prohibit the respective field
61 // to be displayed. As for my personal opinion, I think that the "Subject"
62 // field is rather silly, but some users may consider it useful anyway, since
63 // it is a quite revealing indicator of any spam that may have slipped through
64 // the check.
65 //
66 // $DO_DISPLAY_SENDERS_NAME_FIELD A Boolean parameter that determines
67 // whether to display the "Your name:"
68 // field or not. Recommended setting: true.
69 //
70 // $DO_DISPLAY_SENDERS_EMAIL_FIELD A Boolean parameter that determines
71 // whether to display the "Your email:"
72 // field or not. Recommended setting: true.
73 //
74 // $DO_DISPLAY_SUBJECT_FIELD A Boolean parameter that determines
75 // whether to display the "Subject:"
76 // field or not. Recommended setting:
77 // false. (The subject is rather clear
78 // anyway in the usually short messages
79 // delivered via web forms.)
80 //
81 // Next, the following parameters determine the required fields of the form,
82 // to which additional checks will be applied before any email is sent.
83 // In other words, these parameters determine which of the fields that
84 // will be considered as essential information to allow the message to be
85 // delivered. Again, my personal opinion is that the senders email address
86 // always should be required, but that empty name fields or empty message
87 // bodies should be allowed.
88 //
89 // Notice: Any field that has been disabled for display, by any of the
90 // above set parameters, will be unaffected by the corresponding
91 // "*_*_REQUIRED"-switches below, as the "required-field"-check
92 // is applied _only_ to those fields which actually are displayed.
93 // Neat and simple, huh?
94 //
95 // $SENDER_NAME_REQUIRED A Boolean parameter that determines whether
96 // anyone using the email form should be required
97 // to supply his/her name in the assigned field.
98 // Recommended setting: false.
99 //
100 // $SENDER_EMAIL_REQUIRED A Boolean parameter that determines whether
101 // anyone using the email form should be required
102 // to supply his/her email address (return address)
103 // in the assigned field. Recommended setting: true.
104 //
105 // $SUBJECT_REQUIRED A Boolean parameter that determines whether
106 // anyone using the email form should be required
107 // to supply a subject for the message in the
108 // assigned field. Recommended setting: false.
109 //
110 // $MESSAGE_REQUIRED A Boolean parameter that determines whether
111 // anyone using the email form should be required
112 // to supply a non-empty message in the assigned
113 // field. Recommended setting: false.
114 //
115 // $RECIPIENT The email address of recipient to which the
116 // messages are to be sent. Typically this string
117 // is of the form "My Name <me@mydomain.com>".
118 // Otherwise, just a plain email address of the
119 // form "me@mydomain.com" will do fine.
120 //
121 // $USE_PEAR_SMTP_SENDMAIL Boolean parameter which determines whether to
122 // use PEAR sendmail agent or not. Set to 'true'
123 // if using PEAR mail agent, otherwise 'false'.
124 //
125 // $NOTIFY_ON_SPAM_ATTEMPTS Determines whether spam attempts should cause
126 // a notification to be sent to the recipient.
127 // Set to 'true' to notify on spam attempts,
128 // otherwise 'false' (recommended).
129 //
130 // $PASSCODE_SEED As a final check before submitting any email,
131 // the EMAILFORM script will generate (X)HTML code
132 // for a simple addition test to be passed by the
133 // user. This test will automatically construct the
134 // two terms to be added from the $PASSCODE_SEED,
135 // being a number which may be chosen arbitrarily.
136 //
137 // If $USE_PEAR_SMTP_SENDMAIL is set to 'true', then we also need to set the
138 // following parameters, to be supplied to the PEAR mail agent. In case you
139 // wonder about how the PEAR mail agent delivers email, or if you simply wish
140 // to download the latest PEAR::Mail agent, please visit the PEAR repository
141 // at http://pear.php.net/package/Mail. Otherwise, if simply using a native
142 // sendmail agent, the following parameters can be safely ignored.
143 //
144 // $PEAR_SMTP_SENDMAIL_HOST The host to use when sending SMTP
145 // email. This is typically a server
146 // of the form "mail.some.server.com"
147 //
148 // $PEAR_SMTP_SENDMAIL_PORT The port to use at the server side
149 // when sending the message. Typically,
150 // this parameter seems to be set to 25
151 // by most web hosts as default, but is
152 // admittedly a highly non-standard
153 // parameter.
154 //
155 // $PEAR_SMTP_SENDMAIL_AUTHENTICATION A Boolean parameter, which if set
156 // to 'true' will provide a user ID
157 // and password to the SMTP agent when
158 // sending the email (as required by
159 // some Internet Service Providers).
160 //
161 // $PEAR_SMTP_SENDMAIL_USERNAME The user name (ID) to use when
162 // authenticating the send request at
163 // the SMTP agent.
164 //
165 // $PEAR_SMTP_SENDMAIL_PASSWORD The password to use when authentica-
166 // ting the send request at the SMTP
167 // agent.
168 //
169 // Finally, a setup which you (unfortunately) most likely will have to modify
170 // over time is how EMAILFORM should be triggered on spam attempts. For this
171 // purpose, there are two arrays of strings which contain words which should
172 // cause a message to be considered as spam if any specific words appear in
173 // the message text (determined by the array $SPAM_TRIGGERS_IN_MESSAGE) and
174 // in the address of the sender (determined by the array
175 // $SPAM_TRIGGERS_IN_ADDRESS).
176 //
177 // IMPORTANT NOTICE: By disabling the requirement on the email address
178 // to be specified (that is to say, with $required["email"]=false;),
179 // any check on the correctness or validity of the email field is also
180 // disabled. This leaves the field open for malicious attempts of mail
181 // spamming by the well-known "CC: " injection approach in the text
182 // supplied in the email field, which could be exploited for unsolicited
183 // en-masse email submissions. Hence it is STRONGLY RECOMMENDED that you
184 // below keep $required["email"]=true, just to be on the safe side.
185 // When using PEAR::Mail as the email agent in the EMAILFORM script, a check
186 // will indeed always be performed for any malicious attempts of "CC: " or
187 // "BCC: " injection, but I give no warranty that all possible security
188 // holes are covered.
189 //
190 // See, for example, http://www.w3schools.com/php/php_secure_mail.asp
191 // for a more detailed explanation of this particular security hole.
192 //
193 // Copyright (C) 2006-2009, Fredrik Jonsson <http://jonsson.eu/>
194 // Non-commercial copying welcome.
195 //============================================================================
196 //
197 // ###########################################################################
198 // ######## CUSTOMIZE THE FOLLOWING PARAMETERS WITH YOUR OWN SETTINGS ########
199 // ######## FOR DETAILS, SEE CONFIG INSTRUCTIONS IN THE HEADER ABOVE #########
200 // ###########################################################################
201 //
202 // First of all, define which fields to display at all. Any of these boolean
203 // switches which take the value "false" will prohibit the respective field
204 // to be displayed. As for my personal opinion, I think that the "Subject"
205 // field is rather silly, but some users may consider it useful anyway, since
206 // it is a quite revealing indicator of any spam that may have slipped through
207 // the check.
208 //
209 $DO_DISPLAY_SENDERS_NAME_FIELD=true; // Display "Your name:" field if true
210 $DO_DISPLAY_SENDERS_EMAIL_FIELD=true; // Display "Your email:" field if true
211 $DO_DISPLAY_SUBJECT_FIELD=false; // Display "Subject:" field if true
212
213 //
214 // Next, define a few parameters which determine which of the fields that
215 // will be considered as essential information to allow the message to be
216 // delivered. Again, my personal opinion is that the senders email address
217 // always should be required, but that empty name fields or empty message
218 // bodies should be allowed.
219 //
220 // Notice: Any field that has been disabled for display, by any of the
221 // above set parameters, will be unaffected by the corresponding
222 // "*_*_REQUIRED"-switches below, as the "required-field"-check
223 // is applied only to those fields which actually are displayed.
224 // Neat and simple, huh?
225 //
226 $SENDER_NAME_REQUIRED=false; // True if name of sender is required
227 $SENDER_EMAIL_REQUIRED=true; // True if reply-email of sender is required
228 $SUBJECT_REQUIRED=false; // True if subject field is required
229 $MESSAGE_REQUIRED=false; // True if non-empty message body is required
230
231 //
232 // Define the recipient email address of the messages that are to be
233 // delivered. Usually, the recipient address is the one you check as
234 // your regular address. Notice that this address is "safe" in the
235 // sense that it will never be displayed to the outside, as it always
236 // is hidden by the PHP server. (This is, of course, one of the major
237 // reasons why one would like to have an email form in the first place,
238 // rather than an explicitly displayed email address which immediately
239 // will be taken hostage by spam robots visiting the page.) See further
240 // parameters below configuring the _delivering_ agent.
241 //
242 $RECIPIENT="My Name <me@mydomain.com>"; // Address of recipient
243
244 //
245 // The boolean $NOTIFY_ON_SPAM_ATTEMPTS switch determines whether to inform
246 // the mail recipient (as set by the previous $RECIPIENT parameter) or not
247 // on that a spam attempt has been detected. The default is "false", as I
248 // personally do not care how many attempts per day that were caught.
249 // However, notice that regardless of whether the recipient is informed
250 // or not, the person or agent sending the spam will never be notified
251 // on that the mail has been detected as spam. From his/her/its own
252 // perspective, all will just look as if the message has been delivered.
253 // The useful thing with this behaviour of the EMAILFORM script is that
254 // selective evolution then never reaches the spam deliverers, as no
255 // feedback on success or failure will be supplied.
256 //
257 $NOTIFY_ON_SPAM_ATTEMPTS=false; // Set to 'true' to notify on spam attempts
258
259 //
260 // The boolean $USE_PEAR_SMTP_SENDMAIL switch determines whether to use
261 // the PEAR::Mail SMTP agent for delivering mail or not. If set to "false",
262 // the EMAILFORM script will assume that a local sendmail agent has been
263 // properly set up instead. My recommendation is to use PEAR::Mail whenever
264 // possible.
265 //
266 // IMPORTANT: FOR SOME REASON, PEAR SEEMS NOT TO BE PRESENT IN THE APACHE
267 // SERVER AT CRYSTONE.NET. CHECK THIS WITH THEIR SUPPORT ASAP!
268 //
269 $USE_PEAR_SMTP_SENDMAIL=false; // Set to 'true' if using the PEAR mail agent
270
271 //
272 // If $USE_PEAR_SMTP_SENDMAIL is set to 'true' above, then we also need to
273 // set the following parameters, to be supplied to the PEAR mail agent.
274 // Otherwise, if using a native sendmail agent of the server, these
275 // parameters will be ignored.
276 //
277 $PEAR_SMTP_SENDMAIL_HOST="my.mailserver.com";
278 $PEAR_SMTP_SENDMAIL_PORT="12345";
279 $PEAR_SMTP_SENDMAIL_AUTHENTICATION=true;
280 $PEAR_SMTP_SENDMAIL_USERNAME="me@mydomain.com";
281 $PEAR_SMTP_SENDMAIL_PASSWORD="my_password_goes_here";
282
283 //
284 // Define the seed to be used in generation of the passcode verification of
285 // the user.
286 //
287 $PASSCODE_SEED=1912;
288
289 //
290 // Define various triggers for detecting spam and other malicious email.
291 // Notice that the listed strings only need to match any substring of the
292 // respective message body or address, hence, for example, "porn" will
293 // catch spam containing "porn" as well as "pornography" or any other
294 // variation. In other words, all strings could be considered to be stated
295 // as wild-card patterns of the form "*<teststring>*". Also notice that the
296 // check for spam is performed in a case-insensitive way, hence there is
297 // no need to add anything else than lower-cased words.
298 //
299 $SPAM_TRIGGERS_IN_ADDRESS= // Strings searched for in senders email address
300 array("mail.ru","sddir.info","inbox.ru","xlqrn.com","sucks.org","yaahoo.com",
301 "hnsuqef.com","vmvip.net","autogid.org","hjphrti.com","blonechka","mymail",
302 "stylebrand","xsecurity","inbox.lv");
303 $SPAM_TRIGGERS_IN_MESSAGE= // Strings searched for in message text
304 array("</a>","[/url","[link","xxx","porn","viagra","ringtone","nude",
305 "sepcn.info","101freehost.com","mastur","webmelia.com","casino","adult",
306 "steroid","hostonmars","zelmira.cn","zoomers.cn","zotth.cn","zubba",
307 "prozac","dihydrotestosterone","sex","cardura","drug","xanax","diet pill",
308 "cyberspeed","holipin","freezoka","pillz","drug","techzero","cornel.biz",
309 "cannabis","windowsblinds","phentermine","carpetcleaner");
310 //
311 // ###########################################################################
312 // ######## END OF USER CUSTOMIZABLE PARAMETERS ##############################
313 // ###########################################################################
314 //
315
316 //
317 // The spamcheck($address) function takes an email address $address as input
318 // and checks whether the address contains the "to:" or "cc:" substrings,
319 // which are classical approaches of malicious exploitation of mail forms for
320 // en-masse submissions of spam email. The spamcheck($address) function is
321 // adopted from the example of secure PHP forms for email as explained in
322 // detail at http://www.w3schools.com/php/php_secure_mail.asp.
323 //
324 // On return, the spamcheck() function returns 'true' if a potential attempt
325 // of spamming was detected, and 'false' otherwise.
326 //
327 // Note: The eregi() function in this routine performs a case insensitive
328 // regular expression match, hence any variants such as "to:", "TO:" or "To:"
329 // etc. will be detected as well.
330 //
331 function spamcheck($address) {
332 if (eregi("to:",$address)||eregi("cc:",$address)||eregi("bcc:",$address)) {
333 return true;
334 } else {
335 return false;
336 }
337 }
338
339 //
340 // The leaveMessageHeader($lang) function displays the header of the message
341 // form, with $lang determining which language to use.
342 //
343 function leaveMessageHeader($lang) {
344 switch ($lang) {
345 case en:
346 echo " <h2>Leave a message</h2>\n";
347 break;
348 case sv:
349 echo " <h2>Lämna ett meddelande</h2>\n";
350 break;
351 default:
352 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
353 }
354 return;
355 }
356
357 //
358 // The fromNameFieldIsOK($required) checks that the supplied sender's name
359 // is alright (if required) and returns 'true' if this is the case; otherwise
360 // 'false' is returned.
361 //
362 function fromNameFieldIsOK($required) {
363 if ($required["name"]==true) {
364 if (trim($_REQUEST["name"])=="") {
365 return false;
366 } else {
367 return true;
368 }
369 } else {
370 return true;
371 }
372 }
373
374 //
375 // The fromNameField($lang,$required,$keepTextFields) function generates the
376 // name field, with $lang determining the language to use ("en" or "sv"),
377 // $required['name'] whether the user input in this field is required for
378 // sending the message, and $keepTextFields being a Boolean parameter which
379 // determines if any previously entered data should be maintained in the
380 // field as it is re-displayed (for example at the stage when any of the
381 // required user-supplied has been found to contain errors).
382 //
383 function fromNameField($lang,$required,$keepTextFields) {
384 //
385 // Normally when you have a form with several text input fields, it is
386 // undesirable that the form gets submitted when the user hits ENTER in
387 // a field. People often do that by accident or because they are accustomed
388 // to terminate field input that way. The send button can easily be disabled
389 // using the following lines of Javascript:
390 // <script type="text/javascript">
391 // function noenter() {
392 // return !(window.event && window.event.keyCode == 13);
393 // }
394 // </script>
395 // If you want the ENTER key to be disabled while an input field is active,
396 // then set the $prevent_enter_from_submitting parameter below to true, and
397 // include the above function in your (X)HTML header. This Javascript has
398 // been tested and found to work in Safari, IE6, Opera, Firefox and Mozilla.
399 //
400 $prevent_enter_from_submitting=true;
401 switch ($lang) {
402 case en:
403 echo " <p class=\"fieldLabel\">Your name:";
404 if ($required["name"]==true) echo " (required)";
405 echo "</p>\n";
406 break;
407 case sv:
408 echo " <p class=\"fieldLabel\">Ditt namn:";
409 if ($required["name"]==true) echo " (obligatoriskt)";
410 echo "</p>\n";
411 break;
412 default:
413 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
414 }
415 //
416 // When generating the code for the input field, we perform a check to
417 // see if the field has been previously set (for example prior to an
418 // email send event), in which case the previously used text will be
419 // set as the default for the current field. This is just to avoid the
420 // surprisingly common behaviour of web forms that automatically erase
421 // previously entered data if any of the fields contain incorrect data.
422 //
423 echo " <p><input name=\"name\" id=\"FromName\" ";
424 if ($keepTextFields==true) {
425 if (isset($_REQUEST["name"]))
426 echo "value=\"".$_REQUEST["name"]."\" ";
427 }
428 if ($prevent_enter_from_submitting) echo "onkeypress=\"return noenter()\" ";
429 echo "type=\"text\" /></p>\n";
430 $num_fielderrors=0;
431 if (isset($_REQUEST['email'])) {
432 if (fromNameFieldIsOK($required)!=true) {
433 $num_fielderrors=1;
434 echo " <p class=\"emailFormFieldError\"><i>";
435 switch ($lang) {
436 case en:
437 echo "Please supply your name.";
438 break;
439 case sv:
440 echo "Vänligen fyll i ditt namn.";
441 break;
442 default:
443 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
444 }
445 echo "</i></p>\n";
446 }
447 }
448 return($num_fielderrors);
449 }
450
451 //
452 // The validEmailAddress($required) checks that the supplied email address
453 // of the sender is alright (if required, as determined by the Boolean
454 // parameter $required['email']) and returns 'true' if this is the case;
455 // otherwise 'false' is returned.
456 //
457 // In checking whether the supplied email address is reasonable or not, the
458 // following syntax of the address string is assumed:
459 //
460 // {Proper address} = {An arbitrary string of letters, numbers,
461 // periods (.) or underscores (_)}
462 // @{An arbitrary string of letters, numbers,
463 // periods (.) or underscores (_)}
464 // .{An arbitrary string of letters}
465 //
466 // where the letters arbitrarily may be of lower- or uppercase. The function
467 // also checks for any attempts of "CC:-injection" of the mail header, in
468 // order to prevent that the script (when uploaded onto a web server) is
469 // used in relaying of spam mail. As examples of valid and invalid email
470 // addresses, as recognized by the EMAILFORM script, consider the following
471 // table of return values of the validEmailAddress() function:
472 //
473 // Email address Return value of function
474 // someone@example.com true
475 // someone@example,com false (illegal ',' in domain name)
476 // someone@example false (no '.' in domain name; no top domain)
477 // someone@example.com3 false (top domain names do not contain numbers)
478 // someone@example3.com true
479 // someone@next.example.com true
480 // someone.else@example.com true
481 // someone_else@example.com true
482 // someone:else@example.com false (illegal character ':' in name)
483 // somecc:one@example.com false (caught also in spam check for "cc:")
484 //
485 function validEmailAddress($required) {
486 if ($required["email"]==true) {
487 $address=$_REQUEST["email"]; // Load the supplied email address.
488 $address=stripslashes(trim($address));
489 //
490 // First we check if the supplied email address contains "to:", "cc:"
491 // or "bcc:" substrings, which is a classic approach of malicious
492 // exploitation of mail forms for en-masse submissions of spam email.
493 // This check is adopted from the example of secure PHP forms for email
494 // as explained at http://www.w3schools.com/php/php_secure_mail.asp.
495 //
496 // Note: The eregi() function in this routine performs a case insensitive
497 // regular expression match, hence any variants such as "to:", "TO:" or
498 // "To:" etc. will be detected as well.
499 //
500 if (eregi("to:",$address)||eregi("cc:",$address)||eregi("bcc:",$address)) {
501 return false;
502 }
503 if (!eregi('^[[:alnum:]][a-z0-9_\.\-]*@[a-z0-9\.\-]+\.[a-z]{2,4}$',
504 $address)) {
505 return false;
506 } else {
507 return true;
508 }
509 }
510 }
511
512 //
513 // The fromEmailField($lang,$required,$keepTextFields) function generates
514 // the email field, to contain the sender's email address, with $lang
515 // determining the language to use ("en" or "sv"), $required['email']
516 // whether the user input in this field is required for sending the
517 // message, and $keepTextFields being a Boolean parameter which determines
518 // if any previously entered data should be maintained in the field as it
519 // is re-displayed (for example at the stage when any of the required
520 // user-supplied has been found to contain errors).
521 //
522 function fromEmailField($lang,$required,$keepTextFields) {
523 //
524 // For a description of the $prevent_enter_from_submitting parameter, see
525 // the fromNameField() function above.
526 //
527 $prevent_enter_from_submitting=true;
528 switch ($lang) {
529 case en:
530 echo " <p class=\"fieldLabel\">Your email:";
531 if ($required["email"]==true) echo " (required)";
532 echo "</p>\n";
533 break;
534 case sv:
535 echo " <p class=\"fieldLabel\">Din epost-adress:";
536 if ($required["email"]==true) echo " (obligatorisk)";
537 echo "</p>\n";
538 break;
539 default:
540 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
541 }
542 //
543 // When generating the code for the input field, we perform a check to
544 // see if the field has been previously set (for example prior to an
545 // email send event), in which case the previously used text will be
546 // set as the default for the current field. This is just to avoid the
547 // surprisingly common behaviour of web forms that automatically erase
548 // previously entered data if any of the fields contain incorrect data.
549 //
550 echo " <p><input name=\"email\" id=\"FromEmail\" ";
551 if ($keepTextFields==true) {
552 if (isset($_REQUEST["email"]))
553 echo "value=\"".$_REQUEST["email"]."\" ";
554 }
555 if ($prevent_enter_from_submitting) echo "onkeypress=\"return noenter()\" ";
556 echo "type=\"text\" /></p>\n";
557 $num_fielderrors=0;
558 if (isset($_REQUEST['email'])) {
559 if (validEmailAddress($required)!=true) {
560 $num_fielderrors=1;
561 echo "<p class=\"emailFormFieldError\"><i>";
562 switch ($lang) {
563 case en:
564 echo "Please supply your email address.";
565 break;
566 case sv:
567 echo "Vänligen fyll i din epost-adress.";
568 break;
569 default:
570 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
571 }
572 echo "</i></p>\n";
573 }
574 }
575 return($num_fielderrors);
576 }
577
578 //
579 // The subjectFieldIsOK($required) checks that the supplied subject
580 // is alright (if required) and returns 'true' if this is the case;
581 // otherwise 'false' is returned.
582 //
583 function subjectFieldIsOK($required) {
584 if ($required["subject"]==true) {
585 if (trim($_REQUEST["subject"])=="") {
586 return false;
587 } else {
588 return true;
589 }
590 } else {
591 return true;
592 }
593 }
594
595 //
596 // The subjectField($lang,$required,$keepTextFields) function generates
597 // the subject field, with $lang determining the language to use ("en"
598 // or "sv"), $required['subject'] whether the user input in this field
599 // is required for sending the message, and $keepTextFields being a
600 // Boolean parameter which determines if any previously entered data
601 // should be maintained in the field as it is re-displayed (for example
602 // at the stage when any of the required user-supplied has been found to
603 // contain errors).
604 //
605 function subjectField($lang,$required,$keepTextFields) {
606 //
607 // For a description of the $prevent_enter_from_submitting parameter, see
608 // the fromNameField() function above.
609 //
610 $prevent_enter_from_submitting=true;
611 switch ($lang) {
612 case en:
613 echo " <p class=\"fieldLabel\">Subject:";
614 if ($required["subject"]==true) echo " (required)";
615 echo "</p>\n";
616 break;
617 case sv:
618 echo " <p class=\"fieldLabel\">Ämne:";
619 if ($required["subject"]==true) echo " (obligatoriskt)";
620 echo "</p>\n";
621 break;
622 default:
623 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
624 }
625 //
626 // When generating the code for the input field, we perform a check to
627 // see if the field has been previously set (for example prior to an
628 // email send event), in which case the previously used text will be
629 // set as the default for the current field. This is just to avoid the
630 // surprisingly common behaviour of web forms that automatically erase
631 // previously entered data if any of the fields contain incorrect data.
632 //
633 echo " <p><input name=\"subject\" id=\"Subject\" ";
634 if ($keepTextFields==true) {
635 if (isset($_REQUEST["subject"]))
636 echo "value=\"".$_REQUEST["subject"]."\" ";
637 }
638 if ($prevent_enter_from_submitting) echo "onkeypress=\"return noenter()\" ";
639 echo "type=\"text\" /></p>\n";
640 $num_fielderrors=0;
641 if (isset($_REQUEST['email'])) {
642 if (subjectFieldIsOK($required)!=true) {
643 $num_fielderrors=1;
644 echo "<p class=\"emailFormFieldError\"><i>";
645 switch ($lang) {
646 case en:
647 echo "Please supply your subject.";
648 break;
649 case sv:
650 echo "Vänligen fyll i ämne.";
651 break;
652 default:
653 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
654 }
655 echo "</i></p>\n";
656 }
657 }
658 return($num_fielderrors);
659 }
660
661 //
662 // The messageFieldIsOK($required) checks that the supplied message
663 // body is alright (if required) and returns 'true' if this is the
664 // case; otherwise 'false' is returned.
665 //
666 function messageFieldIsOK($required) {
667 if ($required["message"]==true) {
668 if (trim($_REQUEST["message"])=="") {
669 return false;
670 } else {
671 return true;
672 }
673 } else {
674 return true;
675 }
676 }
677
678 //
679 // The messageField($lang,$required,$keepTextFields) function generates
680 // the message input field, with $lang determining the language to use
681 // ("en" or "sv"), $required['message'] whether the user input in this
682 // field is required for sending the message, and $keepTextFields being
683 // a Boolean parameter which determines if any previously entered data
684 // should be maintained in the field as it is re-displayed (for example
685 // at the stage when any of the required user-supplied has been found to
686 // contain errors).
687 //
688 function messageField($lang,$required,$keepTextFields) {
689 switch ($lang) {
690 case en:
691 echo " <p class=\"fieldLabel\">Message:";
692 if ($required["message"]==true) echo " (required)";
693 echo "</p>\n";
694 break;
695 case sv:
696 echo " <p class=\"fieldLabel\">Meddelande:";
697 if ($required["message"]==true) echo " (obligatoriskt)";
698 echo "</p>\n";
699 break;
700 default:
701 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
702 }
703 //
704 // When generating the code for the input field, we perform a check to
705 // see if the field has been previously set (for example prior to an
706 // email send event), in which case the previously used text will be
707 // set as the default for the current field. This is just to avoid the
708 // surprisingly common behaviour of web forms that automatically erase
709 // previously entered data if any of the fields contain incorrect data.
710 //
711 echo " <p><textarea name=\"message\" id=\"Body\" rows=\"16\" cols=\"40\" >";
712 if ($keepTextFields==true) {
713 if (isset($_REQUEST["message"]))
714 echo $_REQUEST["message"];
715 }
716 echo "</textarea></p>\n";
717 $num_fielderrors=0;
718 if (isset($_REQUEST['email'])) {
719 if (messageFieldIsOK($required)!=true) {
720 $num_fielderrors=1;
721 echo "<p class=\"emailFormFieldError\"><i>";
722 switch ($lang) {
723 case en:
724 echo "Please supply your message.";
725 break;
726 case sv:
727 echo "Vänligen fyll i ditt meddelande.";
728 break;
729 default:
730 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
731 }
732 echo "</i></p>\n";
733 }
734 }
735 return($num_fielderrors);
736 }
737
738 //
739 // The submitButton($lang) function generates the (X)HTML code for the
740 // submit button of the email form, with $lang determining the language
741 // to use ("en" or "sv").
742 //
743 function submitButton($lang) {
744 $num_args=func_num_args();
745 echo " <input type=\"submit\" name=\"send\" ";
746 switch ($lang) {
747 case en:
748 echo "value=\"Send\" ";
749 break;
750 case sv:
751 echo "value=\"Sänd\" ";
752 break;
753 default:
754 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
755 }
756 echo "class=\"sendButton\" />\n";
757 return;
758 }
759
760 //
761 // The clearButton($lang) function generates the (X)HTML code for the
762 // clear button of the email form, with $lang determining the language
763 // to use ("en" or "sv").
764 //
765 function clearButton($lang) {
766 echo " <input type=\"reset\" name=\"clear\" ";
767 switch ($lang) {
768 case en:
769 echo "value=\"Clear\" ";
770 break;
771 case sv:
772 echo "value=\"Radera\" ";
773 break;
774 default:
775 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
776 }
777 echo "class=\"clearButton\" />\n";
778 return;
779 }
780
781 function passcode_term_1($seed) {
782 $tmp=md5($seed+$custom_seed_increment);
783 return $tmp[strlen($tmp)-1]+1;
784 }
785
786 function passcode_term_2($seed) {
787 $tmp=md5($seed+$custom_seed_increment);
788 return $tmp[strlen($tmp)]+2;
789 }
790
791 function passcode($seed) {
792 return passcode_term_1($seed)+passcode_term_2($seed);
793 }
794
795 //
796 // The valid_passcode(supplied_passcode,correct_passcode_in_md5) function
797 // performs a check of the supplied_passcode string against the password
798 // generated from the seed_of_correct_passcode seed, and returns 'true' if
799 // a match was found; otherwise 'false' is returned.
800 //
801 function valid_passcode($supplied_passcode,$seed_of_correct_passcode) {
802 $correct_passcode=passcode($seed_of_correct_passcode);
803 if (strcmp(trim($supplied_passcode),trim($correct_passcode))==0) {
804 return true;
805 } else {
806 return false;
807 }
808 }
809
810 //
811 // The passcodeField($lang) function generates the field for passcode
812 // submission, with $lang determining the language to use ("en" or "sv").
813 //
814 function passcodeField($lang,$seed,$keepTextFields) {
815 //
816 // Normally when you have a form with text input fields, it is undesirable
817 // that the form gets submitted when the user hits ENTER in a field. As in
818 // the case of all other fields, the passcode send button is disabled using
819 // Javascript whenever the $prevent_enter_from_submitting parameter below
820 // is set to true. For details, see comments on the other fields of the
821 // email form.
822 //
823 $prevent_enter_from_submitting=true;
824 $term_1=passcode_term_1($seed);
825 $term_2=passcode_term_2($seed);
826 $question_string=trim($term_1." puls ".$term_2); // Deliberately misspelled
827
828 echo " <p class=\"emailFormPasscodeRequest\">\n";
829 echo " <em>\n";
830 switch ($lang) {
831 case en:
832 echo " Lately, I have been pestered by spam from web robots which\n";
833 echo " use this very email form. In order to separate real users\n";
834 echo " from these web crawlers, I have added an additional step with\n";
835 echo " a very simple test. Hence, in order to submit your message,\n";
836 echo " please enter the sum ".$question_string." in figures below,\n";
837 echo " and press the \"Send Passcode\" button:\n";
838 break;
839 case sv:
840 echo " På sistone har mängden skräppost som\n";
841 echo " levereras via detta formulär ökat markant, och\n";
842 echo " jag har därför lagt till ett enkelt test för\n";
843 echo " att skilja \"robotar\" från verkliga användare.\n";
844 echo " För att skicka ditt meddelande, vänligen skriv in\n";
845 echo " summan".$question_string." i siffror nedan, och tryck\n";
846 echo " på \"Sänd Lösen\"-knappen:";
847 break;
848 default:
849 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
850 }
851 echo " </em>\n";
852 echo " </p>\n";
853
854 //
855 // When generating the code for the input field, we perform a check to
856 // see if the field has been previously set (for example prior to an
857 // email send event), in which case the previously used text will be
858 // set as the default for the current field. This is just to avoid the
859 // surprisingly common behaviour of web forms that automatically erase
860 // previously entered data if any of the fields contain incorrect data.
861 //
862 echo " <p><input name=\"passcod\" id=\"SubmittedPasscode\" ";
863 if ($keepTextFields==true) {
864 if (isset($_REQUEST["passcod"]))
865 echo "value=\"".$_REQUEST["passcod"]."\" ";
866 }
867 if ($prevent_enter_from_submitting) echo "onkeypress=\"return noenter()\" ";
868 echo "type=\"text\" /></p>\n";
869 return;
870 }
871
872 //
873 // The submitPasscodeButton($lang) function generates the (X)HTML code
874 // for the submit button of the passcode (used as verification that the
875 // sender is no robot), with $lang determining the language to use ("en"
876 // or "sv").
877 //
878 function submitPasscodeButton($lang) {
879 echo " <input type=\"submit\" name=\"send\" ";
880 switch ($lang) {
881 case en:
882 echo "value=\"Send Passcode\" ";
883 break;
884 case sv:
885 echo "value=\"Sänd Lösen\" ";
886 break;
887 default:
888 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
889 }
890 echo "class=\"sendPasscodeButton\" />\n";
891 return;
892 }
893
894 //
895 // The thanksForYourMessage($lang) function generates the (X)HTML code
896 // for the acknowledgement message to display as the EMAILFORM script
897 // re-displays the email form after successful submission of the email.
898 // As in the other functions, $lang determining the language to use, with
899 // "en" for English or "sv" for Swedish.
900 //
901 function thanksForYourMessage($lang) {
902 echo "<p class=\"thanksForYourMessage\"><i>";
903 switch ($lang) {
904 case en:
905 echo "Thanks for your message. I will reply a.s.a.p.";
906 break;
907 case sv:
908 echo "Tack för meddelandet. Jag svarar snarast möjligt.";
909 break;
910 default:
911 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
912 }
913 echo "</i></p>\n";
914 return;
915 }
916
917 //
918 // The errorsInYourMessage($lang) function generates the (X)HTML code
919 // for the error message to display as the EMAILFORM script re-displays
920 // the email form after having found illegal or missing entries in the
921 // input fields. As in the other functions, $lang determining the language
922 // to use, with "en" for English or "sv" for Swedish.
923 //
924 function errorsInYourMessage($lang) {
925 echo "<p class=\"emailFormFieldError\"><i>";
926 switch ($lang) {
927 case en:
928 echo "Your message has not been sent, as the fields of the email form ";
929 echo "below contains errors. Please correct before sending.";
930 break;
931 case sv:
932 echo "Ditt meddelande har inte sänts, då formuläret ";
933 echo "nedan innehåller fel. Vänligen korrigera innan ";
934 echo "meddelandet skickas igen.";
935 break;
936 default:
937 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
938 }
939 echo "</i></p>\n";
940 return;
941 }
942
943 function errorsInYourPasscode($lang) {
944 echo "<p class=\"emailFormFieldError\"><i>";
945 switch ($lang) {
946 case en:
947 echo "Your message has not been sent, as the passcode you supplied ";
948 echo "is incorrect. Press the \"Send\" button below again for a new ";
949 echo "attempt of submission.";
950 break;
951 case sv:
952 echo "Ditt meddelande har inte sänts, då lösenordet ";
953 echo "du angav innehöll fel. Tryck på \"Sänd\"-knappen ";
954 echo "nedan igen för ett nytt försök.";
955 break;
956 default:
957 echo "PHP Error: Language switch \"".$lang."\" is not recognized!\n";
958 }
959 echo "</i></p>\n";
960 return;
961 }
962
963 //
964 // The spam($message,$sender) routine performs a check on the message
965 // body string and the email address of the sender to see if the mail
966 // should be considered as spam (in which case the function returns 'true')
967 // or not (in which case it returns 'false'). The checking is performed
968 // against two arrays '$spamwords_in_message' and '$typical_spam_addresses'
969 // which contain the words which triggers the spam flagging. Notice that
970 // the performed checking throughout is case insensitive.
971 //
972 function spam($message,$sender) {
973 //
974 // Modify the $spamwords_in_message and $typical_spam_addresses arrays to
975 // contain the lists of spam words you wish the check to be performed
976 // against. Here $spamwords_in_message contains the words which when
977 // present in the message body should trigger the spam checking function
978 // to return 'true' (spam), while $typical_spam_addresses contains the
979 // words in sender address which should trigger the function to return
980 // 'true'.
981 //
982 $spamwords_in_message=$GLOBALS['SPAM_TRIGGERS_IN_MESSAGE'];
983 $typical_spam_addresses=$GLOBALS['SPAM_TRIGGERS_IN_ADDRESS'];
984 foreach ($spamwords_in_message as $spamword) { // For each word in list, ...
985 if (stristr($message,$spamword)!=false) { // ... if a match is found ...
986 return true; // ... then message is spam!
987 }
988 }
989 foreach ($typical_spam_addresses as $spamword) { // For each address,...
990 if (stristr($sender,$spamword)!=false) { // ... if a match is found ...
991 return true; // ... then message is spam!
992 }
993 }
994 return false; // Only if the above tests fail, the message goes free
995 }
996
997 function emailform($lang) {
998 $bannerstring="Code automatically generated by EMAILFORM 1.24, ";
999 $bannerstring.="http://jonsson.eu/programs/php/emailform/";
1000 //
1001 // The variables used in the emailform() function are:
1002 // $required A Boolean array containing the elements
1003 // $required["name"], $required["message"],
1004 // $required["subject"] and $required["email"].
1005 // Depending on whether an element is set to
1006 // 'true' or 'false', the corresponding email
1007 // form fields will be required or not required,
1008 // respectively.
1009 // $recipient The email address of recipient to which the
1010 // messages are to be sent. Typically this string
1011 // is of the form "John Doe <john@somedomain.com>"
1012 // $use_pear_smtp_sendmail Boolean parameter which determines whether to
1013 // use PEAR sendmail agent or not. Set to 'true'
1014 // if using PEAR mail agent, otherwise 'false'.
1015 // $notify_on_spam_attempts Determines whether spam attempts should cause
1016 // a notification to be sent to the recipient.
1017 // Set to 'true' to notify on spam attempts,
1018 // otherwise 'false'.
1019 //
1020 // The elements of the $required array are as follows:
1021 // $required["name"] True if name of sender is required
1022 // $required["email"] True if reply-email of sender is required
1023 // $required["subject"] True if subject is required
1024 // $required["message"] True if non-empty message body is required
1025 //
1026 // The following parameters determine how the emailform($lang) function
1027 // should operate. In order to simplify the setup of the EMAILFORM package
1028 // on new servers, all customizable parameters are put within a global
1029 // scope and from within the emailform() function accessed via the $GLOBALS
1030 // array. This way, all customizable parameters can appear in the very
1031 // beginning of the code, meanwhile allowing for easy and secure access
1032 // from within any functions.
1033 //
1034 $required["name"]=$GLOBALS['SENDER_NAME_REQUIRED'];
1035 $required["email"]=$GLOBALS['SENDER_EMAIL_REQUIRED'];
1036 $required["subject"]=$GLOBALS['SUBJECT_REQUIRED'];
1037 $required["message"]=$GLOBALS['MESSAGE_REQUIRED'];
1038 $recipient=$GLOBALS['RECIPIENT'];
1039 $use_pear_smtp_sendmail=$GLOBALS['USE_PEAR_SMTP_SENDMAIL'];
1040 $notify_on_spam_attempts=$GLOBALS['NOTIFY_ON_SPAM_ATTEMPTS'];
1041
1042 //
1043 // Parse for additional arguments (that is, in addition to $lang).
1044 // If present, those arguments will be interpreted as parameters
1045 // overriding the default parameters as set above. Notice that any
1046 // additional options should never, ever be passed on from anything
1047 // supplied via the http address, as this would inflict a potential
1048 // security leak.
1049 //
1050 $num_args=func_num_args();
1051
1052 //
1053 // NOTICE: I decided to comment out this block as it so far does not
1054 // really contribute to things. [FJ 29/08/2007]
1055 //
1056 //switch($num_args) {
1057 // case 1:
1058 // // Default is when only one argument is supplied, i.e. the
1059 // // language definition string $lang. For this case, do nothing.
1060 // break;
1061 // case 3:
1062 // $buttontype=func_get_arg(1);
1063 // $imgsrcdir=func_get_arg(2);
1064 // break;
1065 // default:
1066 // echo "PHP Error: emailform() requires ... whatever!\n";
1067 //}
1068
1069 //
1070 // The (X)HTML code of the email form begins with a <form> statement
1071 // of ID "mailForm", which serves as a global hook for any CSS styling
1072 // to be applied. In this opening of the form, we also determine the
1073 // language-specific action to be taken as the form is submitted for
1074 // evaluation and (possibly, if all is OK) email submission.
1075 //
1076 // Note added 6 November 2006:
1077 // Notice that whenever the script is run on a Microsoft Windows IIS
1078 // machine, the "post" action will be causing an error of the form
1079 //
1080 // "HTTP 405 - Resource not allowed
1081 // Internet Information Services"
1082 //
1083 // unless the target is a file of type registered with the service.
1084 // Typically, the above error will appear with the "post" method
1085 // whenever the action target is a directory (i.e. with no extension
1086 // visible), or simply with the target action of something like
1087 // action="?lang=$lang". Hence, in order to avoid this we step outside
1088 // the rules (of trying to keep technology-independent URI:s) and use
1089 // action="index.php?lang=$lang" instead. For further details on how to
1090 // solve the problem at the server side, see http://www.somacon.com/p126.php
1091 //
1092 echo "<!-- $bannerstring -->\n";
1093 echo "<form id=\"mailForm\" method=\"post\" "
1094 ."action=\"index.php?lang=$lang\">\n";
1095
1096 //
1097 // If "email" is supplied to the page via the standard PHP POST method,
1098 // this indicates that an email send request has been submitted. In this
1099 // case, the first task is to validate the data in the fields as supplied
1100 // by the sender before any email actually is sent out.
1101 // Thus the following block, as enclosed in the "if (...)" conditional
1102 // statement, will only be entered if a request to send an email has been
1103 // detected by the EMAILFORM script.
1104 //
1105 if (isset($_REQUEST["email"])) {
1106 //
1107 // If the script detects that a send request has been submitted (that
1108 // is to say, that the 'email' field is detected as set), then proceed
1109 // with checking whether the 'passcod' (for "passcode") also has been
1110 // submitted, in which case the only task left is to check the validity
1111 // of the passcode.
1112 //
1113 if (isset($_REQUEST["passcod"])) {
1114 //
1115 // Notice that while the passcode (which, in general, may be different
1116 // from session to session (or time to time) is submitted in clear text,
1117 // the information on the correct password is only submitted as the seed
1118 // to be used in the generation of the key.
1119 // This way, the correct password is never exposed in clear. (In this
1120 // particular application of email form submission, the generation of the
1121 // password from the seed is rather trivial, but is easy to see how one
1122 // easily could extend the principle to a much more complicated and
1123 // secure passcode verification.
1124 //
1125 $supplied_passcode=trim($_REQUEST["passcod"]);
1126 $seed_of_correct_passcode=trim($_REQUEST["seed"]);
1127
1128 if (valid_passcode($supplied_passcode,$seed_of_correct_passcode)) {
1129 //
1130 // If a send request was detected and a correct passcode has been
1131 // verified, then send email only if all required fields are correctly
1132 // filled out.
1133 //
1134 if (fromNameFieldIsOK($required) && validEmailAddress($required)
1135 && subjectFieldIsOK($required) && messageFieldIsOK($required)) {
1136
1137 //
1138 // If all required fields in the form are correct, then send the
1139 // message. In the body of the sent message, we take the opportunity
1140 // to include information about the sender, such as browser (agent),
1141 // IP number and the web page from which the message was sent.
1142 //
1143 $iparray=explode(".",$_SERVER['REMOTE_ADDR']);
1144 $email=stripslashes(trim($_REQUEST['email']));
1145 $name=$_REQUEST['name'];
1146 if ($GLOBALS['SUBJECT_REQUIRED']==true) {
1147 // Subject field has been displayed by EMAILFORM, so hence extract
1148 // the subject field as entered (if any).
1149 $subject=$_REQUEST['subject'];
1150 } else {
1151 //
1152 // Subject field has not been displayed, hence just use any dummy
1153 // subject to indicate that this is a message submitted via the
1154 // email form on your web site.
1155 //
1156 $subject="EmailForm message sent via website";
1157 }
1158 $message=$_REQUEST['message'];
1159 $sender=($name!=""?"$name <$email>":$email);
1160
1161 if (spam($message,$sender)) { // If message is detected to be spam...
1162 $message_is_spam=true;
1163 if ($notify_on_spam_attempts) { // alter mail if note to be sent,
1164 $message="Spam from ".$sender." was detected.\n";
1165 $sender="Emailform <noreply@jonsson.eu>"; // Replace sender email
1166 $subject="Report of spam attempt"; // Replace subject line
1167 } else {
1168 $message=""; // ... otherwise, just erase the message string.
1169 }
1170 } else {
1171 $message_is_spam=false;
1172 }
1173
1174 $msgfoot="\n\n-------------------------------------------------\n";
1175 $msgfoot.="User IP number: ".$_SERVER['REMOTE_ADDR']."\n";
1176 $msgfoot.="HTTP referrer: ".$_SERVER['HTTP_REFERER']."\n";
1177 $msgfoot.="User agent: ".$_SERVER['HTTP_USER_AGENT']."\n";
1178
1179 //
1180 // Also take the opportunity to enclose links to databases for direct
1181 // look-up of the organization associated with the IP number. The
1182 // databases I here supply links to are RIPE (Reseaux IP Europeens,
1183 // http://www.ripe.net/) and SCHWARZL.
1184 //
1185 $msgfoot.="Look up IP owner using RIPE database:\n";
1186 $msgfoot.="https://www.ripe.net/whois?form_type=simple";
1187 $msgfoot.="&full_query_string=&searchtext=".$_SERVER['REMOTE_ADDR'];
1188 $msgfoot.="&do_search=Search\n\n";
1189
1190 //
1191 // Uncomment the following blocks to include a link to the Schwarzl
1192 // whois database of IP numbers as well.
1193 //
1194 // $msgfoot.="Look up IP owner using SCHWARZL database:\n";
1195 // $msgfoot.="http://www.schwarzl.com/ipcheck.html";
1196 // $msgfoot.="?action=query&ip1=$iparray[0]&ip2=$iparray[1]";
1197 // $msgfoot.="&ip3=$iparray[2]&ip4=$iparray[3]\n";
1198
1199 //
1200 // Finally just enclose the time of execution of the script and a
1201 // simple copyright statement.
1202 //
1203 $msgfoot.="-------------------------------------------------\n";
1204 $msgfoot.="Message sent ".date("F jS Y H:i:s",time()).
1205 " by EMAILFORM,\n";
1206 $msgfoot.="http://jonsson.eu/programs/php/emailform/\n";
1207 $msgfoot.="Copyright (C) 2006-2009, Fredrik Jonsson";
1208 $message.=$msgfoot;
1209 $name=trim($name);
1210 if ($use_pear_smtp_sendmail==true) {
1211 require('Mail.php');
1212 //
1213 // At this stage, notice that if the earlier performed message
1214 // check has shown that the message is a spam mail, then the
1215 // $sender, $message and $subject fields will have been replaced
1216 // by the defaults of spam alert.
1217 //
1218 $headers['From']=$sender;
1219 $headers['To']=$recipient;
1220 $headers['Subject']=$subject;
1221
1222 //
1223 // Parameters when using the SMTP instance of PEAR::Mail. In order
1224 // to simplify the setup of the EMAILFORM package on new servers,
1225 // all customizable parameters are put within a global scope and
1226 // from within the emailform() function accessed via the $GLOBALS
1227 // array. This way, all customizable parameters can appear in the
1228 // very beginning of the code, meanwhile allowing for easy and
1229 // secure access from within any functions.
1230 //
1231 // $params['host'] Server to connect to. Default is localhost.
1232 // $params['port'] The port to connect. Default is 25.
1233 // $params['auth'] Whether or not to use SMTP authentication.
1234 // Default is FALSE.
1235 // $params['username'] Username to use for SMTP authentication.
1236 // $params['password'] Password to use for SMTP authentication.
1237 //
1238 $params['host']=$GLOBALS['PEAR_SMTP_SENDMAIL_HOST'];
1239 $params['port']=$GLOBALS['PEAR_SMTP_SENDMAIL_PORT'];
1240 $params['auth']=$GLOBALS['PEAR_SMTP_SENDMAIL_AUTHENTICATION'];
1241 $params['username']=$GLOBALS['PEAR_SMTP_SENDMAIL_USERNAME'];
1242 $params['password']=$GLOBALS['PEAR_SMTP_SENDMAIL_PASSWORD'];
1243
1244 //
1245 // Create the PEAR mail object using the Mail::factory method
1246 //
1247 if ($message_is_spam) { // If message is spam, and notification is
1248 if ($notify_on_spam_attempts) { // wanted, then send mail with
1249 // changed sender and subject.
1250 $mail_object = Mail::factory('smtp',$params);
1251 $mail=$mail_object->send($recipient, $headers, $message);
1252 }
1253 } else { // If no spam, just go ahead and send the email
1254 $mail_object = Mail::factory('smtp',$params);
1255 $mail=$mail_object->send($recipient, $headers, $message);
1256 }
1257
1258 if (PEAR::isError($mail)) {
1259 echo "Something went wrong with the submission of the message!";
1260 echo("<p>" . $mail->getMessage() . "</p>");
1261 } else {
1262 thanksForYourMessage($lang);
1263 }
1264 } else {
1265 //
1266 // If using the more primitive instance of sendmail under PHP,
1267 // such as, for example, the sendmail agent supplied with the
1268 // Apache distribution shipped with Mac OS X, then use this if
1269 // PEAR SMTP mail has been declared as non-wanted. However, if
1270 // available, do try to use a PEAR mail instance, as this provides
1271 // a more secure mail handling.
1272 //
1273 if ($message_is_spam) { // If message is spam, ...
1274 if ($notify_on_spam_attempts) { // and we wish to be notified ...
1275 mail($recipient,$subject,$message,"From: $sender");
1276 } // then send notification.
1277 } else { // Else, if no spam detected, just go ahead and send ...
1278 mail($recipient,$subject,$message,"From: $sender"); // the email.
1279 }
1280 thanksForYourMessage($lang); // A polite "thank you" is always nice
1281 }
1282 $keepTextFields=false; // Clear all data entered in the email form
1283 } else {
1284 errorsInYourMessage($lang); // If errors detected in user input
1285 $keepTextFields=true; // Re-display data entered in the email form
1286 }
1287 } else { // End of "if (valid_passcode(...,...))"
1288 //
1289 // If we end up here, an email submission with an erroneous passcode
1290 // was detected.
1291 //
1292 errorsInYourPasscode($lang);
1293 $keepTextFields=true; // Re-display data entered in the email form
1294 }
1295 } else { // End of "if (isset($_REQUEST['passcod']))"
1296 //
1297 // If we end up here, an email submission was detected, however with
1298 // no passcode verification yet performed. In this case, the passcode
1299 // request form will be displayed later on, after the re-display of
1300 // the email form. At this stage, however, the script should take no
1301 // action until all email form fields actually have been verified.
1302 //
1303 $keepTextFields=true; // Re-display data entered in the email form
1304 }
1305 } // End of "if (isset($_REQUEST['email']))"
1306
1307 //
1308 // Regardless whether "email" is supplied as a parameter to the page or
1309 // not, display the email form. Depending on whether $keepTextFields in
1310 // any previous blocks has been set to 'true' or 'false', the entered
1311 // data will be re-displayed or not, respectively. However, if "email"
1312 // is supplied to the page, then a check of the fields will be performed
1313 // by the respective field-generating PHP routine is a manner identical
1314 // to the check performed in determining whether an email should be sent
1315 // or not. This is done in order to add any guiding comments to the fields
1316 // labels, such as "Please supply a valid email address", etc.
1317 //
1318 // Notice: Any field that has been disabled for display, by any of the
1319 // "DO_DISPLAY_*"-parameters, will be unaffected by the corresponding
1320 // "*_*_REQUIRED"-switches below, as the "required-field"-check
1321 // is applied only to those fields which actually are displayed.
1322 // Neat and simple, huh?
1323 //
1324 $num_fielderrors=0;
1325 leaveMessageHeader($lang);
1326 if ($GLOBALS['DO_DISPLAY_SENDERS_NAME_FIELD'])
1327 $num_fielderrors+=fromNameField($lang,$required,$keepTextFields);
1328 if ($GLOBALS['DO_DISPLAY_SENDERS_EMAIL_FIELD'])
1329 $num_fielderrors+=fromEmailField($lang,$required,$keepTextFields);
1330 if ($GLOBALS['DO_DISPLAY_SUBJECT_FIELD'])
1331 $num_fielderrors+=subjectField($lang,$required,$keepTextFields);
1332 //
1333 // The message field is for obvious reasons essential, and is hence
1334 // always displayed.
1335 //
1336 $num_fielderrors+=messageField($lang,$required,$keepTextFields);
1337
1338 //
1339 // Determine whether we are in the "email writing and submission" step or
1340 // the "final passcode submission" step. This will determine the way the
1341 // rest of the EMAILFORM form is displayed.
1342 //
1343 if (isset($_REQUEST['email']) // If email submission was requested...
1344 && !isset($_REQUEST['passcod']) // and no passcode supplied so far...
1345 && $num_fielderrors==0) { // and no errors detected in any field...
1346 $passcode_submission_step=true;
1347 } else {
1348 $passcode_submission_step=false;
1349 }
1350
1351 //
1352 // If we have not yet reached the passcode submission step, this might be
1353 // due to that we either:
1354 // 1. Have not yet attempted to submit the email, or
1355 // 2. That any of the fields which are required to be correct
1356 // still contain errors.
1357 // Regardless of which, we should for this case generate the (X)HTML code
1358 // for the email submission button, together with the "Clear" button (which
1359 // for some historical reason almost always is present in submission forms;
1360 // the EMAILFORM script here simply conforms to common practice...).
1361 //
1362 if ($passcode_submission_step==false) {
1363 echo " <div>\n";
1364 submitButton($lang);
1365 clearButton($lang);
1366 echo " </div>\n";
1367 }
1368
1369 //
1370 // On the other hand, if we indeed have entered the passcode submission step,
1371 // then we should omit the "Send" and "Clear" buttons and instead display a
1372 // guiding text on why the passcode test is needed, together with a grand
1373 // "Submit Passcode" button which will take care of the final submission of
1374 // the message.
1375 //
1376 if ($passcode_submission_step==true) {
1377 $seed=$GLOBALS['PASSCODE_SEED']; // Seed for passcode generation
1378 passcodeField($lang,$seed,$keepTextFields); // Generate the passcode field
1379 echo " <div>\n";
1380 submitPasscodeButton($lang); // Generate submission button
1381 echo " </div>\n";
1382 }
1383
1384 //
1385 // In any case, display an EMAILFORM banner to promote this fine art of
1386 // computer code...
1387 //
1388 $emailform_url="http://jonsson.eu/programs/php/emailform/";
1389 echo " <p>";
1390 echo "Generated by <a href=\"".$emailform_url."\">::emailform::</a>";
1391 echo "</p>\n";
1392 echo "</form>\n";
1393 echo "<!-- End of EMAILFORM automatically generated code -->\n";
1394 return;
1395 }
1396 ?>
1397
Generated by ::viewsrc::