diff --git a/gregui/admin.py b/gregui/admin.py
index d5ea59b0fcf2cf68ccd9aeb3737e09cf4c2c2962..7c3f771755952b78e409029ce4c17be9bd6412eb 100644
--- a/gregui/admin.py
+++ b/gregui/admin.py
@@ -1,11 +1,17 @@
 from django.contrib import admin
 from reversion.admin import VersionAdmin
 
-from gregui.models import GregUserProfile
+from gregui.models import EmailTemplate, GregUserProfile
 
 
 class GregUserProfileAdmin(VersionAdmin):
     pass
 
 
+class EmailTemplateAdmin(VersionAdmin):
+    list_display = ["id", "template_key", "subject", "from_email"]
+    save_as = True
+
+
 admin.site.register(GregUserProfile, GregUserProfileAdmin)
+admin.site.register(EmailTemplate, EmailTemplateAdmin)
diff --git a/gregui/mailutils.py b/gregui/mailutils.py
index 19795179783c9b54b8b60652045159895fa2618b..9ccbe5e3dad930357c69fb3c261253afc0034d73 100644
--- a/gregui/mailutils.py
+++ b/gregui/mailutils.py
@@ -1,41 +1,64 @@
+from typing import Union
 from django.conf import settings
-from django.template.loader import render_to_string
+from django.template.context import Context
 from django_q.tasks import async_task
 
+from gregui.models import EmailTemplate
 
-def registration_template(institution, sponsor) -> str:
-    keywords = {
-        "institution": institution,
-        "sponsor": sponsor,
-        "registration_link": "www.google.com",
-    }
-    return render_to_string("guest_registration.txt", keywords)
 
+def prepare_arguments(
+    template: EmailTemplate, context: dict[str, str], mail_to: str
+) -> dict[str, Union[str, list[str]]]:
+    """Combine input to a dict ready for use as arguments ti django's send_mail"""
+    return {
+        "subject": template.get_subject(context),
+        "message": template.get_body(context),
+        "from_email": template.from_email or None,
+        "recipient_list": [mail_to],
+    }
 
-def confirmation_template(guest) -> str:
-    keywords = {"guest": guest, "confirmation_link": "www.google.com"}
-    return render_to_string("sponsor_confirmation.txt", keywords)
 
+def registration_template(
+    institution: str, sponsor: str, mail_to: str
+) -> dict[str, Union[str, list[str]]]:
+    """
+    Prepare email for registration
 
-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],
+    Produces a complete set of arguments ready for use with django.core.mail.send_mail
+    when sending a registration email to the guest.
+    """
+    template = EmailTemplate.objects.get(
+        template_key=EmailTemplate.EmailType.GUEST_REGISTRATION
+    )
+    context = Context(
+        {
+            "institution": institution,
+            "sponsor": sponsor,
+            "registration_link": "www.google.com",
         }
     )
+    return prepare_arguments(template, context, 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],
-        }
+def confirmation_template(guest: str, mail_to: str) -> dict[str, Union[str, list[str]]]:
+    """
+    Prepare email for confirmation
+
+    Produces a complete set of arguments ready for use with django.core.mail.send_mail
+    when sending a confirmation email to the sponsor.
+    """
+    template = EmailTemplate.objects.get(
+        template_key=EmailTemplate.EmailType.SPONSOR_CONFIRMATION
     )
