5

Basically I created a page to send a mail to restore your password. The problem is that after you fill in all the information and it has sent the mail it will continue to send emails everytime you refresh the page. The only solution I can think of is to open a different page with

header("Location: index.php");

Or something which would be fine I guess but are there other solutions? I found something about unsetting all variables for instance but I really don't know how viable that is

Crecket
  • 718
  • 2
  • 7
  • 24
  • 4
    Sessions and tokens. – Funk Forty Niner Mar 23 '15 at 15:54
  • A workaround I can think of is that you could separate the code that initiate the form from the code that process it (and sends the email) with a redirect in it. Therefore, the URL that make the email to be sent is never shown. Please note that is a **workaround** that is not bullet-proof. – D4V1D Mar 23 '15 at 15:55
  • When a user has performed an action, redirect them to another page. Look at [Post/Redirect/Get](https://en.wikipedia.org/wiki/Post/Redirect/Get) for some ideas around this. – TZHX Mar 23 '15 at 15:56
  • 1
    The only solution you can think of is the correct and recommended solution. – Marek Mar 23 '15 at 16:03
  • Here's that link about sessions and tokens http://phpro.org/tutorials/Preventing-Multiple-Submits.html – Funk Forty Niner Mar 23 '15 at 16:04

5 Answers5

4

Crecket, may we see your code? Because I'm affraid you are adding your PHP code into your webpage. When you put the action into the HTML file, everytime the page reloads, the PHP code is re-executed.

To prevent the PHP code from be re-executed, you have to separate it from the HTML files. This way, no matter how many times the user refreshes the page, the PHP code won't execute unless the user presses the submit button. I will give you and example of this separation :

send.php

<?php
session_start();
?>
<html>
  <head>
    <title>Session</title>
  </head>
  <body>
<?php
if ( IsSet( $_SESSION[ "message_sent" ] ) )
   { echo "Your message was sent.";
     unset( $_SESSION[ "message_sent" ] );
   }
?>
    <form method="post" action="email.php">
      Enter message
      <input type="text" name="anything" />
      <input type="submit" value="Send email" />
    </form>
  </body>
</html>

email.php

<?php
session_start();
// SEND MESSAGE HERE.
$_SESSION[ "message_sent" ] = "message sent";
header( "Location: send.php" );
?>

Copy and paste previous codes in two files with the given names, then run send.php from your browser. Send one message. Then refresh the page as many times as you want and you will see, the PHP code won't reexecute so the email won't be resent.

Hope this helps you.

  • 1
    I only recently started with php so I didn't even realize I should put pieces of code outside of the main form like that. Thanks :) – Crecket Mar 23 '15 at 16:17
  • "session_start(): Cannot send session cache limiter - headers already sent" is the error I get right now. I tried creating 2 pages like you suggested: http://pastebin.com/M2EgP2cJ and http://pastebin.com/pzbXyneA – Crecket Mar 23 '15 at 16:49
  • The file "email.php" must send email only, do not add display messages or anything else. – Jose Manuel Abarca Rodríguez Mar 23 '15 at 16:51
  • So I use sessions to check if it was sent and than set the variables for the message on the send.php page? – Crecket Mar 23 '15 at 16:53
  • Oh one more thing, for some reason it kept giving that error and I tried removing session_start(); from the send.php page and it suddenly started working. Can I only have 1 session open or something? – Crecket Mar 23 '15 at 17:24
  • Don't remove session_start, we REALLY need it. Just don't display anything. Remove every echo, printf and anything else that sends data to the screen. – Jose Manuel Abarca Rodríguez Mar 23 '15 at 17:25
  • http://pastebin.com/giSY1KLc here is the send page right now, I added a 2 new session variables for the error/success messages if that could be it? – Crecket Mar 23 '15 at 17:40
  • We need to see if db_connect.php displays a message. Also try this : erase all your code, then add one line (of your previous code), compile, if everything is ok, add another line, compile . . . and so on until we detect the problem line. – Jose Manuel Abarca Rodríguez Mar 23 '15 at 17:44
  • db_connect only sets the login variables. Ill check line by line whats wrong now though, ill respond when if i find it. O and maybe its the mail message itself? I'm using a html message so that might be it? – Crecket Mar 23 '15 at 17:49
  • 1
    No. The error you got, "headers already sent", means you are displaying something or doing a header somewhere, or something like that. Try line by line and we will see... – Jose Manuel Abarca Rodríguez Mar 23 '15 at 17:53
  • Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at /var/www/vh63701/293/crecketgaming.com/forgotinfoPHP.php:1) in /var/www/vh63701/293/crecketgaming.com/forgotinfoPHP.php on line 2 Is the error I get when I litteraly only have session_start(); at the top and nothing else. Could it be something from the previous page? – Crecket Mar 23 '15 at 17:55
  • Ok nevermind I found it... I googled the error and someone suggested checking if there was no space infront of – Crecket Mar 23 '15 at 17:57
2

Like Fred said, sessions are good solution here. Pseudo code below

session_start();
if(!isset($_SESSION['mail_sent'])) {
    mail('someaddresss'...);
    $_SESSION['mail_sent'] = true;
}
Machavity
  • 30,841
  • 27
  • 92
  • 100
  • 2
    It took me a while to find it in my scripts, but this is the link I've used in the past http://phpro.org/tutorials/Preventing-Multiple-Submits.html which I've given the OP also ;-) thanks for the mention btw. – Funk Forty Niner Mar 23 '15 at 16:06
  • @Fred-ii- Thanks! Will be using that in all my forms :) – Crecket Mar 23 '15 at 16:59
1

If you use a nonce field in the form, the same form submission will not be processed twice. The general idea is to generate a token that can only be used once. Once a form has been submitted with a valid token, the token becomes invalid.

Creating nonces is fairly easy to do: How to create and use nonces

Mathew Tinsley
  • 6,805
  • 2
  • 27
  • 37
1

Possible solution would be to have two pages. One with PHP code in it that sends the email that user and another that says the email was sent.

Use a cookie on the first webpage with the email. Immediately once that page loads, it sends the email. You next use the header("Location: http://www.somewhereelse.com/); to send the user to another page. On the next page, it removes the cookie or changes it.

That way, if the user clicks the back button or the refresh, it doesn't send the email again because the email cookie is missing.

dakab
  • 5,379
  • 9
  • 43
  • 67
White Lotus
  • 353
  • 2
  • 6
  • 16
0

You can make a redirect without actually using seperate files:

//form.php
<?php
if($_POST){
    //form processing code here
    //redirect to self
    header("Location: ./form.php");
    exit();
}
Steve
  • 20,703
  • 5
  • 41
  • 67