FormMail. * * Author: Russell Robinson, 2nd October 2001 * Last Modified: RR 17:55 Mon 25 September 2006 * QVCS Version: $Revision: 1.109 $ * * Read This First * ~~~~~~~~~~~~~~~ * This script is very heavily documented! It looks daunting, but * really isn't. * If you have experience with PHP or other scripting languages, * here's what you *need* to read: * - Features * - Configuration (TARGET_EMAIL & DEF_ALERT) * - Creating Forms * That's it! (Alternatively, just read the Quick Start section below). * * Quick Start * ~~~~~~~~~~~ * 1. Edit this file and set TARGET_EMAIL for your requirements (approx * line 2958 in this file - replace "yourhost\.com" with your mail server's * name). We also strongly recommend you set DEF_ALERT (the next * configuration below TARGET_EMAIL). * 2. Install this file as formmail.php on your web server * 3. Create an HTML form and: * - specify a hidden field called "recipients" with the email address * of the person to receive the form's results. * - specify method "post" (or "get") and an action set to * the formmail.php you uploaded to your web server * * Once you have FormMail working, you may be interested in some advanced * usage and features. We have HOW-TO guides at www.tectite.com which * describe many of the advanced processing you can do with FormMail. * * Purpose: * ~~~~~~~~ * To accept HTTP POST information from a form and mail it to recipients. * This version can also supply data to a TectiteCRM document, usually * for insertion into the CRM database. * * What does this PHP script do? * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * On your web site, you may have one or more HTML forms that accept * information from people visiting your website. Your aim is for your * website to email that information to you and/or add it to a database. * formmail.php performs those functions. * * Features * ~~~~~~~~ * - Optionally sends email of form results to recipients that * can be specified in the form itself. * - Optionally stores the form results in a CSV (comma-separated- * values) file on your server. * - Optionally logs form activity. * - Optionally sends form results to a TectiteCRM document; generally, * to automatically update the CRM database. * - Recipient email addresses can be mangled in your forms to * protect them from spambots. * - Emails can be processed through any program (typically an * encryption program) before sending. * - Successful processing can redirect the user to any URL. * For example, for downloads, we redirect the user to the file * they want to download. * - Supports any number of recipients. For security, recipient * domains must be specified inside the script (see "Configuration" * for details). * - Failed processing can redirect to a custom URL. * - Failed processing can be reported to a specific email address. * - Supports both GET and POST methods of form submission. * - Supports file uploads (multiple files can be uploaded). * - Supports checkboxes and multiple-selection lists. * - Supports CC and BCC addresses. * - Supports deriving fields by concatenating other fields. * - Supports exclusion of fields (in email) * - Supports HTML emails via a template feature. * - Supports complex field validation mechanisms. * - Supports advanced user error handling features (including using our * free fmbadhandler.php script). * - Supports error and success template display. * - Provides most of the features of other formmail scripts. * * Security * ~~~~~~~~ * Security is the primary concern in accepting data from your website visitors. * formmail.php has several security features designed into it. Note, however, * it requires configuration for your particular web site. * * Configuration * ~~~~~~~~~~~~~ * For instructions on configuring this program, go to the section * titled "CONFIGURATION" (after reading the legal stuff below). * There is only one mandatory setting: TARGET_EMAIL * * Creating Forms * ~~~~~~~~~~~~~~ * This section explains how to call formmail.php from your HTML * forms. You already need to know how to create an HTML form, but * this section will tell you how to link it with this formmail script. * * Your form communicates its requirements to formmail.php through * a set of "hidden" fields (using ). The data to * be processed by formmail (e.g. the actual email to send) comes from * a combination of hidden fields and other form fields (i.e. data entry * fields from the user). * * Here are the steps to use formmail.php with your HTML form: * 1. Create your HTML form using standard HTML * 2. Ensure your form has the following fields defined. These are * fields you expect the user to fill in: * email the user's email address * realname the real name of the user * 3. Add the following hidden fields to your form. Note that all * are optional: * recipients a comma-separated list of email addresses that * the form results will be sent to. These must * be valid according to the "TARGET_EMAIL" configuration. * Example: * russ.robbo@rootsoftware.com,sales@rootsoftware.com.au * alert_to email address to send errors/alerts to * Example: * webmaster@rootsoftware.com * required a list of fields the user must provide, together * with a friendly name. The field list is separated * by commas, and you append the friendly name to * the field name with a ':'. * Example: * email:Your email address,realname:Your name,Country,Reason:The reason you're interested in our product * Note that field names and friendly names must not * contain any of these characters: * :|^!=, * Advanced usage allows you to do the following: * field1:name1|field2:name2 * either field1 or field2 is required * (both allowed, too) * field1:name1^field2:name2 * either field1 or field2 is required * (both not allowed) * field1:name1=field2:name2 * field1's value must be the same as * field2's value * field1:name1!=field2:name2 * field1's value must be different from * field2's value * In all the above ":name" is optional for any field. * * conditions a list of complex conditions, all of which must * evaluate to true. Conditions are a more powerful * alternative to the "required" specification. * The list of conditions is separated by a character * you specify by the first character in the list. You * specify the internal conditions component separator * as the second character in the list, as follows: * name="conditions" value=":@condition1:condition2 * :condition3" * specifies that the conditions are separated by the * asterisk character. * There are size limitations to fields, so you * can specifie any number of conditions fields like * this: * name="conditions1" value=":@condition1:condition2 * :condition3" * name="conditions2" value=":@condition4:condition5 * :condition6" * * A condition has this general format (spaces * optional): * COMMAND@ test1 @test2 @... @MESSAGE@ * COMMAND and MESSAGE are mandatory. MESSAGE is * the message to display to the user if the condition * fails. * "@" is the internal separator that you specified * as the second character of the conditions list. * The tests are field comparisons, and have this * general format: * field1 OP field2 * * OP is an operand. Tests are similar to the "required" * specification, but the friendly field names are not * allowed because you can provide a general message. * * field1 * field1 must have a value * field1&field2 * both field1 and field2 must have a value * field1|field2 * either field1 or field2 must have a value * (both allowed, too) * field1^field2 * either field1 or field2 must have a value * (both not allowed) * field1=field2 * field1's value must be the same as * field2's value * field1!=field2 * field1's value must be different from * field2's value * field1~pattern * field1's value must match the specified * perl regular expression * field1!~pattern * field1's value must not match the specified * perl regular expression * field1#=number * field1's value is interpreted as a number * and must equal the given number * field1#!=number * field1's value is interpreted as a number * and must be not equal to the given number * field1#number * field1's value is interpreted as a number * and must be greater than the given number * field1#<=number * field1's value is interpreted as a number * and must be less than or equal to the given number * field1#>=number * field1's value is interpreted as a number * and must be greater than or equal to the given number * ! * the test evaluates to "false". * an empty test evaluates to "true". * * The conditions are: * @TEST@test@message@ * the test must be true. If not, the * given message is shown. * Example: * @TEST@realname@Please provide your name so * that we can address you properly.@ * This is exactly the same as a "required" * specification except that you can provide * an arbitrary message. * * @IF@test1@test2@test3@message@ * if test1 is true then test2 * must be true. If test1 is false then * test3 must be true. * Examples: * @IF@salutation~/usefirst/@firstname@lastname@You * must provide your first name if you * want us to use it to address you or * your last name for Mr., Mrs., etc.@ * says that firstname is required * if salutation has the value "usefirst", * and lastname is required otherwise. * On failure, the given message is shown. * * @IF@payment~/ccard/@creditcard~/[1-9][0-9]{12,15}/@@You must * enter your credit card number to * pay by credit card.@ * says that if the payment value is "ccard" * then the creditcard field must contain * at least one digit. * * mail_options a list of options to control FormMail when * sending email * derive_fields a mechanism for deriving form fields by * concatenating other form fields * Example: * realname=firstname+lastname,fullphone=area.phone,address=street*suburb * Operators are: * + concatenate with a single space between, * but skip the space if the next field is * empty * . concatenate with no space between * * concatenate with a single space between * file_names a mechanism for naming the files uploaded by the * form. By default the files will be named with * user's original file name. This feature allows you * to provide different names. * The same features are available as for derive_fields. * Example: * file1=order_id.%'-1'%,file2=order_id.%'-2'% * good_url the URL to redirect to on successful processing * bad_url the URL to redirect to on failed processing * this_form the URL of the form that's submitting the data; * used with intelligent bad_url processing * good_template a template file that FormMail can display on * successful processing * bad_template a template file that FormMail can display on * failed processing * template_list_sep a string to use when expanding lists * of values in templates. The default is comma. * subject a subject line for the email that's sent to your * recipients * Example: * Form Submission * env_report a comma-separated list of environment variables * you want included in the email * Example: * REMOTE_HOST,REMOTE_ADDR,HTTP_USER_AGENT,AUTH_TYPE,REMOTE_USER * filter name of a filter to process the email before sending. * You can encode or encrypt the email, for example. * filter_options comma-separated list of options to control the filter. * filter_fields comma-separated list of fields to filter. * The behaviour of this specification can vary slightly * depending on your other specifications. Refer * to our How-To guide on Filtering for more information. * logfile name of a file to append activity to. Note that * you must configure "LOGDIR" for this to work. * Example: * formmail.log * csvfile name of the CSV database to append results to. Note that * you must configure "CSVDIR" for this to work. You * must also specify the csvcolumns field. * Example: * formmail.csv * csvcolumns comma-separated list of field names you want to * store in the CSV database. These are the field * names in your form, and the order specifies the * order for storage in the CSV database. * Example: * email,realname,Country,Reason * autorespond comma-spearated list of specifications for the * Auto Repsonder feature. Specifications are: * Subject set to the subject line you * want in the email sent to the user * HTMLTemplate set to the name of the template * to use for sending HTML email to * the user * PlainTemplate set to the name of the template * to use for sending plain text email * to the user * TemplateMissing set to the string to use to * fill in unsubmitted fields in template * You can specify either HTMLTemplate or PlainTemplate * or both. * Example: * Subject=Thanks for your purchase,HTMLTemplate=orderemail.htm * crm_url a URL to send the form data to. This is for use * with the TectiteCRM system. * crm_spec a specification to pass to TectiteCRM. Please * read the TectiteCRM documentation for details of * how to use this field. * crm_options options to control processing of TectiteCRM * interface * * 4. Check that you've provided at least one of these fields: * recipients, or * logfile, or * csvfile and csvcolumns, or * crm_url and crm_spec * If you don't specify any of these, then formmail.php will fail * because you've given it no work to do! * * Note that we've provided a sample HTML form to get you started. * Look for "Sample HTML Form Using FormMail" on our forums at * http://www.tectite.com/. * * Note also that the default success and failure pages shown by formmail.php * are quite basic. We recommend that you provide your own pages * with "good_url" and "bad_url". * * Copying and Use * ~~~~~~~~~~~~~~~ * formmail.php is provided free of charge and may be freely distributed * and used provided that you: * 1. keep this header, including copyright and comments, * in place and unmodified; and, * 2. do not charge a fee for distributing it, without an agreement * in writing with Root Software allowing you to do so; and, * 3. if you modify formmail.php before distributing it, you clearly * identify: * a) who you are * b) how to contact you * c) what changes you have made * d) why you have made those changes. * * Warranty and Disclaimer * ~~~~~~~~~~~~~~~~~~~~~~~ * formmail.php is provided free-of-charge and with ABSOLUTELY NO WARRANTY. * It has not been verified for use in critical applications, including, * but not limited to, medicine, defense, aircraft, space exploration, * or any other potentially dangerous activity. * * By using formmail.php you agree to indemnify Root Software and * Open Concepts Pty Ltd, their agents, employees, directors and * associated companies and businesses from any liability whatsoever. * * We still care * ~~~~~~~~~~~~~ * If you find a bug or fault in FormMail, please report it to us. * We will respond to your report and make endeavours to rectify any * faults you've detected as soon as possible. * To contact us, visit http://www.tectite.com/contacts.php. * * Version History * ~~~~~~~~~~~~~~~ * **Version 7.11: 25-Sep-2006 * * Fixed typographical error in defining the FILE_MODE constant. This typo appears * to be harmless as PHP handled it automatically. * * Added new configuration option, SET_SENDER_FROM_EMAIL, * to support yet another server requirement for sending email. * * Added extensive description of the email logic since different and * conflicting server requirements are making it very difficult to * understand. * * Fixed bug in handling multiple email addresses in the INI file * (specifically, a list of email addresses for a word in the * [email_addresses] section of the INI file. * **Version 7.10: 07-July-2006 * * Fixes a vulnerability involving file uploads to the server. * To be vulnerable, you would need both of these statements * to be true: * 1. You are using version 7.06 thru 7.09 of FormMail. * 2. You have set FILEUPLOADS to true in FormMail's configuration.. * 3. You have set $FILE_REPOSITORY in FormMail's configuration. * * If any of these statements are false, then you are not vulnerable. * * The exploit for the vulnerability (which we won't publish at this time) * is complex and specific to each server. In most cases it will not succeed * because the web server software cannot write to arbitrary files on * the server. * * We detected this problem though our QA procedures, and we have received * no reports of any exploits. * * Mitigating this vulnerability is the fact that the documentation for * file uploading to the server was only published in mid-June 2006. Also, * while there are a large number of users of the vulnerable versions, * very few enable file uploads to the server. * **Version 7.09: 30-May-2006 * * Fixes a bug in using FromAddr (mail_options) with AT_MANGLE on some servers * (those that require SENDMAIL_F_OPTION and/or INI_SET_FROM). * Prior to this version, the FromAddr was not un-mangled before setting * it for the server. * **Version 7.08: 28-Feb-2006 * * Alerts now show the IP address of the user. Fixed minor issue * in last version with showing the 'this_form' in alerts. * * Fixed some code formatting that had gone wonky. * * Implemented a new special field called "file_names". This is * similar in syntax to "derive_fields" and allows you to provide * different names for uploaded files. * * Empty derivations are now ignored - previously an alert was generated. * **Version 7.07: 18-Feb-2006 * * Fixes a minor problem with using a file field name in good_template * when the file has been stored on the server. * * Alert messages now show the referring page or the 'this_form' field * so you can identify which form generated the alert. * * Implemented a Hook System. This allows you to include a PHP file within * FormMail at various points. * * Implemented an "if" function for use when deriving fields. * **Version 7.06: 14-Feb-2006 * * Added support for a form INI file. This allows you to set special fields * and provide secret email addresses outside of the HTML form. * * Fixed a problem with processing conditions in the specified order. This * problem would occur if you specified conditions7, conditions2, conditions1 * in that order. Now they will be processed in the order specified by their * numeric ID. * * Added support for uploading the files to the server instead of attaching * them. * * Added support for imgverify special field. You can now prevent form * submission unless this matches the CAPTCHA string from verifyimg.php. * * A missing image verification string in the session is now reported * as a system error (for imgverify or arverify). It indicates a failure * in the PHP session processing. * * Added more features for handling file uploads. A file field can now: * - be tested in "conditions" and "required". For "required", the value * of the file field is the name of the file uploaded from the user's * computer. Similarly for "conditions" on string testing. For * "conditions" performing numeric comparisons, the file field * expands to the size of the uploaded file in bytes. * - be used to derive other fields. The name of the file is expanded * in the derivation. * - be used in templates. The name of the file is expanded in the * derivation. * - the size of a file can now be used to derive a field: * fieldname = %size(filefield)% * * Improved IsFieldEmpty function to handle array values. This is * really for future accuracy, as it shouldn't affect any current * processing. * **Version 7.05: 27-Oct-2005 * * Added support for HTTP authentication when using FMBadHandler. * FormMail now sends the name and password to FMBadHandler so that * it can return to the form. * * Added support for HTTP authentication when using multi-page forms. * This is only needed when returning to the first page, as all other * pages are templates. * **Version 7.04: 26-Sep-2005 * * Removed parentheses which previously surrounded message numbers. * Added new optional "mnums=no" parameter when using "testlang=1" * * Fixed bug in matching "selected" and "checked" attributes when processing * multi-page forms. This bug only occurred under rare circumstances. * An example is: *