+    context = Context({"guest": guest, "confirmation_link": "www.google.com"})
+    return prepare_arguments(template, context, mail_to)
+
+
+def send_registration_mail(mail_to: str, sponsor: str) -> str:
+    arguments = registration_template(settings.INSTANCE_NAME, sponsor, mail_to)
+    return async_task("django.core.mail.send_mail", **arguments)
+
+
+def send_confirmation_mail(mail_to: str, guest: str) -> str:
+    arguments = confirmation_template(guest, mail_to)
+    return async_task("django.core.mail.send_mail", **arguments)
diff --git a/gregui/migrations/0002_emailtemplate.py b/gregui/migrations/0002_emailtemplate.py
new file mode 100644
index 0000000000000000000000000000000000000000..15c4b7b6a3c3b1fe58631cb3b613f54d40eb736e
--- /dev/null
+++ b/gregui/migrations/0002_emailtemplate.py
@@ -0,0 +1,48 @@
+# Generated by Django 3.2.8 on 2021-11-02 12:49
+
+import dirtyfields.dirtyfields
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("gregui", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="EmailTemplate",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("created", models.DateTimeField(auto_now_add=True)),
+                ("updated", models.DateTimeField(auto_now=True)),
+                (
+                    "template_key",
+                    models.CharField(
+                        choices=[
+                            ("guest_registration", "Guest Registration"),
+                            ("sponsor_confirmation", "Sponsor Confirmation"),
+                        ],
+                        max_length=64,
+                        unique=True,
+                    ),
+                ),
+                ("subject", models.CharField(blank=True, max_length=255, null=True)),
+                ("from_email", models.CharField(blank=True, max_length=255, null=True)),
+                ("body", models.TextField(blank=True, null=True)),
+            ],
+            options={
+                "abstract": False,
+            },
+            bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model),
+        ),
+    ]
diff --git a/gregui/models.py b/gregui/models.py
index 48b579bed9dae968c69c4e84f5ebce32171b7cd6..551b20f8127c5a265b39f69b027381ef99a25292 100644
--- a/gregui/models.py
+++ b/gregui/models.py
@@ -1,3 +1,4 @@
+from django import template
 from django.conf import settings
 from django.db import models
 from django.utils.translation import gettext_lazy
@@ -24,3 +25,34 @@ class GregUserProfile(BaseModel):
         null=True,
     )
     userid_feide = models.CharField(gettext_lazy("userid-feide"), max_length=150)
+
+
+class EmailTemplate(BaseModel):
+    """
+    Stores templates for emails.
+
+    Only one template of each type is allowed. To introduce new ones, simply add a new
+    EmailType.
+    """
+
+    class EmailType(models.TextChoices):
+        """Types of Emails"""
+
+        GUEST_REGISTRATION = "guest_registration"
+        SPONSOR_CONFIRMATION = "sponsor_confirmation"
+
+    template_key = models.CharField(
+        max_length=64, choices=EmailType.choices, unique=True
+    )
+    subject = models.CharField(max_length=255, blank=True, null=True)
+    from_email = models.CharField(max_length=255, blank=True, null=True)
+    body = models.TextField(blank=True, null=True)
+
+    def get_rendered_template(self, tpl, context):
+        return template.Template(tpl).render(context)
+
+    def get_subject(self, context):
+        return self.get_rendered_template(self.subject, context)
+
+    def get_body(self, context):
+        return self.get_rendered_template(self.body, context)
diff --git a/gregui/tests/conftest.py b/gregui/tests/conftest.py
index fc70bdca4858316b191b6c1d1e7b7860363521a3..2e34c790b013086e4e3241c54fa396779a37e1b3 100644
--- a/gregui/tests/conftest.py
+++ b/gregui/tests/conftest.py
@@ -19,7 +19,7 @@ from greg.models import (
     Sponsor,
 )
 
-from gregui.models import GregUserProfile
+from gregui.models import EmailTemplate, GregUserProfile
 
 # faker spams the logs with localisation warnings
 # see https://github.com/joke2k/faker/issues/753
@@ -256,3 +256,33 @@ def log_in(client):
         return client
 
     return _log_in
