Search:

Return to previous page

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&auml;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&auml;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&auml;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\">&Auml;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&auml;nligen fyll i &auml;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&auml;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&auml;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&aring; sistone har m&auml;ngden skr&auml;ppost som\n";
  841         echo "  levereras via detta formul&auml;r &ouml;kat markant, och\n";
  842         echo "  jag har d&auml;rf&ouml;r lagt till ett enkelt test f&ouml;r\n";
  843         echo "  att skilja \"robotar\" fr&aring;n verkliga anv&auml;ndare.\n";
  844         echo "  F&ouml;r att skicka ditt meddelande, v&auml;nligen skriv in\n";
  845         echo "  summan".$question_string." i siffror nedan, och tryck\n";
  846         echo "  p&aring; \"S&auml;nd L&ouml;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&auml;nd L&ouml;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&ouml;r meddelandet. Jag svarar snarast m&ouml;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&auml;nts, d&aring; formul&auml;ret ";
  933         echo "nedan inneh&aring;ller fel. V&auml;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&auml;nts, d&aring; l&ouml;senordet ";
  953         echo "du angav inneh&ouml;ll fel. Tryck p&aring; \"S&auml;nd\"-knappen ";
  954         echo "nedan igen f&ouml;r ett nytt f&ouml;rs&ouml;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   

Return to previous page

Generated by ::viewsrc::

Last modified Wednesday 15 Feb 2023