Page 1 of 1
preventing multiple form submissions
Posted: Thu Mar 26, 2009 5:25 pm
by oboedrew
I'm trying to prevent multiple submissions of a "contact me" form. Most of the solutions I've found online involve javascript, but I don't want to rely on users having javascript enabled. I have an idea how to do this, but I want to run it by you guys and see if it is a common and reliable approach.
The current version works like this:
The script contact-me.html (I use .htaccess to have html pages parsed for php so that I can still use the .html extension) displays a form with method="post" and action="contact-me.html". When the submit button is clicked, the script does a series of checks to filter user input. If all the input is clean, then the message is sent via mail(), and a "message sent" page is displayed. The problem with this method is that the same script displays the form and generates the email, so if a user clicks the button several time in a row I get several duplicate emails.
Here's the solution I'm considering:
I'd start the script the same way, with contact-me.html displaying a form and then filtering input. But if the input passes all checks, I would store it in session variables and redirect to message-sent.html, where the info in the session variables would be used to construct an email with mail(), the session variables would be unset, and then a "message sent" page would be displayed.
It seems this would eliminate the problem of multiple submissions, since clicking the submit button does not actually run a script that generates and sends an email, but instead redirects to a separate script that generates and sends an email. Is this sort of approach common? Am I overlooking any security concerns?
Thanks,
Drew
Re: preventing multiple form submissions
Posted: Thu Mar 26, 2009 7:00 pm
by requinix
When the script creates the form have it generate a unique identifier and attach it to the form.
When the script receives the form have it store the identifier in sessions.
If the identifier already exists in $_SESSION then don't send the mail.
Code: Select all
<?php
session_start();
if (!isset($_SESSION["contact form ids"])) $_SESSION["contact form ids"] = array();
if (form was submitted) {
$unique = $_POST["unique"];
if (isset($_SESSION["contact form ids"][$unique])) {
don't send mail
} else {
$_SESSION["contact form ids"][$unique] = 1;
send mail
}
}
?>
...
<input type="hidden" name="unique" value="<?php echo uniqid(time()); ?>">
...
(There are a billion ways of doing this: here is one)
Re: preventing multiple form submissions
Posted: Thu Mar 26, 2009 7:15 pm
by deejay
redirecting to another page, with a success msg etc is a pretty common way of solving this problem.
Re: preventing multiple form submissions
Posted: Thu Mar 26, 2009 7:23 pm
by oboedrew
Thanks, guys. I will play around with both of these methods.
Cheers,
Drew
Re: preventing multiple form submissions
Posted: Sun Mar 29, 2009 2:47 pm
by phpbaby2009
deejay, I agree with you. I am facing similar problems.
I want users to submit news and information which are stored to a flat file. I'm still googling but can't seem to solve all of these:
1) Remove the submit FORM from browser's search History,
if NOT
Reset all form values to zero when user comes back either by typing the address
or back button.
2) Allow a limited number of form submissions.
Any thoughts ?
Re: preventing multiple form submissions
Posted: Tue Jun 16, 2009 8:41 pm
by oboedrew
I need to resurrect this topic for further advice. Several months ago I implemented this method of preventing multiple form submissions. The script that creates the form and does the validation doesn't send the message. Instead, it stores the info in session variables and then redirects to a new script that actually sends a message generated from those session variables. I tested it several months ago by sending messages to myself through the contact form, and I found that no matter how many times I clicked the submit button, and no matter how rapidly I clicked it, I still received only one message. But something has gone wrong, as I'm now receiving duplicate form submissions. I'll attach the code below. Any ideas?
Here's contact-me.html (the script that displays the form and validates the info submitted through the form)
Code: Select all
<?php
ob_start();
include('../includes/session-start.txt');
$title='Contact Me';
include('../includes/header.txt');
if(!isset($_POST['submitted'])){
$caption='Questions? Comments? Just want to talk shop? Drop me a line.';
include('../includes/contact-me.txt');
}else{
$_POST['name']=trim($_POST['name']);
$_POST['name']=preg_replace('# {2,}#', ' ', $_POST['name']);
$_POST['name']=htmlentities($_POST['name'], ENT_QUOTES, 'UTF-8');
$_POST['email']=trim($_POST['email']);
$_POST['email']=htmlentities($_POST['email'], ENT_QUOTES, 'UTF-8');
$_POST['email_again']=trim($_POST['email_again']);
$_POST['email_again']=htmlentities($_POST['email_again'], ENT_QUOTES, 'UTF-8');
$_POST['message']=trim($_POST['message']);
$_POST['message']=preg_replace('# {2,}#', ' ', $_POST['message']);
$_POST['message']=htmlentities($_POST['message'], ENT_QUOTES, 'UTF-8');
if(empty($_POST['name']) || empty($_POST['email']) || empty($_POST['email_again']) || empty($_POST['message'])){
$caption='Oops! You left a field empty.';
include('../includes/contact-me.txt');
}elseif(preg_match('#[^A-Za-z ]#', $_POST['name'])){
$caption='Oops! Name contains prohibited character(s). Only letters and spaces allowed.';
include('../includes/contact-me.txt');
}elseif($_POST['email']!=$_POST['email_again']){
$caption='Oops! Emails don\'t match.';
include('../includes/contact-me.txt');
}elseif(!preg_match('#^[A-Za-z0-9-_.]+@[A-Za-z0-9-_.]+\.[A-Za-z]{2,6}$#D', $_POST['email'])){
$caption='Oops! Email not valid.';
include('../includes/contact-me.txt');
}else{
$_SESSION['name']=html_entity_decode($_POST['name'], ENT_QUOTES, 'UTF-8');
$_SESSION['email']=html_entity_decode($_POST['email'], ENT_QUOTES, 'UTF-8');
$_SESSION['message']=html_entity_decode($_POST['message'], ENT_QUOTES, 'UTF-8');
ob_end_clean();
header('location: http://www.oboedrew.com/message-sent.html');
exit();
}
}
include('../includes/footer.txt');
ob_end_flush();
?>
Here's contact-me.txt (the form, which is an inc file)
Code: Select all
<div class="content">
<h2>Contact Me</h2>
<p> </p>
<p><?php echo$caption; ?></p>
<p> </p>
<form method="post" action="http://www.oboedrew.com/contact-me.html">
<p><label for="name">name:</label></p>
<p><input id="name" name="name" type="text" maxlength="40" value="<?php echo$_POST['name']; ?>" /></p>
<p> </p>
<p><label for="email">email:</label></p>
<p><input id="email" name="email" type="text" maxlength="40" value="<?php echo$_POST['email']; ?>" /></p>
<p> </p>
<p><label for="email_again">email again:</label></p>
<p><input id="email_again" name="email_again" type="text" maxlength="40" value="<?php echo$_POST['email_again']; ?>" /></p>
<p> </p>
<p><label for="message">message:</label></p>
<p><textarea id="message" name="message" rows="10" cols="1"><?php echo$_POST['message']; ?></textarea></p>
<p> </p>
<p><input id="button" type="submit" value="send" /><input type="hidden" name="submitted" value="1" /></p>
</form>
</div>
And here's message-sent.html (the script that actually sends the message)
Code: Select all
<?php
ob_start();
include('../includes/session-start.txt');
if(!isset($_SESSION['name']) || !isset($_SESSION['email']) || !isset($_SESSION['message'])){
$title='404 Not Found';
include('../../includes/header.txt');
include('../../includes/404.txt');
include('../../includes/footer.txt');
}else{
$title='Message Sent';
include('../includes/header.txt');
$_SESSION['message']=wordwrap($_SESSION['message'], 70, "\n", true);
mail('Drew Keller <drewkeller@oboedrew.com>', 'message sent through oboedrew.com', $_SESSION['message'], "From: {$_SESSION['name']} <{$_SESSION['email']}>", '-f drewkeller@oboedrew.com');
unset($_SESSION['name']);
unset($_SESSION['email']);
unset($_SESSION['message']);
echo"\n\t\t\t".
"<div class=\"content\">\n\t\t\t\t".
"<h2>Message Sent</h2>\n\t\t\t\t".
"<p> </p>\n\t\t\t\t".
"<p>Thanks for contacting me. I'll reply soon.</p>\n\t\t\t".
"</div>"
;
include('../includes/footer.txt');
}
ob_end_flush();
?>
Thanks in advance for any tips!
Cheers,
Drew
Re: preventing multiple form submissions
Posted: Thu Jun 18, 2009 12:41 pm
by oboedrew
Any ideas?
Thanks,
Drew
Re: preventing multiple form submissions
Posted: Fri Jun 19, 2009 12:22 pm
by Eric!
Drew, you are relying on the behavior of the browser to control your form. Did you update your browser since you last tried this? The browser apparently is no longer caching the session data once, but now fully resends with each post request.
The best fix is to use php sessions to control multiple posts as suggested by tasairis.
Re: preventing multiple form submissions
Posted: Sat Jun 20, 2009 7:07 pm
by oboedrew
Ah, I did update several of my browsers. I guess that explains why it worked before but doesn't work now. I remember not really understanding tasairis's post back when I first created this thread, but I'm a little more php-savvy now, so I'll review it and probably it'll make more sense to me now.
Thanks,
Drew