While writing server code for resend confirmation page something came to my mind: an attacker could make several requests to /resendemail?user=blah (example URL) and flood such user with registration emails (of course, as long as the user exists and hasn't confirmed their email).

My first idea was to limit request per-session, however, this can be bypassed very easily. Per-IP limit is too much trouble too implement and can be bypassed too (i.e. using several proxies), so I'm confident there must be something simple enough to mitigate this sort of exploit.

  • I think this can be mitigated the same way I prevent flood registration, which is by using CAPTCHAs.
    – Nacib Neme
    Commented Mar 1, 2015 at 20:04

4 Answers 4


Rate-limit on a per-user or per-email-address basis. Since re-sending confirmation emails is rare, setting the limit absurdly low (say, two re-sends per day) should be sufficient to keep from flooding a user.


Add a time stamp to the email field, if an email has been resent in the last x minutes do not send another email. I would not use a captcha as bots are better at solving those than humans are anyway.

  • Depending on the captcha, you are correct. Currently, there is one type of captcha (with images and text) that hasn't been cracked using computer power. Commented Mar 2, 2015 at 12:23

At work, I've implemented a very rudimentar and basic system to a contact form.

Each IP is only allowed to send 5-9 emails a day (random number generated by IP).

You can adapt this and add some options to (for example), allow only 1 or 2 per day in case the user asks it in a somewhat constant manner.

Or block at all and only allow to resend if a specific code is introduced.

You send a recovery code with a specific link.

Then that person visits the link, introduces the code and only then the person can actually recover the password.

  • Why would you randomly assign a limit?
    – Jon
    Commented Mar 2, 2015 at 6:23
  • @Chipperyman So that no one has a fixed number of tries. An automated script to make requests might blindly request 200 codes. This way, only a very few requests will make it through. This helped to minimize the ammount of spam we were getting on one of our systems (where I've implemented the random limit). I've found it to work quite well. Some may disagree, but I'm happy with the result. Commented Mar 2, 2015 at 9:16
  • 3
    @IsmaelMiguel How exactly random limit is better than fixed one?
    – Cthulhu
    Commented Mar 2, 2015 at 11:28
  • @Cthulhu I'll try to explain in a different way: Imagine that a system gives 10 attemps a day. You can write a code that will send 10 tries. Then it bails out and uses another IP to try more 10 tries. Imagine that now, you don't have a fixed limit. Your limit is randomly betwen 5 and 10. You can send the 10 tries, but up to 5 tries will be complete waste. And then, you have to change to a different IP just to try to hit half the times, and repeat. Sure, you can just go and use 5 tries, but is it really worth to aim for low? Unless it is something worthy, no one (sane) will do this. Right? Commented Mar 2, 2015 at 12:22
  • So just make the limit 5 then. It's not worth for attacker to aim that low, right?
    – domen
    Commented Mar 2, 2015 at 13:15

In addition to rate limiting, you can make your email infrastructure report back to your app whether the email was accepted by the destination server or not; and rate-limit only if the emails are getting delivered successfully.

A nice advantage of this method is that your app can tell the user whether the email they sent actually got through and is waiting for them in their inbox or if they should try a different email address.

  • There are a number of ways that an email could be accepted by the destination without ending up in the end-user's mailbox, such as if the email was deleted by a spam or virus filter.
    – Mark
    Commented Mar 2, 2015 at 10:33
  • @Mark that's why I said rate limit and not outright block further sending of mails.
    – user42178
    Commented Mar 2, 2015 at 11:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .