diff --git a/hc/accounts/decorators.py b/hc/accounts/decorators.py
new file mode 100644
index 00000000..5c253136
--- /dev/null
+++ b/hc/accounts/decorators.py
@@ -0,0 +1,47 @@
+from functools import wraps
+import secrets
+
+from django.core.signing import TimestampSigner, SignatureExpired
+from django.shortcuts import redirect, render
+from hc.lib import emails
+
+
+def _session_unsign(request, key, max_age):
+    if key not in request.session:
+        return None
+
+    try:
+        return TimestampSigner().unsign(request.session[key], max_age=max_age)
+    except SignatureExpired:
+        pass
+
+
+def require_sudo_mode(f):
+    @wraps(f)
+    def wrapper(request, *args, **kwds):
+        assert request.user.is_authenticated
+
+        # is sudo mode active and has not expired yet?
+        if _session_unsign(request, "sudo", 1800) == "active":
+            return f(request, *args, **kwds)
+
+        # has the user submitted a code to enter sudo mode?
+        if "sudo_code" in request.POST:
+            ours = _session_unsign(request, "sudo_code", 900)
+            if ours and ours == request.POST["sudo_code"]:
+                request.session.pop("sudo_code")
+                request.session["sudo"] = TimestampSigner().sign("active")
+                return redirect(request.path)
+
+        if not _session_unsign(request, "sudo_code", 900):
+            code = "%06d" % secrets.randbelow(1000000)
+            request.session["sudo_code"] = TimestampSigner().sign(code)
+            emails.sudo_code(request.user.email, {"sudo_code": code})
+
+        ctx = {}
+        if "sudo_code" in request.POST:
+            ctx["wrong_code"] = True
+
+        return render(request, "accounts/sudo.html", ctx)
+
+    return wrapper
diff --git a/hc/lib/emails.py b/hc/lib/emails.py
index d62d82bb..79bbcf0d 100644
--- a/hc/lib/emails.py
+++ b/hc/lib/emails.py
@@ -92,3 +92,7 @@ def sms_limit(to, ctx):
 
 def call_limit(to, ctx):
     send("phone-call-limit", to, ctx)
+
+
+def sudo_code(to, ctx):
+    send("sudo-code", to, ctx)
diff --git a/templates/accounts/sudo.html b/templates/accounts/sudo.html
new file mode 100644
index 00000000..1fcccefa
--- /dev/null
+++ b/templates/accounts/sudo.html
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div class="row">
+    <div class="col-sm-6 col-sm-offset-3">
+        <div class="hc-dialog">
+            <h1>Enter a Confirmation Code</h1>
+            <br />
+            <p>
+                We have sent a confirmation code to your email
+                address. Please enter it below to continue:
+            </p>
+
+            <form method="POST">
+                {% csrf_token %}
+
+                <div class="form-group {% if wrong_code %}has-error{% endif %}">
+                    <input
+                        class="form-control input-lg"
+                        type="text" name="sudo_code" />
+
+                    {% if wrong_code %}
+                    <div class="help-block">The entered code was not correct.</div>
+                    {% endif %}
+                </div>
+
+                <button
+                    class="btn btn-lg btn-primary btn-block"
+                    type="submit">
+                    Continue
+                </button>
+
+            </form>
+
+        </div>
+    </div>
+</div>
+
+{% endblock %}
diff --git a/templates/emails/sudo-code-body-html.html b/templates/emails/sudo-code-body-html.html
new file mode 100644
index 00000000..86e02667
--- /dev/null
+++ b/templates/emails/sudo-code-body-html.html
@@ -0,0 +1,27 @@
+{% extends "emails/base.html" %}
+{% load hc_extras %}
+
+{% block content %}
+Hello,<br />
+
+<br />
+
+We send a confirmation code before performing sensitive actions on {% site_name%}.<br />
+Your confirmation code is:<br />
+<br />
+<div style="font-family: monospace; font-weight: bold; font-size: 24px">
+    {{ sudo_code }}
+</div>
+<br />
+
+Note: this code is only valid for 15 minutes.<br />
+
+<br />
+{% endblock %}
+
+{% block content_more %}
+All the Best,<br>
+The {% site_name %} Team
+<br /><br />
+
+{% endblock %}
diff --git a/templates/emails/sudo-code-body-text.html b/templates/emails/sudo-code-body-text.html
new file mode 100644
index 00000000..873a55a3
--- /dev/null
+++ b/templates/emails/sudo-code-body-text.html
@@ -0,0 +1,12 @@
+{% load hc_extras %}
+Hello,
+
+We send a confirmation code before performing sensitive actions on {% site_name%}.
+
+Your confirmation code is: {{ sudo_code }}
+
+Note: this code is only valid for 15 minutes.
+
+--
+All the Best,
+The {% site_name %} Team
diff --git a/templates/emails/sudo-code-subject.html b/templates/emails/sudo-code-subject.html
new file mode 100644
index 00000000..f04c61bc
--- /dev/null
+++ b/templates/emails/sudo-code-subject.html
@@ -0,0 +1 @@
+Confirmation code: {{ sudo_code }}