fix(reports): stamp email subject date at send time, not import time (#40693)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Evan Rusackas
2026-06-04 12:03:28 -07:00
committed by GitHub
parent cd5bdf11ac
commit 9a31362fa5
2 changed files with 28 additions and 9 deletions

View File

@@ -28,8 +28,8 @@ from pytz import timezone
from superset import is_feature_enabled
from superset.exceptions import SupersetErrorsException
from superset.reports.models import ReportRecipientType
from superset.reports.notifications.base import BaseNotification
from superset.reports.models import ReportRecipients, ReportRecipientType
from superset.reports.notifications.base import BaseNotification, NotificationContent
from superset.reports.notifications.exceptions import NotificationError
from superset.utils import json
from superset.utils.core import HeaderDataType, send_email_smtp
@@ -83,7 +83,17 @@ class EmailNotification(BaseNotification): # pylint: disable=too-few-public-met
"""
type = ReportRecipientType.EMAIL
now = datetime.now(timezone("UTC"))
def __init__(
self, recipient: ReportRecipients, content: NotificationContent
) -> None:
super().__init__(recipient, content)
# Stamp each notification with its own timestamp at construction, which
# happens per recipient immediately before the email is dispatched. The
# date rendered into the subject (when DATE_FORMAT_IN_EMAIL_SUBJECT is
# enabled) therefore tracks the dispatch time. A module- or class-level
# value would instead freeze on the first import in a long-running worker.
self.now = datetime.now(timezone("UTC"))
@property
def _name(self) -> str:

View File

@@ -17,6 +17,7 @@
from datetime import datetime
import pandas as pd
from freezegun import freeze_time
from pytz import timezone
from tests.unit_tests.conftest import with_feature_flags
@@ -107,8 +108,6 @@ def test_email_subject_with_datetime() -> None:
from superset.reports.notifications.base import NotificationContent
from superset.reports.notifications.email import EmailNotification
now = datetime.now(timezone("UTC"))
datetime_pattern = "%Y-%m-%d"
content = NotificationContent(
@@ -130,8 +129,18 @@ def test_email_subject_with_datetime() -> None:
"execution_id": "test-execution-id",
},
)
subject = EmailNotification(
recipient=ReportRecipients(type=ReportRecipientType.EMAIL), content=content
)._get_subject()
# Freeze the clock to a fixed, distinctive instant and construct the
# notification *under* the freeze. The subject date must reflect this
# frozen moment, which is only possible if the timestamp is stamped per
# instance at construction/send time. If the timestamp were a class
# attribute evaluated at import time (the regression this fixes), it would
# carry the real import-time date instead and this assertion would fail.
frozen_now = datetime(2021, 4, 22, 12, 0, 0, tzinfo=timezone("UTC"))
with freeze_time(frozen_now):
notification = EmailNotification(
recipient=ReportRecipients(type=ReportRecipientType.EMAIL),
content=content,
)
subject = notification._get_subject()
assert datetime_pattern not in subject
assert now.strftime(datetime_pattern) in subject
assert frozen_now.strftime(datetime_pattern) in subject