diff --git a/app/auth/views/mfa.py b/app/auth/views/mfa.py
index b6430d44..f04f8bde 100644
--- a/app/auth/views/mfa.py
+++ b/app/auth/views/mfa.py
@@ -16,6 +16,7 @@ from wtforms import BooleanField, StringField, validators
from app.auth.base import auth_bp
from app.config import MFA_USER_ID, URL
from app.db import Session
+from app.email_utils import send_email, render
from app.extensions import limiter
from app.models import User, MfaBrowser
@@ -91,6 +92,12 @@ def mfa():
return response
else:
+ send_email(
+ user.email,
+ "There was an unsuccessful login on your SimpleLogin account",
+ render("transactional/invalid-totp-login.txt"),
+ render("transactional/invalid-totp-login.html"),
+ )
flash("Incorrect token", "warning")
# Trigger rate limiter
g.deduct_limit = True
diff --git a/templates/emails/transactional/invalid-totp-login.html b/templates/emails/transactional/invalid-totp-login.html
new file mode 100644
index 00000000..9dd1942e
--- /dev/null
+++ b/templates/emails/transactional/invalid-totp-login.html
@@ -0,0 +1,10 @@
+{% extends "base.html" %}
+
+{% block content %}
+ {{ render_text("There has been an unsuccessful login on your SimpleLogin account.") }}
+ {{ render_text("An invalid TOTP code was provided. The email and password were provided correctly.") }}
+
+ {{ render_text("If this was not you, please change your password immediately.") }}
+ {{ render_text('Thanks,
SimpleLogin Team.') }}
+{% endblock %}
+
diff --git a/templates/emails/transactional/invalid-totp-login.txt b/templates/emails/transactional/invalid-totp-login.txt
new file mode 100644
index 00000000..c0f4e62a
--- /dev/null
+++ b/templates/emails/transactional/invalid-totp-login.txt
@@ -0,0 +1,7 @@
+There has been an unsuccessful login on your SimpleLogin account.
+An invalid TOTP code was provided. The email and password were provided correctly.
+
+If this was not you, please change your password immediately.
+
+Thanks,
+SimpleLogin Team.