boogdesign posts

Longer posts on standards based web design, portable web development and Linux, intermingled with some stuff on my other nerd interests.

Rob Crowther, London, UK based Blogger, Web Developer, Web Designer and System Administrator - read my Curriculum Vitae

Buy my book!

Book CoverHello! HTML5 and CSS3 available now

Buy my other book!

Book CoverEarly access to HTML5 in Action available now
« IE8 Beta 1 - A Review :: Web Development for the Blackberry Pearl »

Fixing Jack's formmail.php for register_globals = off


11:37:49 pm Permalink Fixing Jack's formmail.php for register_globals = off

Categories: Server Side Web Development

For many years now, I've used various versions of Jack's FormMail.php to handle simple form submissions on various websites, mostly 'contact us' forms. The script has gotten a little more sophisticated with time, but it's still one of the simpler ways of making a website 'interactive.'

The website at work uses it to send the marketing department emails when someone fills in the contact us form. The form is somewhat sophisticated, in that it presents different information depending on a few parameters in the URL, and passes formmail.php a different subject for the email depending on what configuration it's in. It also passes a redirect URL in a hidden field, so the user is redirected to a 'thanks for contacting us' page after submitting the form. Google Analytics is set up so that any hits on the 'thanks' page after viewing the contact page counts as a Goal. And this is where I spotted the problem - as I checked through the Analytics stats I noticed we hadn't achieved any goals since the middle of last week, although a day or two here and there without any is fairly common five on the trot is pretty rare.

My first step was to go to the contact form and try submitting it, the email duly arrived in the correct mailbox but the script didn't redirect to the thanks page. So first mystery solved, no hits on the thanks page means no goals on Analytics, but the marketing department hadn't noticed because they were still getting emails. I messed around with some of the different configurations of the contact page but none of them redirected as intended. Then I realised that all the emails had the same subject, and that was the default one given by formmail.php when it doesn't get passed a subject, though the values in the form fields were appearing in the email correctly, so it wasn't like the information wasn't getting passed though.

I checked the web host's page and discovered that they had recently updated the PHP config on the server, this in order to support PHP v5. There was a new option in CPanel to select the default version of PHP, so I went and set it to v4 in case formmail was incompatible with the newer release. It didn't make any difference though, so I started looking at formmail.php itself in detail.

The first thing I noticed was that the redirect functionality required register_globals to be enabled. Although my PHP configuration page claimed that register_globals was enabled, the behaviour of the script indicated that it wasn't. Unsurprisingly, the subject field also expected register_globals to be enabled, as did several other fields which I wasn't using, but the code which builds the email uses $HTTP_POST_VARS so works fine without.

If you've managed to read this far without falling asleep and you know what register_globals is, then you now have enough information to fix the problem yourself and there's no need to torture yourself any further. If you currently have no idea what I'm on about, I'm now going to try and explain and then show you how to edit your script to fix the problem. register_globals is a configuration setting for the PHP interpreter, if it's set to on then PHP will helpfully make any parameters passed into the script global variables. Parameters are the bits in the URL after the question mark, or fields in a form. This can be quite handy when you're slapping together a quick script, but is also very dangerous because, if you're not careful, you can create easy opportunities for hackers to do nasty things. For this reason, register_globals = on has long been discouraged in the PHP community, unfortunately many useful scripts were written in the days before anyone realised it was an issue, so web hosts usually provide a way turn it back on even if it's not enabled by default.

However, today we're going to make formmail.php work properly with register_globals = off. You're going to need to open the formmail.php script in a text editor - Notepad will do fine. First we shall fix the redirect issue, find the following lines near the end of the file:

