Skip to content

Commit

Permalink
Merge pull request #4093 from open-formulieren/feature/3725-add-probl…
Browse files Browse the repository at this point in the history
…ems-to-email-digest

[#3725] Add problems to the email digest
  • Loading branch information
sergei-maertens authored Apr 10, 2024
2 parents f77c242 + 0eee5b5 commit 2ee5b30
Show file tree
Hide file tree
Showing 9 changed files with 365 additions and 133 deletions.
60 changes: 34 additions & 26 deletions src/openforms/emails/tasks.py
Original file line number Diff line number Diff line change
@@ -1,51 +1,59 @@
from datetime import timedelta
from datetime import datetime, timedelta
from typing import Any

from django.conf import settings
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from django_yubin.models import Message

from openforms.celery import app
from openforms.config.models import GlobalConfiguration
from openforms.logging.models import TimelineLogProxy
from openforms.logging.service import (
collect_failed_emails,
collect_failed_registrations,
)

from .utils import send_mail_html


class Digest:
def __init__(self, since: datetime) -> None:
self.since = since

def get_context_data(self) -> dict[str, Any]:
failed_emails = collect_failed_emails(self.since)
failed_registrations = collect_failed_registrations(self.since)

if not (failed_emails or failed_registrations):
return {}

return {
"failed_emails": failed_emails,
"failed_registrations": failed_registrations,
}

def render(self) -> str:
if not (context := self.get_context_data()):
return ""

return render_to_string("emails/admin_digest.html", context)


@app.task
def send_email_digest() -> None:
config = GlobalConfiguration.get_solo()
if not (recipients := config.recipients_email_digest):
return

period_start = timezone.now() - timedelta(days=1)

logs = TimelineLogProxy.objects.filter(
timestamp__gt=period_start,
extra_data__status=Message.STATUS_FAILED,
extra_data__include_in_daily_digest=True,
).distinct("content_type", "extra_data__status", "extra_data__event")
yesterday = timezone.now() - timedelta(days=1)
digest = Digest(since=yesterday)
content = digest.render()

if not logs:
if not content:
return

content = render_to_string(
"emails/admin_digest.html",
{
"logs": [
{
"submission_uuid": log.content_object.uuid,
"event": log.extra_data["event"],
}
for log in logs
],
},
)

send_mail_html(
_("[Open Forms] Daily summary of failed emails"),
_("[Open Forms] Daily summary of detected problems"),
content,
settings.DEFAULT_FROM_EMAIL,
recipients,
Expand Down
41 changes: 34 additions & 7 deletions src/openforms/emails/templates/emails/admin_digest.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
{% load static i18n %}

<p>
{% blocktranslate %}Here is a summary of the emails that failed to send yesterday:{% endblocktranslate %}
</p>
<ul>
{% for log in logs %}<li>- Email for the event "{{ log.event }}" for submission {{ log.submission_uuid }}.</li>
{% endfor %}
</ul>
<h3>
{% blocktranslate %}Here is a summary of the problems detected in the past 24 hours:{% endblocktranslate %}
</h3>

{% if failed_emails %}
<h5>{% trans "Emails that failed to send" %}</h5>
<ul>
{% for email in failed_emails %}
<li>
{% blocktranslate with event=email.event submission_uuid=email.submission_uuid trimmed %}
Email for the event "{{ event }}" for submission {{ submission_uuid }}.
{% endblocktranslate %}
</li>
{% endfor %}
</ul>
{% endif %}

{% if failed_registrations %}
<h5>{% trans "Registrations" %}</h5>
<ul>
{% for registration in failed_registrations %}
<li>
{% blocktranslate with form_name=registration.form_name counter=registration.failed_submissions_counter first_failure_at=registration.initial_failure_at|time:"H:i" last_failure_at=registration.last_failure_at|time:"H:i" trimmed %}
Form '{{ form_name }}' failed {{ counter }} times between {{ first_failure_at }} and {{ last_failure_at }}.</br>
{% endblocktranslate %}

<a href="{{ registration.admin_link }}">
{% blocktranslate with form_name=registration.form_name %}
View failed '{{ form_name }}' submissions
{% endblocktranslate %}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
Loading

0 comments on commit 2ee5b30

Please sign in to comment.