This mail kit is used to provide both our 'mail this page' feature in the header of all pages and by the addition of a hidden field it also handles our 'mail us', 'feedback' and 'bug report' mail functions (OK, so we're cheap). There are many PHP email functions around - we don't think ours is particularly special and it is presented here in case it has some interesting aspects that you may find useful.
During early 2006 we discovered that we were getting occasional abuse of the 'mail this page' feature which we fixed in a very trivial way, then in May 2006 we got hammered with a full-scale SPAM injection attack and had to drastically rework all our mail capabilities to check for a variety of abuses. The lesson was clear - we had survived for over 5 years without any real problems - but we had been lucky, perhaps even naive.
Health-Warning: This is made available at your risk, we make no warranty that the code has no bugs in it or that it will even do what we think or say it will. Like all downloaded software we urge caution if you use it.
We wanted a 'mail this page' feature and we'd played around previously with href=mailto directives and briefly with Javascript mail features none of which gave us what we wanted. Javascript mail and 'mailto' are very useful and trivial because they do not use any server (CGI) features .. but if the user's PC is not configured with a local mail client they do not work - we wanted to provide a PC independent method of getting mail to us - though our webmaster link at the foot of the page will continue to use mailto. Moreover, all the articles we had read indicated that PHP is a real breeze for mailing.
However:
We wanted the ability to either send a page link or optionally to send the entire HTML page being referenced as a mail item
We wanted (and still do) the option to send the entire page as a mail item not just a link in our 'mail this page' feature. Most of our pages are generated using Apache Server Side Includes (SSIs) and contain 'relative' references to other pages and embedded images, for example, '../images/logo.gif' etc.. Big deal .. so what. Here's so what:
When you send HTML in mail you need 'absolute' references, for example, 'http://www.example.com/images/logo.gif' to other pages and images used in the document.
We need to expand our pages (containing SSIs etc) and then fix up all the 'relative' references.
We need to get the resultant page string into our PHP mail call. We think this is currently impossible using standard PHP functions.
There are a couple solutions to 'relative' addressing (none of which fit our circumstances) which may work for you.
Don't use relative addresses always use 'absolute' addresses (very restrictive and you gotta type stuff man, lots of stuff).
Use SSI based 'absolute' addressing i.e. embed an SSI echo directive in the 'href's and img 'src' fields, for instance,
<img border="0" src="http://<!--#echo var="HTTP_HOST" -->/images/snap.gif"> <a href="http://<!--#echo var="HTTP_HOST" -->/page.htm">
The only way we can figure to do this is to issue the GET request from PHP. This would provide a raw string containing the expanded page. We would then change the 'relative' references to 'absolute' references with a couple of PHP regular expression function calls and then mail the resulting modified string.
We decided not to do this on very tenuous grounds. It didn't feel right (oh really!!). Actually we could see a whole host of additional applications for this relative to absolute addressing and currently believe that the best way is to modify PHP virtual function. Perhaps one day Real Soon Now™. For the time being we use a simple text mail web page reference.
Configuring PHP for mail is a breeze if you are running an SMTP server on the same server as your web. We weren't and so had to install an SMTP agent. The relevant configuration directives (in the php.ini file) are these:
;;;;;;;; ; MAIL ; ;;;;;;;; [mail function] SMTP = ;for win32 only sendmail_from = ;for win32 only sendmail_path = /usr/sbin/sendmail ;typical sendmail path for Linux distros sendmail_path = /usr/local/sbin/sendmail ;typical sendmail path for bsd
We were running Linux Web Servers (now replaced with FreeBSD) which had no configured mail package. Soooo.... we had to install and run at least an SMTP mail server 'cos PHP mail needs a sendmail wrapper program and our standard mail package did not have one that runs between hosts. For lots of reasons we did not want to run our normal mail software on our web server. So we looked around for a suitable e-mail package with an eye mostly for ease of configuration but with the possibility of implementing the e-mail solution more widely in the future.
We reviewed sendmail (the 'de facto' standard but too much documentation and too complicated for our trivial requirement), qmail (better but no simple explanation to configure as SMTP only) and then we stumbled across postfix and it was up and running within 24 hours. We had to make some configuration changes but the parameters are very well documented and exceptionally logical so it took very little effort. Very impressive. It even puts the sendmail wrapper application in the right place so we did not have to change the php.ini file at all!! In fact the sum total or our PHP changes to implement mail was nil. Now that's what we call integration.
<warning> We upgraded to Postfix 2.1.1 and everything stopped working. Seems as if you have to supply a -t argument to sendmail so your php.ini file must now look like this.
sendmail_path = /usr/sbin/sendmail -t ;postfix sendmail path
We could find nothing about this in the documentation. </warning>
Until we have completed our proposed extensions to PHP our 'mail this page' function only works with a mailed page reference (Click 'mail this page' at the top of the screen to see the actual interface). The mail function consists of two php pages:
When you click the 'mail this page' feature is calls mailpage.php (use save as in your browser) without parameters. This page responds with a POST'ed form which, when submitted, calls 'mailthispage.php' (below). Its a classic HTML form page and as such could have been standard HTML - however during our early attempts at defeating the abusers we used a trivial date and time based psuedo-cookie (hidden field of random) which worked for a number of months - but proved totally inadequate against serious hackers.
The mail function for 'mail this page' calls 'mailthispage.php' (use save as in your browser) which mails the page, shows the user what was mailed and offers to return the user back to their original page.
The mail function for 'mail us', 'bug Reports' or 'Feed back' calls 'mail.php' (use save as in your browser) which uses a hidden field to construct a valid to: email address, mails the item, shows the user what was mailed and offers to return the user back to their original page.
Both 'mail.php' and 'mailthispage.php' now contain error checking to avoid abuse and spam injection. We briefly thought that since mail.php only returns mail to us it was not vulnerable to injection attacks, but since both cc: and bcc: fields could be added to the content - each with many addresses - by the time we saw the first email there could be many thousands of spam mail sent. The function bad_stuff takes an array containing all the form fields that are used in constructing the email and performs the following checks:
bad_stuff function:
// legal checks function bad_stuff($strarr){ // $strarr is an array with $from and $to as first entries (for email address check) // check email addresses look valid $s = "invalid email address"; if(preg_match('#^[a-z0-9.!\#$%&\'*+-/=?^_`{|}~]+@([0-9.]+|([^\s]+\.+[a-z]{2,6}))$#si', $strarr[0])){ if(preg_match('#^[a-z0-9.!\#$%&\'*+-/=?^_`{|}~]+@([0-9.]+|([^\s]+\.+[a-z]{2,6}))$#si', $strarr[1])){ $s = "suspect injection - mail rejected"; // if no user agent brobably did not come from a browser - fail if(isset($_SERVER['HTTP_USER_AGENT'])){ // if not using post method - kill it if($_SERVER['REQUEST_METHOD'] == "POST"){ // injection header check $headers = Array("content-type:","mime-version:", "multipart/mixed","Content-Transfer-Encoding:","bcc:","cc:","to:"); $s = ""; foreach($strarr as $txt){ foreach($headers as $bad) { if(strpos(strtolower($txt),$bad) !== false) { $s = "suspect injection - mail rejected"; return $s; } } } } } } } return $s; }
Notes:
To capture the modules just click 'save as' a php module in an appropriate directory. If you are using netscape (4.x) you may have to 'copy' and 'paste' into a suitable text editor.
You are right the modules mailpage.php and mailthispage.php should have their names swapped to make more sense! Satisfied.
We just made a number of changes to the PHP mail() function call to add "\r\n\" at the end of each section (was just "\n") and "\r\n\r\n" to the end of the header section to prevent SMTP injection problems. We also added MIME-Version: and Content-Type: parameters to the header since we will be adding MTML versions of the mail function One Day Real Soon™.
Parameter-less calls
The 'mail this page' is a parameter-less call since the calling page is available via the use of the CGI environmental variable $HTTP_REFERRER (available to SSI, PHP and any CGI environment). We also use this variable in the hidden form to take the user back to the original calling page (see below).
Common Mail Page
All mail requests are processed by the same PHP module through the use of two hidden elements embedded in the forms. The following example will serve to illustrate the technique:
<form name="mailForm" method="post" action="/cgi/mail.php"> <input type="hidden" name="op" value="m"> <input type="hidden" name="s" value="<!--#echo var="HTTP_REFERER" -->"> <table border="0" width="100%"> <tr> <td width="120" valign="middle" align="right"></td> <td>(<font color="#FF0000">*</font> denotes required field in form below)</font></td> </tr> <tr> <td valign="middle" align="right">First Name <font color="#FF0000">*</font>:</td> <td><INPUT type="text" name="fname" size="50"></td> </tr> <tr> <td valign="middle" align="right">Last Name <font color="#FF0000">*</font>:</td> <td><INPUT type="text" name="lname" size="50"></td> </tr> <tr> <td valign="middle" align="right">E-Mail <font color="#FF0000">*</font>:</td> <td><INPUT type="text" name="email" size="50"></td> </tr> <tr> <td valign="middle" align="right">Comment:</td> <td><TEXTAREA name="comments" rows=10 cols=50></TEXTAREA></td> </tr> <tr> <td></td> <td> <input type="submit" VALUE="Send"> <!--#if expr="${isJS}" --> <input type="reset" VALUE="Clear" onClick="clearform();"> <!--#endif --> </td> </tr> </table> </FORM>
The hidden element 'op' has a unique value used by mail.php (use save as in your browser) to indicate the type of form and hence what names may be present, what destination to send to etc.
The hidden element 's' is used to pass on the calling page via an SSI echo directive. When the mail form is returned this variable can be formatted to return the user to the page they were on when they took the deviation.
The 'reset' button is conditionally generated using an SSI only if the user has a Javascript enabled browser (for a full explanation of how we generate the 'isJS' variable). Using a similar technique we generate the Javascript function to clear the form:
<!--#if expr="${isJS}" --> <script language="JavaScript1.2"> function clearform() { document.fname = ""; document.lname = ""; document.email = ""; document.comments = ""; } </script> <!--#endif -->
The more observant (or those just awake) may notice that this form does no vetting of supplied parameters. If we were to add any (and one day, real soon now, we will!!) we could add the code to this Javascript function.
Briefly on the subject of vetting (or parameter checking). We don't as we have said. Our reasons apart from laziness are these:
Problems, comments, suggestions, corrections (including broken links) or something to add? Please take the time from a busy life to 'mail us' (at top of screen), the webmaster (below) or info-support at zytrax. You will have a warm inner glow for the rest of the day.
Tech Stuff
If you are happy it's OK - but your browser is giving a less than optimal experience on our site. You could, at no charge, upgrade to a W3C standards compliant browser such as Firefox
Search
Share
Page
Resources
HTML Stuff
W3C HTML 4.01
HTML5 (WHATWG)
HTML4 vs HTML5
HTML5 Reference
W3C Page Validator
W3C DOCTYPE
CSS Stuff
W3C CSS2.1
W3C CSS2.2
Default Styles
CSS3 Selectors
CSS 3 Media Queries
CSS 3 Colors
DOM Stuff
W3C DOM
W3C DOM 3 Core
W3C 3 Events
Accessibility
usability.gov
W3C - WAI
Web Style Guide
WebAim.org
Useful Stuff
Peter-Paul Koch
A List Apart
Eric Meyer on CSS
glish.com
Our Stuff
Our DOM Pages
DOM Navigation
Liquid Layout
CSS Short Cuts
CSS overview
CSS One Page
Javascript Stuff
Site
Copyright © 1994 - 2024 ZyTrax, Inc. All rights reserved. Legal and Privacy |
site by zytrax hosted by javapipe.com |
web-master at zytrax Page modified: January 20 2022. |