diff --git a/gregui/api/views/invitation.py b/gregui/api/views/invitation.py
index feed09ddb0daa097bc1913cfd5c16d7292f09f72..3bfbcc0c4a5b5d90b51f8ad8ecc6f0155f323d28 100644
--- a/gregui/api/views/invitation.py
+++ b/gregui/api/views/invitation.py
@@ -23,6 +23,7 @@ from greg.models import Identity, InvitationLink, Person, Invitation
 from greg.permissions import IsSponsor
 from gregui.api.serializers.guest import GuestRegisterSerializer
 from gregui.api.serializers.invitation import InviteGuestSerializer
+from gregui.mailutils import send_invite_mail
 from gregui.models import GregUserProfile
 
 logger = logging.getLogger(__name__)
@@ -76,8 +77,7 @@ class InvitationView(CreateAPIView, DestroyAPIView):
             invitation__role__person_id=person.id,
             invitation__role__sponsor_id=sponsor_user.sponsor.id,
         )
-        # TODO: send email to invited guest
-        print(invitationlink)
+        send_invite_mail(invitationlink)
         return Response(status=status.HTTP_201_CREATED)
 
     def delete(self, request, *args, **kwargs) -> Response:
@@ -310,7 +310,6 @@ class ResendInvitationView(UpdateModelMixin, APIView):
             #     expire=timezone.now() + datetime.timedelta(days=30),
             # )
 
-            # TODO: send email to invited guest
-            print(link)
+            send_invite_mail(link)
 
         return Response(status=status.HTTP_200_OK)
diff --git a/gregui/mailutils.py b/gregui/mailutils.py
index 9ccbe5e3dad930357c69fb3c261253afc0034d73..c9bfd68f9710cb63120d5b1d30d7784a2cb9968b 100644
--- a/gregui/mailutils.py
+++ b/gregui/mailutils.py
@@ -1,13 +1,19 @@
+import logging
+
+from typing import Optional
 from typing import Union
 from django.conf import settings
 from django.template.context import Context
 from django_q.tasks import async_task
 
+from greg.models import InvitationLink
 from gregui.models import EmailTemplate
 
+logger = logging.getLogger(__name__)
+
 
 def prepare_arguments(
-    template: EmailTemplate, context: dict[str, str], mail_to: str
+        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 {
@@ -19,7 +25,7 @@ def prepare_arguments(
 
 
 def registration_template(
-    institution: str, sponsor: str, mail_to: str
+        institution: str, sponsor: str, mail_to: str
 ) -> dict[str, Union[str, list[str]]]:
     """
     Prepare email for registration
@@ -62,3 +68,18 @@ def send_registration_mail(mail_to: str, sponsor: str) -> str:
 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)
+
+
+def send_invite_mail(link: InvitationLink) -> Optional[str]:
+    email_address = link.invitation.role.person.private_email
+    sponsor = link.invitation.role.sponsor
+
+    if not email_address:
+        logger.warning(f"No e-mail address found for invitation link with ID: {link.id}")
+        return None
+
+    if not sponsor:
+        logger.warning("Unable to determine sponsor for invitation link with ID: {link.id}")
+        return None
+
+    return send_registration_mail(email_address.value, f"{sponsor.first_name} {sponsor.last_name}")