diff --git a/frontend/src/components/debug/index.tsx b/frontend/src/components/debug/index.tsx
index 1097897ff8bfe539ca1899e9149ca48a07293b2c..a151d73ff3a5802c4f38a2f6df20ce995393d275 100644
--- a/frontend/src/components/debug/index.tsx
+++ b/frontend/src/components/debug/index.tsx
@@ -82,6 +82,19 @@ export const Debug = () => {
       })
   }
 
+
+  const testMail = () => {
+    fetch('/api/ui/v1/testmail/', {
+      credentials: 'same-origin',
+    })
+      .then((data) => {
+         console.log(data)
+      })
+      .catch((err) => {
+        console.log(err)
+      })
+  }
+
   const whoami = () => {
     fetch('/api/ui/v1/whoami/', {
       headers: {
@@ -151,6 +164,9 @@ export const Debug = () => {
         <Button type="button" onClick={() => logout()}>
           LOGOUT
         </Button>
+        <Button type="button" onClick={() => testMail()}>
+          SEND TEST MAIL
+        </Button>
       </Stack>
       <Box sx={{ maxWidth: '30rem' }}>
         <Table>
diff --git a/gregsite/settings/base.py b/gregsite/settings/base.py
index c6441013c29e38e9e46e85eeb419ec7c289bda5e..e6eea48ec3a5174b3b171077dea705879f06964f 100644
--- a/gregsite/settings/base.py
+++ b/gregsite/settings/base.py
@@ -46,6 +46,7 @@ INSTALLED_APPS = [
     "django_extensions",
     "django_filters",
     "mozilla_django_oidc",
+    "django_q",
     "greg",
     "gregui",
 ]
diff --git a/gregsite/settings/dev.py b/gregsite/settings/dev.py
index 403f1f10fe320a20fa8d60ae77d9cc80b866cb0f..0305521fb351dcb4632836bbd7d980c2b79193bc 100644
--- a/gregsite/settings/dev.py
+++ b/gregsite/settings/dev.py
@@ -15,6 +15,17 @@ ORGREG_CLIENT = {
     "headers": {"X-Gravitee-Api-Key": "bar"},
 }
 
+Q_CLUSTER = {
+    "name": "greg",
+    "workers": 4,
+    "timeout": 90,
+    "retry": 120,
+    "queue_limit": 50,
+    "bulk": 10,
+    "orm": "default",
+    "sync": True,
+}
+
 AUTHENTICATION_BACKENDS = [
     "gregui.authentication.auth_backends.DevBackend",  # Fake dev backend
     "django.contrib.auth.backends.ModelBackend",  # default
diff --git a/gregui/mailutils.py b/gregui/mailutils.py
index 30187aaf73fcec8090921f83e5b95a2b36a8eb48..19795179783c9b54b8b60652045159895fa2618b 100644
--- a/gregui/mailutils.py
+++ b/gregui/mailutils.py
@@ -1,6 +1,6 @@
 from django.conf import settings
-from django.core.mail import send_mail
 from django.template.loader import render_to_string
+from django_q.tasks import async_task
 
 
 def registration_template(institution, sponsor) -> str:
@@ -17,19 +17,25 @@ def confirmation_template(guest) -> str:
     return render_to_string("sponsor_confirmation.txt", keywords)
 
 
-def send_registration_mail(mail_to, sponsor) -> int:
-    return send_mail(
-        subject="Subject",
-        message=registration_template(settings.INSTANCE_NAME, sponsor),
-        from_email=None,
-        recipient_list=[mail_to],
+def send_registration_mail(mail_to, sponsor) -> str:
+    return async_task(
+        "django.core.mail.send_mail",
+        **{
+            "subject": "Subject",
+            "message": registration_template(settings.INSTANCE_NAME, sponsor),
+            "from_email": None,
+            "recipient_list": [mail_to],
+        }
     )
 
 
-def send_confirmation_mail(mail_to, guest) -> int:
-    return send_mail(
-        subject="Subject",
-        message=confirmation_template(guest),
-        from_email=None,
-        recipient_list=[mail_to],
+def send_confirmation_mail(mail_to, guest) -> str:
+    return async_task(
+        "django.core.mail.send_mail",
+        **{
+            "subject": "Subject",
+            "message": confirmation_template(guest),
+            "from_email": None,
+            "recipient_list": [mail_to],
+        }
     )
diff --git a/gregui/tests/test_mailutils.py b/gregui/tests/test_mailutils.py
index 25391f5d12898a832f6da139a94f77fb47f46e1a..03f30f3de2d4604859dbf5e1945e47a0830faf4e 100644
--- a/gregui/tests/test_mailutils.py
+++ b/gregui/tests/test_mailutils.py
@@ -1,4 +1,5 @@
 from django.core import mail
+from django_q.tasks import result
 
 import pytest
 from gregui import mailutils
@@ -33,7 +34,8 @@ Your guest, Foo Bar, has completed their registration, please confirm the guest
 @pytest.mark.django_db
 def test_registration_mail():
     mail.outbox = []
-    assert mailutils.send_registration_mail("test@example.no", "Foo") == 1
+    task_id = mailutils.send_registration_mail("test@example.no", "Foo")
+    assert result(task_id) == 1
     assert len(mail.outbox) == 1
     assert mail.outbox[0].to == ["test@example.no"]
 
@@ -41,6 +43,7 @@ def test_registration_mail():
 @pytest.mark.django_db
 def test_confirmation_mail():
     mail.outbox = []
-    assert mailutils.send_confirmation_mail("test@example.no", "Foo") == 1
+    task_id = mailutils.send_confirmation_mail("test@example.no", "Foo")
+    assert result(task_id) == 1
     assert len(mail.outbox) == 1
     assert mail.outbox[0].to == ["test@example.no"]
diff --git a/gregui/urls.py b/gregui/urls.py
index 56e17df61e6251dd7d569ba4d0a64892b440298c..cc6fa884e2da3bc3a1884dcb83b4382a0f0ac9f9 100644
--- a/gregui/urls.py
+++ b/gregui/urls.py
@@ -17,6 +17,7 @@ urlpatterns: List[URLResolver] = [
     path("api/ui/v1/logout/", views.logout_view, name="api-logout"),
     path("api/ui/v1/login/", views.login_view, name="api-login"),
     path("api/ui/v1/session/", views.SessionView.as_view(), name="api-session"),
+    path("api/ui/v1/testmail/", views.send_test_email, name="api-testmail"),
     path("api/ui/v1/whoami/", views.WhoAmIView.as_view(), name="api-whoami"),
     path("api/ui/v1/userinfo/", UserInfoView.as_view()),  # type: ignore
     path("api/ui/v1/ous/", OusView.as_view()),
diff --git a/gregui/views.py b/gregui/views.py
index 0801eda1a1f60441677b32e47484ec1970e1b1fd..2bf3fc9d8c59fccfc5a75fe5ae29685e34e2a23b 100644
--- a/gregui/views.py
+++ b/gregui/views.py
@@ -8,6 +8,7 @@ from rest_framework.views import APIView
 
 from greg.models import Role, Sponsor
 from greg.permissions import IsSponsor
+from gregui import mailutils
 from gregui.models import GregUserProfile
 
 
@@ -37,6 +38,11 @@ def login_view(request):
     return redirect("/api/ui/v1/whoami/")
 
 
+def send_test_email(request):
+    mailutils.send_registration_mail("test@example.no", "Foo Bar")
+    return JsonResponse({"detail": "Created task to send test mail."})
+
+
 class SessionView(APIView):
     authentication_classes = [SessionAuthentication, BasicAuthentication]
     permission_classes = [IsAuthenticated]
diff --git a/poetry.lock b/poetry.lock
index 0943957de6dd8d05c85dd11b8282f2f0e5d02b79..c44130e8e57d7010ca5e935b877cb28fdfbe6414 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,3 +1,11 @@
+[[package]]
+name = "ansicon"
+version = "1.89.0"
+description = "Python wrapper for loading Jason Hood's ANSICON"
+category = "main"
+optional = false
+python-versions = "*"
+
 [[package]]
 name = "appnope"
 version = "0.1.2"
@@ -6,6 +14,17 @@ category = "dev"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "arrow"
+version = "1.2.0"
+description = "Better dates & times for Python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+python-dateutil = ">=2.7.0"
+
 [[package]]
 name = "asgiref"
 version = "3.4.1"
@@ -86,6 +105,19 @@ jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
 python2 = ["typed-ast (>=1.4.2)"]
 uvloop = ["uvloop (>=0.15.2)"]
 
+[[package]]
+name = "blessed"
+version = "1.19.0"
+description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities."
+category = "main"
+optional = false
+python-versions = ">=2.7"
+
+[package.dependencies]
+jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""}
+six = ">=1.9.0"
+wcwidth = ">=0.1.4"
+
 [[package]]
 name = "certifi"
 version = "2021.5.30"
@@ -259,6 +291,40 @@ python-versions = "*"
 [package.dependencies]
 django = ">=1.8"
 
+[[package]]
+name = "django-picklefield"
+version = "3.0.1"
+description = "Pickled object field for Django"
+category = "main"
+optional = false
+python-versions = ">=3"
+
+[package.dependencies]
+Django = ">=2.2"
+
+[package.extras]
+tests = ["tox"]
+
+[[package]]
+name = "django-q"
+version = "1.3.9"
+description = "A multiprocessing distributed task queue for Django"
+category = "main"
+optional = false
+python-versions = ">=3.6.2,<4"
+
+[package.dependencies]
+arrow = ">=1.1.0,<2.0.0"
+blessed = ">=1.17.6,<2.0.0"
+django = ">=2.2"
+django-picklefield = ">=3.0.1,<4.0.0"
+redis = ">=3.5.3,<4.0.0"
+
+[package.extras]
+testing = ["hiredis (>=1.0.1,<2.0.0)", "psutil (>=5.7.0,<6.0.0)", "django-redis (>=4.12.1,<5.0.0)", "iron-mq (>=0.9,<0.10)", "boto3 (>=1.14.12,<2.0.0)", "pymongo (>=3.10.1,<4.0.0)", "croniter (>=0.3.34,<0.4.0)"]
+rollbar = ["django-q-rollbar (>=0.1)"]
+sentry = ["django-q-sentry (>=0.1)"]
+
 [[package]]
 name = "django-reversion"
 version = "4.0.0"
@@ -483,6 +549,17 @@ MarkupSafe = ">=2.0"
 [package.extras]
 i18n = ["Babel (>=2.7)"]
 
+[[package]]
+name = "jinxed"
+version = "1.1.0"
+description = "Jinxed Terminal Library"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+ansicon = {version = "*", markers = "platform_system == \"Windows\""}
+
 [[package]]
 name = "josepy"
 version = "1.9.0"
@@ -919,7 +996,7 @@ test = ["coverage", "docutils", "testscenarios (>=0.4)", "testtools"]
 name = "python-dateutil"
 version = "2.8.2"
 description = "Extensions to the standard Python datetime module"
-category = "dev"
+category = "main"
 optional = false
 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
 
@@ -950,6 +1027,17 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
+[[package]]
+name = "redis"
+version = "3.5.3"
+description = "Python client for Redis key-value store"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.extras]
+hiredis = ["hiredis (>=0.1.3)"]
+
 [[package]]
 name = "regex"
 version = "2021.8.28"
@@ -1140,7 +1228,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
 name = "wcwidth"
 version = "0.2.5"
 description = "Measures the displayed width of unicode strings in a terminal"
-category = "dev"
+category = "main"
 optional = false
 python-versions = "*"
 
@@ -1166,13 +1254,21 @@ python-versions = "*"
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.9"
-content-hash = "3733c24aefbb0889d6071468bd42582689c50ce9903937f94b922997fc4a8f23"
+content-hash = "b964658143e61764cbb714c40fe6227158d260a426c2722ff84f813421f12d24"
 
 [metadata.files]
+ansicon = [
+    {file = "ansicon-1.89.0-py2.py3-none-any.whl", hash = "sha256:f1def52d17f65c2c9682cf8370c03f541f410c1752d6a14029f97318e4b9dfec"},
+    {file = "ansicon-1.89.0.tar.gz", hash = "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1"},
+]
 appnope = [
     {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"},
     {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"},
 ]
+arrow = [
+    {file = "arrow-1.2.0-py3-none-any.whl", hash = "sha256:8fb7d9d3d4bf90e49e734c22fa077bdd0964135c4b8120de2510575a8d1f620c"},
+    {file = "arrow-1.2.0.tar.gz", hash = "sha256:16fc29bbd9e425e3eb0fef3018297910a0f4568f21116fc31771e2760a50e074"},
+]
 asgiref = [
     {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
     {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
@@ -1197,6 +1293,10 @@ black = [
     {file = "black-21.8b0-py3-none-any.whl", hash = "sha256:2a0f9a8c2b2a60dbcf1ccb058842fb22bdbbcb2f32c6cc02d9578f90b92ce8b7"},
     {file = "black-21.8b0.tar.gz", hash = "sha256:570608d28aa3af1792b98c4a337dbac6367877b47b12b88ab42095cfc1a627c2"},
 ]
+blessed = [
+    {file = "blessed-1.19.0-py2.py3-none-any.whl", hash = "sha256:1f2d462631b2b6d2d4c3c65b54ef79ad87a6ca2dd55255df2f8d739fcc8a1ddb"},
+    {file = "blessed-1.19.0.tar.gz", hash = "sha256:4db0f94e5761aea330b528e84a250027ffe996b5a94bf03e502600c9a5ad7a61"},
+]
 certifi = [
     {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
     {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
@@ -1329,6 +1429,8 @@ cryptography = [
     {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34dae04a0dce5730d8eb7894eab617d8a70d0c97da76b905de9efb7128ad7085"},
     {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b"},
     {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:9965c46c674ba8cc572bc09a03f4c649292ee73e1b683adb1ce81e82e9a6a0fb"},
+    {file = "cryptography-3.4.8-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c4129fc3fdc0fa8e40861b5ac0c673315b3c902bbdc05fc176764815b43dd1d"},
+    {file = "cryptography-3.4.8-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:695104a9223a7239d155d7627ad912953b540929ef97ae0c34c7b8bf30857e89"},
     {file = "cryptography-3.4.8-cp36-abi3-win32.whl", hash = "sha256:21ca464b3a4b8d8e86ba0ee5045e103a1fcfac3b39319727bc0fc58c09c6aff7"},
     {file = "cryptography-3.4.8-cp36-abi3-win_amd64.whl", hash = "sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc"},
     {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d2a6e5ef66503da51d2110edf6c403dc6b494cc0082f85db12f54e9c5d4c3ec5"},
@@ -1365,6 +1467,14 @@ django-log-request-id = [
     {file = "django-log-request-id-1.6.0.tar.gz", hash = "sha256:0126f5da0cacc62cf834efb3cf66e4606031d911ccff048da2f88fe2c0bbcbc9"},
     {file = "django_log_request_id-1.6.0-py3-none-any.whl", hash = "sha256:c3f7f53b1fc92f62269c247bee14d578daab000a2f7ae70b70ae288b603b5907"},
 ]
+django-picklefield = [
+    {file = "django-picklefield-3.0.1.tar.gz", hash = "sha256:15ccba592ca953b9edf9532e64640329cd47b136b7f8f10f2939caa5f9ce4287"},
+    {file = "django_picklefield-3.0.1-py3-none-any.whl", hash = "sha256:3c702a54fde2d322fe5b2f39b8f78d9f655b8f77944ab26f703be6c0ed335a35"},
+]
+django-q = [
+    {file = "django-q-1.3.9.tar.gz", hash = "sha256:5c6b4d530aa3aabf9c6aa57376da1ca2abf89a1562b77038b7a04e52a4a0a91b"},
+    {file = "django_q-1.3.9-py3-none-any.whl", hash = "sha256:1b74ce3a8931990b136903e3a7bc9b07243282a2b5355117246f05ed5d076e68"},
+]
 django-reversion = [
     {file = "django-reversion-4.0.0.tar.gz", hash = "sha256:ad6d714b4b9b824e22b88d47201cc0f74b5c4294c8d4e1f8d7ac7c3631ef3188"},
     {file = "django_reversion-4.0.0-py3-none-any.whl", hash = "sha256:f059c654e38c0dd8dccd7f0990aa2f6d9ad22dab55c5e095f9596aeda8079dcd"},
@@ -1433,6 +1543,10 @@ jinja2 = [
     {file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"},
     {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"},
 ]
+jinxed = [
+    {file = "jinxed-1.1.0-py2.py3-none-any.whl", hash = "sha256:6a61ccf963c16aa885304f27e6e5693783676897cea0c7f223270c8b8e78baf8"},
+    {file = "jinxed-1.1.0.tar.gz", hash = "sha256:d8f1731f134e9e6b04d95095845ae6c10eb15cb223a5f0cabdea87d4a279c305"},
+]
 josepy = [
     {file = "josepy-1.9.0-py2.py3-none-any.whl", hash = "sha256:49798be66a467e7c81f071fe5ff03ac5e37c6d7081933612259028496bb05a68"},
     {file = "josepy-1.9.0.tar.gz", hash = "sha256:51cce8d97ced0556aae0ce3161b26d5f0f54bc42c749d3c606edc6d97d9802dc"},
@@ -1773,6 +1887,10 @@ pyyaml = [
     {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
     {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
 ]
+redis = [
+    {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"},
+    {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"},
+]
 regex = [
     {file = "regex-2021.8.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2"},
     {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a"},
diff --git a/pyproject.toml b/pyproject.toml
index de3569b75f655aff15beb71d8916c63c1d8db8ca..9d78cee33085524aa154086a7b0b97686b95f3a8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,6 +24,7 @@ whitenoise = "*"
 django-reversion = "*"
 django-sesame = {extras = ["ua"], version = "^2.4"}
 mozilla-django-oidc = "^2.0.0"
+django-q = "^1.3.9"
 
 [tool.poetry.dev-dependencies]
 Faker = "*"