if ($redirect) {
   header("Location: $redirect");

We're going to replace $redirect, which is trying to access the global variable, with $_POST['redirect'], like so:

if (isset($_POST['redirect'])) {
   header("Location: ". $_POST['redirect']);

The same trick works with the subject and email address, scroll up a few lines and find this:

mail_it(stripslashes($content), ($subject)?stripslashes($subject):"Form Submission", $email, $recipient); 

Replace it with:

mail_it(stripslashes($content), isset($_POST['subject'])?stripslashes($_POST['subject']):"Form Submission", $_POST['email'], $recipient);

Now upload your new version to the server and you should find things start working as before. As you can see the general rule is to replace $variable with $_POST['variable'], notice that I didn't change $recipient because I always hard code that value at the top of the script as a security precaution.

Tweet this!


Comment from: Rebecca [Visitor]
22/03/08 @ 05:45
You also have to replace the HTTP_POST_VARS with $_POST because HTTP_POST_VARS isn't supported.
Comment from: robertc [Member] ·
22/03/08 @ 10:03
Thanks for pointing that out Rebecca - I think it is still supported in PHP5 but you have to turn it on explicitly in php.ini (see also this excellent blog post to turn it back on in .htaccess).
Comment from: Clayton Moore [Visitor]
03/04/08 @ 21:14
Thank you! I have been troubleshooting this formmail for weeks. Once I applied the above mentioned corrections, as well as the $_POST replacement, the webform transmitted the form fields, which it did not send before. I am utilizing a webhosting company running PHP version 5. I sincerely appreciate post like these, it saved a huge headache.

For reference to anyone else. My form did send email and subject - however my form fields such as customer name, phone number and comments did not come through email.

Comment from: robertc [Member] ·
04/04/08 @ 02:02
Hi Clayton, thanks for taking the time to make a comment, I'm glad I could help!
Comment from: geekgirly [Visitor]
26/04/08 @ 00:22
THANK YOU. FROM THE BOTTOM OF MY GEEK HEART. For those of you hosting with siteground, this is an EXCELLENT fix. You completely ROCK, Robert. My headaches are gone over this issue.
Comment from: robertc [Member] ·
26/04/08 @ 16:50
No problem geekgirly, glad I could help. This blog post certainly seems to have hit on common issue :)
Comment from: Jason [Visitor] ·
28/04/08 @ 03:39
Hey Robert,
Great stuff. That first peice of code squashed the redirect issue I was having. Many kudos to you!!!

Comment from: Al [Visitor]
04/05/08 @ 03:27
Thanks, that fixed up exactly my problem!
Moved to PHP 5 server which broke the script, and now it works. Thanks :)
Comment from: Dan Wilkinson [Visitor] ·
21/05/08 @ 14:41
Thanks for these tips...they work great. I appears that the "Required Fields" functionality of the script still doesn't work though...any ideas?
Comment from: robertc [Member] ·
21/05/08 @ 18:04
The required fields are a bit more complicated, because they're subject to some processing. The lines you need to worry about are these ones:
if ($required)
$require = $required;
// handle the required fields
if ($require) {
// seperate at the commas
$require = ereg_replace( " +", "", $require);
$required = split(",",$require);
I've not tested this, so beware, but I think it should look something like :
// handle the required fields
if (isset($_POST['require'])|isset($_POST['required'])) {
// seperate at the commas
$require = ereg_replace( " +", "", isset($_POST['required'])?$_POST['required']:$_POST['require']);
$required = split(",",$require);
The if logic doesn't work when $require is no longer a global variable, so you have to munge that a bit, but you don't have to replace every instance of $require and $required because the variables get re-assigned in the lines above. Give it a go and see how it works, but keep a backup of your original because, as I said above, this is just off the top of my head and I've not tried it in a working script.


PS. I've tested it now (several hours later) and updated the code above (got a few brackets wrong), seems to work OK.
Comment from: Dan Wilkinson [Visitor] ·
28/05/08 @ 05:41
Awesome! Thanks!
Comment from: Florian [Visitor]
29/05/08 @ 09:50
Anyone knows how to fix the file upload? THANK YOU!
Comment from: David Fulp [Visitor]
10/06/08 @ 23:06
I'm now receiving DUPLICATE (2) emails of every submission... everything else is working great... thanks to all for your help... any ideas on fixing the dupes?

Comment from: robertc [Member] ·
10/06/08 @ 23:17
Can you get see the headers of the emails you're receiving? This might be under 'details' or 'properties' or something like that. That should indicate why you're getting two of everything, possibly you're just adding the same email address in two places.

Comment from: Balitas [Visitor]
17/06/08 @ 23:19
In my case not work the redirect only. Help please robertc I do all the things you mentioned but not work for me :( Check and fill the form below. Here my php info:
Comment from: robertc [Member] ·
17/06/08 @ 23:36
Hi Balitas. Can you post what you have at in your formmail.php from the if (isset($_POST['redirect'])) { line onwards?

Comment from: Balitas [Visitor]
18/06/08 @ 16:04
Sure :)

if (isset($_POST['redirect'])) {
header("Location: ".$_POST['redirect']);
Comment from: robertc [Member] ·
18/06/08 @ 18:00
Hmm, can't see anything obvious wrong. Are you getting any error messages in the logs? One thing you can try, if you don't have to redirect to different pages for different forms, is simply to hardcode the redirect. Take the whole if condition out and just end the script with:
Comment from: Balitas [Visitor]
19/06/08 @ 18:46
Dear robertc unfortunately not work :(

Please download the formmail.php here to test it.

Comment from: robertc [Member] ·
23/06/08 @ 23:40
Hi Balitas - what's happened is, you've fixed the wrong $redirect, scroll right to the bottom of the script, line 410, and make the changes with isset and $_POST['redirect'] there.

Comment from: Balitas [Visitor]
24/06/08 @ 17:43
Is still works as I mentioned.

Comment from: robertc [Member] ·
02/07/08 @ 00:18
Hi Balitas, sorry it took me so long to get round to updating my blog again. When you applied the fix to the lines further down you forget to change the if ($redirect) to if (isset($_POST['redirect'])) - everything else was correct!

Comment from: Rachael [Visitor] ·
06/08/08 @ 15:48
Great fix. Never could understand why form worked great with some clients and not redirect to "Thank You" page with others. Realize now it's a hosting issue and can easily be fixed! This just saved me a ton of time :)
Comment from: Colin Jones [Visitor] ·
07/09/08 @ 14:30
Thanks for this - - it was driving me crazy! The only thing I can't get to work is the 'required' section. I am only requiring 2 fields, name and email, but by adding the fix above I always get an error screen saying both fields are missing, even if they are filled in. Any ideas?
Comment from: robertc [Member] ·
08/09/08 @ 23:39
Hi Colin. One of the many posts I have sitting in draft status addresses that very issue, as I had to fix it for a site of my own a few weeks ago. I'm going to try and get caught up with my posts this week so please check back in a few days.

Comment from: ryan [Visitor] ·
19/09/08 @ 00:47
Hi Rob, did you ever get that draft finished? I would love to know how to fix the require part of the script.

Comment from: Joan [Visitor] ·
22/09/08 @ 19:59
Hi Rob, thanks a lot for this fix now I can use my formmail again with globals off, just one little detail, Ive used to have on every end of each form something called enviroment variables, like this:

------ eviromental variables ------
BROWSER: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)

now with this fix, thats not showing up with every submission, any ideas?
Comment from: Joan [Visitor] ·
22/09/08 @ 20:06
It also stop sending attachments! Help!
Comment from: Margaret [Visitor]
06/10/08 @ 01:32
This seems kind of silly. Instead of giving it to us one variable at a time, could someone PLEASE link to a zip version that works properly?

Thanks so much!
Comment from: jOSE [Visitor] · http://WWW.DELTAASESORES.COM
30/10/08 @ 03:04
Great advice, but still need some help with the missing-fields-redirect and being able to change the referers since I change referers according to the form.
Comment from: Bob [Visitor]
06/11/08 @ 15:32
Comment from: Jason [Visitor]
06/11/08 @ 15:56

I'm using Yahoo hosting and found that I never receive ANY messages sent from the form although it does go to "thanknote" page after I submit the form. I looked at the FAQs on Yahoo and it only makes me more confused..

Has anybody use formmail.php successfully with Yahoo hosting?
Comment from: robertc [Member] ·
07/11/08 @ 14:42
Hi Jason. Have a look at this forum post. It says that the sender (From field) must be a valid Yahoo address.
Comment from: Sander [Visitor]
09/11/08 @ 11:25
You saved my live with this :-)

Nut I've still got the redirect_missing_field problem (redirects always to this)... Is there anyone who solved this yet??
Comment from: ryan [Visitor] ·
13/11/08 @ 23:19
Hey all. See link provided for a fully function version of formmail with register_globals off. I found it online, hosting it on my site. Just uncomment the first part about register_globals. Enjoy!

Comment from: robertc [Member] ·
14/11/08 @ 14:05
Thanks for finding that Ryan. You should note that the script is 'fixed' in the sense that it effectively re-enables the register globals code using import_request_variables() function - so it makes the script once again vulnerable to the class of security problems which were the reason for turning it off in the first place.

Comment from: ryan [Visitor]
18/11/08 @ 04:22
Hi Rob. Thanks for the info, so not really a fix at all I guess. However a solution for my purposes which is all I need. I'll keep checking back though, would love to use your updated script but it's still missing some of the main functionality.

Comment from: SuperjakkoTM [Visitor] ·
03/02/09 @ 18:33
Excellent. I kept reading the config pdf over and over again wondering if I was missing something out and in the end it was the code at fault. Thanks so much for taking the time to fix something like this that is simply an act of kindness.
Comment from: Nick [Visitor]
05/02/09 @ 05:09
Almost a year later and you saved my night! Originally found this post without redirect working or receiving an email from it- fixed both. Only problem though, I'm receiving blank emails. Any help for the rookie over here? Thanks!
Comment from: Nick [Visitor]
05/02/09 @ 19:16
Fixed now. Used the "replace the HTTP_POST_VARS with $_POST" advice from one of the comments, purrs like a lion.

Thanks so much, who knows how much more hair I would have lost trying to fix this!
Comment from: steve [Visitor]
10/02/09 @ 17:57
thank you - my formmail had stopped working correctly and although the hosting co denied any changes, obviously the register_globals had been switched off - I was wasting hours trying to figure out what was up. Your posting solved all my issues including - missing field redirect-

thanks again
Comment from: Jenn [Visitor]
24/02/09 @ 18:39
Please help! I am using the formmail.php form and I receive 2 blank emails everytime I submit the form. What am I doing wrong. This is my first time using this form and I am a php novice.

Thank you
Comment from: Fred [Visitor] ·
07/03/09 @ 18:19
Hi, thanks I was able to get the form working again with these changes however I can't get the form to validate or send file attachments. Any ideas?

Thanks again! I was losing my mind over why this wasn't working!
Comment from: Ken [Visitor] ·
14/03/09 @ 01:12
Hi, Form works great, but the resulting email arrive without any details in the SENDER field.. so some email clients or spam filters reject the resulting email.. how do I add a sender? the formmail.asp version used to do that..

Regards, Ken
Comment from: Cody [Visitor]
18/03/09 @ 16:25
To get the script from sending duplicate email to the recipient, remove this line:
$headers .= "To: ".$recipient."\n";
Comment from: Adam [Visitor]
15/05/09 @ 18:40
Just found this post as I have used formmail for many years.. However, I am getting a recipient error message when sending my forms.. The script is stating it has not valid reciepient and I recently went to php5 at my host.. can you elaborate on how to make the necessary changes for recipients.
Comment from: Bob [Visitor]
05/06/09 @ 15:31
Thank you so much, I've been pounding my head with this and your fixes solved all of my problems! Great Name btw!
Comment from: Narelle [Visitor] ·
10/06/09 @ 03:58
Hi, my form is also running well, however emails are arriving without any details in the SENDER field. I have made the alterations above, but with no joy. Thanks.

Cheers Narelle.
Comment from: siddeek [Visitor]
11/06/09 @ 00:43
Thanks for this. im a complete php noob and this was a great help. im still having trouble with the required fields throwing up a error message saying the fields are missing even when filled in. I cant find the post you mentioned to fix this. Can you point me in the right direction
Comment from: Rood [Visitor]
18/06/09 @ 10:07
I went from
- no check on input but email was sent
- no check and just the subject line emailed
- script says all input is missing

so its back to the drawing board for me but this tutorial will get me there :)
Comment from: pablo [Visitor] ·
15/07/09 @ 00:43
YOU ROCK!!! Thanks for this fix! It really works!
Comment from: Anthony [Visitor] ·
30/09/09 @ 13:38
Hi guys,

Been trying to get Formmail to work for months... I can receive emails with the information just fine but I want to do a redirect to my own html page. I've tried all the hacks in this thread and still no luck. Could someone please help me out? I'm a php noob so make no assumptions.
Comment from: claudia [Visitor] ·
07/10/09 @ 18:41
Hello Robert!
I made the changes above but still having problems.. same as as Balitas.. Can I email you my form mail so you can take a peak? Thanks in advance
Comment from: Jim [Visitor]
02/05/10 @ 00:17
Thank you, I'd forgotten that the new website used php5 when I changed servers and couldn't figure out for the life of me what was wrong.
Comment from: Chris [Visitor]
18/06/10 @ 23:39
thank you so much for the fix I have been sturggling all day
Comment from: Jason [Visitor]
09/09/10 @ 17:22
I have applied all the changes above with mixed results. Most of these fixes work. However, as stated above in a few post "the require fields don't function properly." Even if the required fields are filled out, the script still thinks they are not. Any one got a solution/way to fix this script?
Comment from: Tim [Visitor]
06/10/10 @ 08:29
I am having mixed results aswell. I changed some of the faults with the suggestions but not eveything is fixed. I cant get the required fields to work. I asked my webhosting company but they had no idea. Would anyone be interested in helping a complete novice?
Comment from: Wade [Visitor]
24/05/14 @ 23:24
Thank you for this post. I'm a PHP noob. I've tried to follow all the suggestions listed but I'm still having trouble. The form won't email the inputted information still. Can I show you my code? Please?
Comment from: Wade [Visitor]
24/05/14 @ 23:56
OK. Nevermind my previous comment. I kept working at it and figured it out. Used some of the coding listing in the other comments.

Thanks for this fix. Awesome help. I searched all over without any luck before finding this thread.

You're the best!!