diff --git a/aleksis/apps/alsijil/data_checks.py b/aleksis/apps/alsijil/data_checks.py
index 54abf4678345b1bdb63596f19f31a4125e523cc1..679de00ee61914f8b4962a38cda5ba47f42a7bec 100644
--- a/aleksis/apps/alsijil/data_checks.py
+++ b/aleksis/apps/alsijil/data_checks.py
@@ -2,12 +2,14 @@ import logging
 
 from django.contrib.contenttypes.models import ContentType
 from django.db.models import F
+from django.db.models.aggregates import Count
 from django.utils.translation import gettext as _
 
 import reversion
 from calendarweek import CalendarWeek
+from templated_email import send_templated_mail
 
-from aleksis.core.util.core_helpers import celery_optional
+from aleksis.core.util.core_helpers import celery_optional, get_site_preferences
 
 
 class SolveOption:
@@ -97,3 +99,37 @@ def check_data():
     for check in DATA_CHECKS:
         logging.info(f"Run check: {check.verbose_name}")
         check.check_data()
+
+    if get_site_preferences()["alsijil__data_checks_send_emails"]:
+        send_emails_for_data_checks()
+
+
+def send_emails_for_data_checks():
+    """Notify one or more recipients about new problems with data.
+
+    Recipients can be set in dynamic preferences.
+    """
+    from .models import DataCheckResult  # noqa
+
+    results = DataCheckResult.objects.filter(solved=False, sent=False)
+
+    if results.exists():
+        results_by_check = results.values("check").annotate(count=Count("check"))
+
+        results_with_checks = []
+        for result in results_by_check:
+            results_with_checks.append(
+                (DATA_CHECKS_BY_NAME[result["check"]], result["count"])
+            )
+
+        send_templated_mail(
+            template_name="data_checks",
+            from_email=get_site_preferences()["mail__address"],
+            recipient_list=[
+                p.email
+                for p in get_site_preferences()["alsijil__data_checks_recipients"]
+            ],
+            context={"results": results_with_checks},
+        )
+
+        results.update(sent=True)
diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py
index b584083b4b0842610f4503a59cd15d72cac531ea..8f8b6fee054d8fdf136e51a61260bb9725421ec3 100644
--- a/aleksis/apps/alsijil/models.py
+++ b/aleksis/apps/alsijil/models.py
@@ -239,6 +239,7 @@ class DataCheckResult(ExtensibleModel):
     related_object = GenericForeignKey("content_type", "object_id")
 
     solved = models.BooleanField(default=False, verbose_name=_("Issue solved"))
+    sent = models.BooleanField(default=False, verbose_name=_("Notification sent"))
 
     @property
     def related_check(self) -> DataCheck:
diff --git a/aleksis/apps/alsijil/preferences.py b/aleksis/apps/alsijil/preferences.py
index bcefc075e2ac5025ebaf2b361abe3f2325b16563..01dedd9bbe6955226baf3c434f68da557b8557ee 100644
--- a/aleksis/apps/alsijil/preferences.py
+++ b/aleksis/apps/alsijil/preferences.py
@@ -1,8 +1,9 @@
 from django.utils.translation import gettext as _
 
 from dynamic_preferences.preferences import Section
-from dynamic_preferences.types import BooleanPreference
+from dynamic_preferences.types import BooleanPreference, ModelMultipleChoicePreference
 
+from aleksis.core.models import Person
 from aleksis.core.registries import site_preferences_registry
 
 alsijil = Section("alsijil", verbose_name=_("Class register"))
@@ -40,3 +41,24 @@ class AllowOpenPeriodsOnSameDay(BooleanPreference):
     help_text = _(
         "Lessons in the past are not affected by this setting, you can open them whenever you want."
     )
+
+
+@site_preferences_registry.register
+class DataChecksSendEmails(BooleanPreference):
+    """Enable email sending if data checks detect problems."""
+
+    section = alsijil
+    name = "data_checks_send_emails"
+    default = False
+    verbose_name = _("Send emails if data checks detect problems")
+
+
+@site_preferences_registry.register
+class DataChecksEmailsRecipients(ModelMultipleChoicePreference):
+    """Email recipients for data check problem emails."""
+
+    section = alsijil
+    name = "data_checks_recipients"
+    default = []
+    model = Person
+    verbose_name = _("Email recipients for data checks problem emails")
diff --git a/aleksis/apps/alsijil/templates/templated_email/data_checks.css b/aleksis/apps/alsijil/templates/templated_email/data_checks.css
new file mode 100644
index 0000000000000000000000000000000000000000..b385b185ecfe66dcca070e8eb024bbb091917f04
--- /dev/null
+++ b/aleksis/apps/alsijil/templates/templated_email/data_checks.css
@@ -0,0 +1,16 @@
+body {
+    line-height: 1.5;
+    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
+    font-weight: normal;
+    color: rgba(0, 0, 0, 0.87);
+}
+
+.count {
+    text-align: right;
+    font-family: monospace;
+    font-size: 14pt;
+}
+
+td, th {
+    padding: 10px;
+}
diff --git a/aleksis/apps/alsijil/templates/templated_email/data_checks.email b/aleksis/apps/alsijil/templates/templated_email/data_checks.email
new file mode 100644
index 0000000000000000000000000000000000000000..636dc27d36a37c650fc1a7cc7b8364653b00ce91
--- /dev/null
+++ b/aleksis/apps/alsijil/templates/templated_email/data_checks.email
@@ -0,0 +1,44 @@
+{% load i18n %}
+
+{% block subject %}
+ {% trans "The system detected some new problems with your data." %}
+{% endblock %}
+
+{% block plain %}
+ {% trans "Hello," %}
+
+ {% blocktrans %}
+  the system detected some new problems with your data in the digital class register.
+  Please take some time to inspect them and solve the issues or mark them as ignored.
+ {% endblocktrans %}
+
+ {% for result in results %}
+  {{ result.0.problem_name }}: {{ result.1 }}
+ {% endfor %}
+{% endblock %}
+
+{% block html %}
+ <style>
+  {% include "templated_email/data_checks.css" %}
+ </style>
+ <p>{% trans "Hello," %}</p>
+ <p>
+  {% blocktrans %}
+   the system detected some new problems with your data in the digital class register.
+   Please take some time to inspect them and solve the issues or mark them as ignored.
+  {% endblocktrans %}
+ </p>
+
+ <table>
+  <tr>
+   <th>{% trans "Problem description" %}</th>
+   <th>{% trans "Count of objects with new problems" %}</th>
+  </tr>
+  {% for result in results %}
+   <tr>
+    <td>{{ result.0.problem_name }}</td>
+    <td class="count">{{ result.1 }}</td>
+   </tr>
+  {% endfor %}
+ </table>
+{% endblock %}