diff --git a/pkg/config/config.go b/pkg/config/config.go index b81cda4..68e94b5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -50,7 +50,11 @@ const ( ResetPasswordRedisKey = "reset-password/%s" ChangeEmailRedisKey = "change-email/%s" SignupTokenExpires = 24 * time.Hour // used for all tokens so far - EmailDebounceExpires = 24 * time.Hour // how to rate limit duplicate mail being sent + + // How to rate limit same types of emails being delivered, e.g. + // signups, cert approvals (double post), etc. + EmailDebounceDefault = 24 * time.Hour // default debounce per type of email + EmailDebounceResetPassword = 4 * time.Hour // "forgot password" emails debounce // Rate limits RateLimitRedisKey = "rate-limit/%s/%s" // namespace, id diff --git a/pkg/controller/account/reset_password.go b/pkg/controller/account/reset_password.go index f866776..6a787a0 100644 --- a/pkg/controller/account/reset_password.go +++ b/pkg/controller/account/reset_password.go @@ -135,17 +135,25 @@ func ForgotPassword() http.HandlerFunc { return } - // Email them their reset link. - if err := mail.Send(mail.Message{ - To: user.Email, - Subject: "Reset your forgotten password", - Template: "email/reset_password.html", - Data: map[string]interface{}{ - "Username": user.Username, - "URL": config.Current.BaseURL + "/forgot-password?token=" + token.Token, - }, - }); err != nil { - session.FlashError(w, r, "Error sending an email: %s", err) + // Email them their reset link -- if not banned. + if !user.IsBanned() { + if err := mail.LockSending("reset_password", user.Email, config.EmailDebounceResetPassword); err == nil { + if err := mail.Send(mail.Message{ + To: user.Email, + Subject: "Reset your forgotten password", + Template: "email/reset_password.html", + Data: map[string]interface{}{ + "Username": user.Username, + "URL": config.Current.BaseURL + "/forgot-password?token=" + token.Token, + }, + }); err != nil { + session.FlashError(w, r, "Error sending an email: %s", err) + } + } else { + log.Error("LockSending: reset_password e-mail is not sent to %s: one was sent recently", user.Email) + } + } else { + log.Error("Do not send 'forgot password' e-mail to %s: user is banned", user.Email) } // Success message and redirect away. diff --git a/pkg/controller/account/signup.go b/pkg/controller/account/signup.go index c045172..f34790a 100644 --- a/pkg/controller/account/signup.go +++ b/pkg/controller/account/signup.go @@ -145,7 +145,7 @@ func Signup() http.HandlerFunc { if user.IsBanned() { log.Error("Do not send signup e-mail to %s: user is banned", email) } else { - if err := mail.LockSending("signup", email, config.EmailDebounceExpires); err == nil { + if err := mail.LockSending("signup", email, config.EmailDebounceDefault); err == nil { err := mail.Send(mail.Message{ To: email, Subject: "You already have a nonshy account", diff --git a/pkg/controller/photo/certification.go b/pkg/controller/photo/certification.go index b2c0194..cae76fc 100644 --- a/pkg/controller/photo/certification.go +++ b/pkg/controller/photo/certification.go @@ -434,7 +434,7 @@ func AdminCertification() http.HandlerFunc { } // Notify the user via email. - if err := mail.LockSending("cert_rejected", user.Email, config.EmailDebounceExpires); err == nil { + if err := mail.LockSending("cert_rejected", user.Email, config.EmailDebounceDefault); err == nil { if err := mail.Send(mail.Message{ To: user.Email, Subject: "Your certification photo has been denied", @@ -507,7 +507,7 @@ func AdminCertification() http.HandlerFunc { } // Notify the user via email. - if err := mail.LockSending("cert_approved", user.Email, config.EmailDebounceExpires); err == nil { + if err := mail.LockSending("cert_approved", user.Email, config.EmailDebounceDefault); err == nil { if err := mail.Send(mail.Message{ To: user.Email, Subject: "Your certification photo has been approved!",