+
+
+@pytest.fixture
+def confirmation_template():
+    et = EmailTemplate.objects.create(
+        template_key=EmailTemplate.EmailType.SPONSOR_CONFIRMATION,
+        subject="confirmation subject",
+        body="""Dette er en automatisk generert melding fra gjesteregistreringstjenesten.
+Din gjest, {{ guest }}, har fullført registrering, bekreft gjesten her: {{ confirmation_link }}
+
+This message has been automatically generated by the guest registration system.
+Your guest, {{ guest }}, has completed their registration, please confirm the guest here: {{ confirmation_link }}""",
+    )
+    return EmailTemplate.objects.get(id=et.id)
+
+
+@pytest.fixture
+def registration_template():
+    et = EmailTemplate.objects.create(
+        template_key=EmailTemplate.EmailType.GUEST_REGISTRATION,
+        subject="registration subject",
+        body="""Dette er en automatisk generert melding fra gjesteregistreringstjenesten.
+Du har blitt registrert som gjest på {{ institution }} av {{ sponsor }}.
+For å fullføre registreringen av gjestekontoen følg denne lenken: {{ registration_link }}
+
+This message has been automatically generated by the guest registration system.
+You have been registered as a guest at {{ institution }} by {{ sponsor }}.
+To complete the registration of your guest account, please follow this link: {{ registration_link }}""",
+    )
+    return EmailTemplate.objects.get(id=et.id)
diff --git a/gregui/tests/test_mailutils.py b/gregui/tests/test_mailutils.py
index 03f30f3de2d4604859dbf5e1945e47a0830faf4e..7977f4cfac3568e8064c65ebe7d273035d941234 100644
--- a/gregui/tests/test_mailutils.py
+++ b/gregui/tests/test_mailutils.py
@@ -6,33 +6,43 @@ from gregui import mailutils
 
 
 @pytest.mark.django_db
-def test_registration_template():
-    prefilled_template = """Dette er en automatisk generert melding fra gjesteregistreringstjenesten.
+def test_registration_template(registration_template):
+    prefilled_template = {
+        "from_email": None,
+        "recipient_list": ["test@example.com"],
+        "subject": "registration subject",
+        "message": """Dette er en automatisk generert melding fra gjesteregistreringstjenesten.
 Du har blitt registrert som gjest på InstanceName av Foo Bar.
 For å fullføre registreringen av gjestekontoen følg denne lenken: www.google.com
 
 This message has been automatically generated by the guest registration system.
 You have been registered as a guest at InstanceName by Foo Bar.
-To complete the registration of your guest account, please follow this link: www.google.com
-"""
-    rendered_template = mailutils.registration_template("InstanceName", "Foo Bar")
+To complete the registration of your guest account, please follow this link: www.google.com""",
+    }
+    rendered_template = mailutils.registration_template(
+        "InstanceName", "Foo Bar", "test@example.com"
+    )
     assert rendered_template == prefilled_template
 
 
 @pytest.mark.django_db
-def test_confirmation_template():
-    prefilled_template = """Dette er en automatisk generert melding fra gjesteregistreringstjenesten.
+def test_confirmation_template(confirmation_template):
+    prefilled_template = {
+        "from_email": None,
+        "recipient_list": ["test@example.com"],
+        "subject": "confirmation subject",
+        "message": """Dette er en automatisk generert melding fra gjesteregistreringstjenesten.
 Din gjest, Foo Bar, har fullført registrering, bekreft gjesten her: www.google.com
 
 This message has been automatically generated by the guest registration system.
-Your guest, Foo Bar, has completed their registration, please confirm the guest here: www.google.com
-"""
-    rendered_template = mailutils.confirmation_template("Foo Bar")
+Your guest, Foo Bar, has completed their registration, please confirm the guest here: www.google.com""",
+    }
+    rendered_template = mailutils.confirmation_template("Foo Bar", "test@example.com")
     assert rendered_template == prefilled_template
 
 
 @pytest.mark.django_db
-def test_registration_mail():
+def test_registration_mail(registration_template):
     mail.outbox = []
     task_id = mailutils.send_registration_mail("test@example.no", "Foo")
     assert result(task_id) == 1
@@ -41,7 +51,7 @@ def test_registration_mail():
 
 
 @pytest.mark.django_db
-def test_confirmation_mail():
+def test_confirmation_mail(confirmation_template):
     mail.outbox = []
     task_id = mailutils.send_confirmation_mail("test@example.no", "Foo")
     assert result(task_id) == 1