From 13eaf44357cb01415735ad90ceb8baf765babbe6 Mon Sep 17 00:00:00 2001
From: kyokukou
Date: Thu, 28 May 2026 14:03:07 -0700
Subject: [PATCH 1/6] add submit time and email system warning
---
app/email_content.py | 5 +++-
app/schema.py | 5 ++--
app/templates/email_body.py | 8 ++++++
app/templates/submission.py | 22 ++++++++++++----
tests/test_email_content.py | 51 +++++++++++++++++++++++++++++--------
5 files changed, 73 insertions(+), 18 deletions(-)
diff --git a/app/email_content.py b/app/email_content.py
index cfa4f96..7c6a794 100644
--- a/app/email_content.py
+++ b/app/email_content.py
@@ -3,13 +3,14 @@
from zoneinfo import ZoneInfo
from sqlalchemy import select
+from arxiv.config import settings as arxiv_settings
from arxiv.db import Session
from arxiv.db.models import Submission, SubmissionCategory
from arxiv.taxonomy.definitions import CATEGORY_ALIASES
from app.schema import SubEmailData, SimplifiedNotification, CommentData, PromoteData, NewPropData, PropRespData, EmailTask, UserContact
-_ET = ZoneInfo("America/New_York")
+_ET = ZoneInfo(arxiv_settings.ARXIV_BUSINESS_TZ)
def _fmt_time(dt: datetime) -> str:
et = dt.astimezone(_ET)
return et.strftime("%m-%d %H:%M ET")
@@ -55,6 +56,7 @@ def get_submission_info(submission_ids: set[int]) -> dict[int, SubEmailData]:
Submission.status,
Submission.submitter_name,
Submission.submitter_id,
+ Submission.submit_time,
).where(Submission.submission_id.in_(submission_ids))
).all()
@@ -77,6 +79,7 @@ def get_submission_info(submission_ids: set[int]) -> dict[int, SubEmailData]:
submitter_name=row.submitter_name or "",
submitter_id=row.submitter_id or 0,
submission_categories=_build_category_string(cats_by_sub.get(row.submission_id, [])),
+ submit_time=row.submit_time,
)
for row in rows
}
diff --git a/app/schema.py b/app/schema.py
index e8832a7..c082708 100644
--- a/app/schema.py
+++ b/app/schema.py
@@ -1,5 +1,5 @@
from datetime import datetime
-from typing import Literal, Union
+from typing import Literal, Union, Optional
from enum import Enum
from pydantic import BaseModel
from dataclasses import dataclass, field
@@ -77,4 +77,5 @@ class SubEmailData:
status: int
submitter_name: str
submitter_id: int
- submission_categories: str = ""
\ No newline at end of file
+ submission_categories: str = ""
+ submit_time: Optional[datetime] = None
\ No newline at end of file
diff --git a/app/templates/email_body.py b/app/templates/email_body.py
index b5b1573..44a548d 100644
--- a/app/templates/email_body.py
+++ b/app/templates/email_body.py
@@ -5,6 +5,9 @@
MOD_HUB_URL = "https://arxiv-org.atlassian.net/wiki/spaces/ModRes/pages/812580865/Moderator+Hub"
MOD_HUB_TITLE = "Moderator Hub"
+_FOOTER_LINE1 = "This email was generated by the moderator email system version 2.0"
+_FOOTER_LINE2 = "Some of your arXiv moderation emails may look different. We are in the process of transitioning email systems."
+
def render_body(
sub_text: str,
@@ -21,6 +24,9 @@ def render_body(
f"{CHECK_GUIDE_TITLE}: {CHECK_GUIDE_URL} \n"
f"{HOW_TO_MOD_TITLE}: {HOW_TO_MOD_URL} \n"
f"{MOD_HUB_TITLE}: {MOD_HUB_URL} \n"
+ f"\n"
+ f"{_FOOTER_LINE1}\n"
+ f"{_FOOTER_LINE2}\n"
)
body_html = (
f"{sub_html}\n"
@@ -32,5 +38,7 @@ def render_body(
f"{HOW_TO_MOD_TITLE} | "
f"{MOD_HUB_TITLE}"
f"
\n"
+ f"{_FOOTER_LINE1}
\n"
+ f"{_FOOTER_LINE2}
\n"
)
return body_text, body_html
diff --git a/app/templates/submission.py b/app/templates/submission.py
index 91c03cd..a74c476 100644
--- a/app/templates/submission.py
+++ b/app/templates/submission.py
@@ -1,10 +1,13 @@
import html
+from zoneinfo import ZoneInfo
+from arxiv.config import settings as arxiv_settings
from arxiv.submission.statuses import STATUS_NAMES
from app.schema import SubEmailData
CHECK_SUBMISSION_URL = "https://check.arxiv.org/submit/{submission_id}"
+_ET = ZoneInfo(arxiv_settings.ARXIV_BUSINESS_TZ)
def render_submission_block(sub: SubEmailData) -> tuple[str, str]:
@@ -14,20 +17,29 @@ def render_submission_block(sub: SubEmailData) -> tuple[str, str]:
title = sub.title or "(no title)"
authors = sub.authors or "(no authors)"
+ submit_time_str = (
+ sub.submit_time.astimezone(_ET).strftime("%Y-%m-%d %H:%M EST")
+ if sub.submit_time else None
+ )
+
text = (
- f"Submission: submit/{sub.submission_id}\n"
+ f"Submission: submit/{sub.submission_id} | {check_url}\n"
f"Title: {title}\n"
f"Authors: {authors}\n"
f"Status: {status_label}\n"
f"Current Categories: {cat_list}\n"
- f"View in Check: {check_url}\n"
)
+ if submit_time_str:
+ text += f"Submitted: {submit_time_str}\n"
+
html_out = (
- f"Submission: submit/{sub.submission_id}
\n"
+ f"
Submission: submit/{sub.submission_id} | {check_url}
\n"
f"Title: {html.escape(title)}
\n"
f"Authors: {html.escape(authors)}
\n"
f"Status: {status_label}
\n"
- f"Current Categories: {cat_list}
\n"
- f"View in Check: {check_url}
\n"
+ f"Current Categories: {cat_list}"
)
+ if submit_time_str:
+ html_out += f"
\nSubmitted: {submit_time_str}"
+ html_out += "\n"
return text, html_out
diff --git a/tests/test_email_content.py b/tests/test_email_content.py
index fc5412a..a36c02a 100644
--- a/tests/test_email_content.py
+++ b/tests/test_email_content.py
@@ -98,7 +98,7 @@ def test_render_change_block_dispatches():
# ── submission block ──────────────────────────────────────────────────────────
def _mock_submission(submission_id=123, title="ML Paper", authors="Alice, Bob", status=1,
- submission_categories="cs.LG cs.AI"):
+ submission_categories="cs.LG cs.AI", submit_time=_TIME):
return SubEmailData(
submission_id=submission_id,
title=title,
@@ -107,6 +107,7 @@ def _mock_submission(submission_id=123, title="ML Paper", authors="Alice, Bob",
submitter_name="",
submitter_id=0,
submission_categories=submission_categories,
+ submit_time=submit_time,
)
def test_render_submission_block():
@@ -164,6 +165,7 @@ def test_render_email_contains_all_sections_and_footer():
#will need to be updated whenever format changes
#feel free to delete if too annoying, but its kind of nice to see the whole output
_WHEN = "06-15 10:30 ET" # _TIME (2024-06-15 14:30 UTC) converted to EDT
+_SUBMIT_TIME_STR = "2024-06-15 10:30 EST" # _TIME converted to ET
_CHECK_URL_123 = "https://check.arxiv.org/submit/123"
@@ -239,12 +241,24 @@ def test_submission_exact_text():
sub = _mock_submission()
text, _ = render_submission_block(sub)
assert text == (
- "Submission: submit/123\n"
+ f"Submission: submit/123 | {_CHECK_URL_123}\n"
+ "Title: ML Paper\n"
+ "Authors: Alice, Bob\n"
+ "Status: submitted\n"
+ "Current Categories: cs.LG cs.AI\n"
+ f"Submitted: {_SUBMIT_TIME_STR}\n"
+ )
+
+
+def test_submission_exact_text_no_submit_time():
+ sub = _mock_submission(submit_time=None)
+ text, _ = render_submission_block(sub)
+ assert text == (
+ f"Submission: submit/123 | {_CHECK_URL_123}\n"
"Title: ML Paper\n"
"Authors: Alice, Bob\n"
"Status: submitted\n"
"Current Categories: cs.LG cs.AI\n"
- f"View in Check: {_CHECK_URL_123}\n"
)
@@ -252,12 +266,24 @@ def test_submission_exact_html():
sub = _mock_submission()
_, html_out = render_submission_block(sub)
assert html_out == (
- "Submission: submit/123
\n"
+ f"
Submission: submit/123 | {_CHECK_URL_123}
\n"
"Title: ML Paper
\n"
"Authors: Alice, Bob
\n"
"Status: submitted
\n"
- "Current Categories: cs.LG cs.AI
\n"
- f"View in Check: {_CHECK_URL_123}
\n"
+ f"Current Categories: cs.LG cs.AI
\n"
+ f"Submitted: {_SUBMIT_TIME_STR}\n"
+ )
+
+
+def test_submission_exact_html_no_submit_time():
+ sub = _mock_submission(submit_time=None)
+ _, html_out = render_submission_block(sub)
+ assert html_out == (
+ f"Submission: submit/123 | {_CHECK_URL_123}
\n"
+ "Title: ML Paper
\n"
+ "Authors: Alice, Bob
\n"
+ "Status: submitted
\n"
+ "Current Categories: cs.LG cs.AI
\n"
)
@@ -275,12 +301,12 @@ def test_full_email_exact_text():
promote_text, promote_html = render_change_block(promote, _USER)
body_text, _ = render_body(sub_text, sub_html, [comment_text, promote_text], [comment_html, promote_html])
assert body_text == (
- "Submission: submit/123\n"
+ f"Submission: submit/123 | {_CHECK_URL}\n"
"Title: ML Paper\n"
"Authors: Alice, Bob\n"
"Status: submitted\n"
"Current Categories: cs.LG cs.AI\n"
- f"View in Check: {_CHECK_URL}\n"
+ f"Submitted: {_SUBMIT_TIME_STR}\n"
"\n"
"----------------------------------------\n"
f"[{_WHEN}] {_USER} added a comment:\n"
@@ -293,6 +319,9 @@ def test_full_email_exact_text():
f"How to use Check: {_GUIDE_URL} \n"
f"How to moderate: {_MOD_URL} \n"
f"Moderator Hub: {_HUB_URL} \n"
+ "\n"
+ "This email was generated by the moderator email system version 2.0\n"
+ "Some of your arXiv moderation emails may look different. We are in the process of transitioning email systems.\n"
)
@@ -305,12 +334,12 @@ def test_full_email_exact_html():
promote_text, promote_html = render_change_block(promote, _USER)
_, body_html = render_body(sub_text, sub_html, [comment_text, promote_text], [comment_html, promote_html])
assert body_html == (
- "Submission: submit/123
\n"
+ f"
Submission: submit/123 | {_CHECK_URL}
\n"
"Title: ML Paper
\n"
"Authors: Alice, Bob
\n"
"Status: submitted
\n"
"Current Categories: cs.LG cs.AI
\n"
- f"View in Check: {_CHECK_URL}
\n"
+ f"Submitted: {_SUBMIT_TIME_STR}\n"
"\n"
"
\n"
f"[{_WHEN}] {_USER} added a comment:
\n"
@@ -322,6 +351,8 @@ def test_full_email_exact_html():
f"
How to use Check | "
f"How to moderate | "
f"Moderator Hub
\n"
+ "This email was generated by the moderator email system version 2.0
\n"
+ "Some of your arXiv moderation emails may look different. We are in the process of transitioning email systems.
\n"
)
From f21af287f3d0b3bf83186a5725883b9ec66c6438 Mon Sep 17 00:00:00 2001
From: kyokukou
Date: Fri, 29 May 2026 09:14:24 -0700
Subject: [PATCH 2/6] use correct category set for subject
---
app/process.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/app/process.py b/app/process.py
index abdca9b..745c836 100644
--- a/app/process.py
+++ b/app/process.py
@@ -148,9 +148,8 @@ def _send_email_tasks(
#send email — failure skips ack (will redeliver)
try:
- cat_str = " ".join(sorted(c.id for c in task.notifications.categories))
submitter = sub.submitter_name or f"user {sub.submitter_id}"
- subject = f"Action Required: arXiv submission submit/{task.submission_id} to {cat_str} by {submitter}"
+ subject = f"Action Required: arXiv submission submit/{task.submission_id} to {sub.submission_categories} by {submitter}"
send_email(
to_emails=task.to_emails,
subject=subject,
From 593660e2c9b96ac81eacd27f4e4af11e3b17bd0c Mon Sep 17 00:00:00 2001
From: kyokukou
Date: Fri, 29 May 2026 11:02:13 -0700
Subject: [PATCH 3/6] include special arxiv emails in to and reply to
---
README.md | 17 +++++++++++++++++
app/config.py | 4 ++++
app/email.py | 16 +++++++++++-----
3 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index fe3fc4f..fbf04d2 100644
--- a/README.md
+++ b/README.md
@@ -11,3 +11,20 @@ tests are set up to run on most individual functions and use test data in data.s
poetry install
poetry run coverage run -m pytest
```
+
+deploying:
+happens automatically on merge to major branches through GCP build triggers to a cloud run job
+
+additonal environment variables needed:
+CLASSIC_DB_URI
+HALON_CREDS
+SEND_EMAILS
+ARCHIVAL_EMAIL
+MOD_REPLY_TO
+
+optional:
+MAIL_FROM
+ENV
+LOG_LEVEL
+REDIRECT_RECIPIENT
+
diff --git a/app/config.py b/app/config.py
index 91aae03..d9d5101 100644
--- a/app/config.py
+++ b/app/config.py
@@ -1,3 +1,4 @@
+from typing import Optional
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
@@ -12,6 +13,9 @@ class Settings(BaseSettings):
SMTP_HOST: str = "mailh.arxiv.org"
SMTP_USER: str = "arxiv"
MAIL_FROM: str = "e-prints@arxiv.org"
+ REDIRECT_RECIPIENT: str = "test-colab-group@arxiv.org"
+ ARCHIVAL_EMAIL: Optional[str] = None
+ MOD_REPLY_TO: Optional[str] = None
model_config = SettingsConfigDict(
env_file=".env",
diff --git a/app/email.py b/app/email.py
index c10ebb7..08d6d94 100644
--- a/app/email.py
+++ b/app/email.py
@@ -9,8 +9,6 @@
logger = logging.getLogger(__name__)
-_OVERRIDE_RECIPIENT = "test-colab-group@arxiv.org"
-
def send_email(
to_emails: list[str],
@@ -21,18 +19,26 @@ def send_email(
) -> None:
"""Send a plain-text and HTML email via the Halon SMTP relay."""
+ reply_to_emails = (reply_to_emails or []) + ([settings.MOD_REPLY_TO] if settings.MOD_REPLY_TO else [])
+ bcc_emails: list[str] = [settings.ARCHIVAL_EMAIL] if settings.ARCHIVAL_EMAIL else []
+
if not settings.SEND_EMAILS:
logger.info(f"Email sending disabled. Would send to {to_emails}: {subject}")
return
+ # redirect emails while under development
redirect_header = f"[TEST REDIRECT]\nOriginal To: {', '.join(to_emails)}"
if reply_to_emails:
redirect_header += f"\nOriginal Reply-To: {', '.join(reply_to_emails)}"
+ if bcc_emails:
+ redirect_header += f"\nOriginal Bcc: {', '.join(bcc_emails)}"
body = redirect_header + "\n\n" + body
html_body = redirect_header.replace("\n", "
\n") + "
\n" + html_body
- to_emails = [_OVERRIDE_RECIPIENT]
+ to_emails = [settings.REDIRECT_RECIPIENT]
reply_to_emails = []
+ bcc_emails = []
+ #build email
msg = email.message.EmailMessage()
msg["Date"] = format_datetime(localtime())
msg["Message-ID"] = make_msgid()
@@ -49,7 +55,7 @@ def send_email(
sess.send_message(
msg,
from_addr=settings.MAIL_FROM,
- to_addrs=to_emails,
+ to_addrs=to_emails + bcc_emails,
mail_options=("8bitmime",),
)
- logger.info(f"Email sent to {to_emails}: {subject}")
+ logger.debug(f"Email sent to {to_emails + bcc_emails}: {subject}")
From c874af8d411f01e004dea7079b81e1c396e2fa92 Mon Sep 17 00:00:00 2001
From: kyokukou
Date: Fri, 29 May 2026 11:23:47 -0700
Subject: [PATCH 4/6] redirect email through env
---
app/config.py | 2 +-
app/email.py | 4 ++++
tests/data.sql | 3 +++
tests/test_process_message.py | 38 +++++++++++++++++++++++++++++++++++
4 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/app/config.py b/app/config.py
index d9d5101..4e1f4c6 100644
--- a/app/config.py
+++ b/app/config.py
@@ -13,7 +13,7 @@ class Settings(BaseSettings):
SMTP_HOST: str = "mailh.arxiv.org"
SMTP_USER: str = "arxiv"
MAIL_FROM: str = "e-prints@arxiv.org"
- REDIRECT_RECIPIENT: str = "test-colab-group@arxiv.org"
+ REDIRECT_RECIPIENT: Optional[str] = None
ARCHIVAL_EMAIL: Optional[str] = None
MOD_REPLY_TO: Optional[str] = None
diff --git a/app/email.py b/app/email.py
index 08d6d94..3b73455 100644
--- a/app/email.py
+++ b/app/email.py
@@ -27,6 +27,10 @@ def send_email(
return
# redirect emails while under development
+ if not settings.REDIRECT_RECIPIENT:
+ logger.error("REDIRECT_RECIPIENT not set — refusing to send to avoid misdirected email")
+ return
+
redirect_header = f"[TEST REDIRECT]\nOriginal To: {', '.join(to_emails)}"
if reply_to_emails:
redirect_header += f"\nOriginal Reply-To: {', '.join(reply_to_emails)}"
diff --git a/tests/data.sql b/tests/data.sql
index b523a74..b268701 100644
--- a/tests/data.sql
+++ b/tests/data.sql
@@ -59,6 +59,7 @@ INSERT INTO `tapir_nicknames` VALUES (10005,'jsmith',2,1,1,0,0,1);
INSERT INTO `arXiv_submissions` (submission_id, title, authors, status, remote_addr, remote_host, package) VALUES (123, 'A Test Paper on Machine Learning', 'Author One, Author Two', 1, '127.0.0.1', 'localhost', '');
INSERT INTO `arXiv_submissions` (submission_id, title, authors, status, remote_addr, remote_host, package) VALUES (124, 'Another Test Paper on Category Promotion', 'Author Three', 1, '127.0.0.1', 'localhost', '');
INSERT INTO `arXiv_submissions` (submission_id, title, authors, status, remote_addr, remote_host, package) VALUES (125, 'Paper With No Categories', 'Some Author', 1, '127.0.0.1', 'localhost', '');
+INSERT INTO `arXiv_submissions` (submission_id, title, authors, status, remote_addr, remote_host, package) VALUES (126, 'A Math-Physics Paper', 'Author Math', 1, '127.0.0.1', 'localhost', '');
-- submission categories for get_submission_info tests
-- 123: cs.LG primary + cs.AI cross-list
@@ -68,3 +69,5 @@ INSERT INTO `arXiv_submission_category` VALUES (123, 'cs.AI', 0, NULL);
INSERT INTO `arXiv_submission_category` VALUES (124, 'cs.AI', 0, NULL);
INSERT INTO `arXiv_submission_category` VALUES (124, 'cs.LG', 0, NULL);
-- 125: no categories
+-- 126: math-ph primary (math.MP alias should also appear)
+INSERT INTO `arXiv_submission_category` VALUES (126, 'math-ph', 1, NULL);
diff --git a/tests/test_process_message.py b/tests/test_process_message.py
index d4c9f98..59ff7f9 100644
--- a/tests/test_process_message.py
+++ b/tests/test_process_message.py
@@ -375,3 +375,41 @@ def test_changes_ordered_newest_first():
assert mock_send.call_count == 2
body = mock_send.call_args.kwargs["body"]
assert body.index("01-02 05:00 ET") < body.index("01-01 05:00 ET")
+
+@pytest.mark.usefixtures("db_session")
+def test_subject_uses_paper_categories():
+ # submission 123: cs.LG (primary) + cs.AI (cross), no submitter name in DB
+ msg = _make_pubsub_message("ack-1", GOOD_COMMENT)
+
+ mock_send = Mock()
+ with patch("app.process.send_email", mock_send):
+ process_messages([msg], ack_fn=Mock())
+
+ assert mock_send.call_args.kwargs["subject"] == \
+ "Action Required: arXiv submission submit/123 to cs.LG cs.AI by user 0"
+
+@pytest.mark.usefixtures("db_session")
+def test_subject_no_primary_category():
+ # submission 124: cs.AI + cs.LG both cross-list, no primary
+ note = {**GOOD_COMMENT, "submission_id": 124}
+ msg = _make_pubsub_message("ack-1", note)
+
+ mock_send = Mock()
+ with patch("app.process.send_email", mock_send):
+ process_messages([msg], ack_fn=Mock())
+
+ assert mock_send.call_args.kwargs["subject"] == \
+ "Action Required: arXiv submission submit/124 to no primary cs.AI cs.LG by user 0"
+
+@pytest.mark.usefixtures("db_session")
+def test_subject_alias_category_expands():
+ # submission 126: math-ph (primary); math.MP alias should also appear
+ note = {**GOOD_COMMENT, "submission_id": 126}
+ msg = _make_pubsub_message("ack-1", note)
+
+ mock_send = Mock()
+ with patch("app.process.send_email", mock_send):
+ process_messages([msg], ack_fn=Mock())
+
+ assert mock_send.call_args.kwargs["subject"] == \
+ "Action Required: arXiv submission submit/126 to math-ph math.MP by user 0"
From 82e10c6f1229f252454649aeedff11f377ef9564 Mon Sep 17 00:00:00 2001
From: kyokukou
Date: Tue, 2 Jun 2026 09:05:31 -0700
Subject: [PATCH 5/6] generic east coast time zone
---
app/templates/submission.py | 2 +-
tests/test_email_content.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/templates/submission.py b/app/templates/submission.py
index a74c476..36f835a 100644
--- a/app/templates/submission.py
+++ b/app/templates/submission.py
@@ -18,7 +18,7 @@ def render_submission_block(sub: SubEmailData) -> tuple[str, str]:
authors = sub.authors or "(no authors)"
submit_time_str = (
- sub.submit_time.astimezone(_ET).strftime("%Y-%m-%d %H:%M EST")
+ sub.submit_time.astimezone(_ET).strftime("%Y-%m-%d %H:%M ET")
if sub.submit_time else None
)
diff --git a/tests/test_email_content.py b/tests/test_email_content.py
index a36c02a..b7dec38 100644
--- a/tests/test_email_content.py
+++ b/tests/test_email_content.py
@@ -164,8 +164,8 @@ def test_render_email_contains_all_sections_and_footer():
# ── exact output tests ────────────────────────────────────────────────────────
#will need to be updated whenever format changes
#feel free to delete if too annoying, but its kind of nice to see the whole output
-_WHEN = "06-15 10:30 ET" # _TIME (2024-06-15 14:30 UTC) converted to EDT
-_SUBMIT_TIME_STR = "2024-06-15 10:30 EST" # _TIME converted to ET
+_WHEN = "06-15 10:30 ET" # _TIME (2024-06-15 14:30 UTC) converted to ET
+_SUBMIT_TIME_STR = "2024-06-15 10:30 ET" # _TIME converted to ET
_CHECK_URL_123 = "https://check.arxiv.org/submit/123"
From 04eba88be228cc3cc28f6814d832acecf9bc271e Mon Sep 17 00:00:00 2001
From: kyokukou
Date: Tue, 2 Jun 2026 09:35:02 -0700
Subject: [PATCH 6/6] time zone lables changes with DST
---
app/email_content.py | 2 +-
app/templates/submission.py | 2 +-
tests/test_email_content.py | 6 +++---
tests/test_process_message.py | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/app/email_content.py b/app/email_content.py
index 7c6a794..d018eef 100644
--- a/app/email_content.py
+++ b/app/email_content.py
@@ -13,7 +13,7 @@
_ET = ZoneInfo(arxiv_settings.ARXIV_BUSINESS_TZ)
def _fmt_time(dt: datetime) -> str:
et = dt.astimezone(_ET)
- return et.strftime("%m-%d %H:%M ET")
+ return et.strftime("%m-%d %H:%M %Z")
from app.templates.comment import render_comment_block
from app.templates.promote import render_promote_block
diff --git a/app/templates/submission.py b/app/templates/submission.py
index 36f835a..12b5a85 100644
--- a/app/templates/submission.py
+++ b/app/templates/submission.py
@@ -18,7 +18,7 @@ def render_submission_block(sub: SubEmailData) -> tuple[str, str]:
authors = sub.authors or "(no authors)"
submit_time_str = (
- sub.submit_time.astimezone(_ET).strftime("%Y-%m-%d %H:%M ET")
+ sub.submit_time.astimezone(_ET).strftime("%Y-%m-%d %H:%M %Z")
if sub.submit_time else None
)
diff --git a/tests/test_email_content.py b/tests/test_email_content.py
index b7dec38..893cd61 100644
--- a/tests/test_email_content.py
+++ b/tests/test_email_content.py
@@ -28,7 +28,7 @@ def test_render_comment_block():
text, html_out = render_comment_block(note, _USER)
assert "looks good to me" in text and "looks good to me" in html_out
assert _USER in text and _USER in html_out
- assert "ET" in text
+ assert "EDT" in text
def test_render_comment_escapes_html():
note = _note(CommentData(comment=" & done"))
@@ -164,8 +164,8 @@ def test_render_email_contains_all_sections_and_footer():
# ── exact output tests ────────────────────────────────────────────────────────
#will need to be updated whenever format changes
#feel free to delete if too annoying, but its kind of nice to see the whole output
-_WHEN = "06-15 10:30 ET" # _TIME (2024-06-15 14:30 UTC) converted to ET
-_SUBMIT_TIME_STR = "2024-06-15 10:30 ET" # _TIME converted to ET
+_WHEN = "06-15 10:30 EDT" # _TIME (2024-06-15 14:30 UTC)
+_SUBMIT_TIME_STR = "2024-06-15 10:30 EDT"
_CHECK_URL_123 = "https://check.arxiv.org/submit/123"
diff --git a/tests/test_process_message.py b/tests/test_process_message.py
index 59ff7f9..3b3bf02 100644
--- a/tests/test_process_message.py
+++ b/tests/test_process_message.py
@@ -367,14 +367,14 @@ def test_changes_ordered_newest_first():
assert mock_send.call_count == 1
body = mock_send.call_args.kwargs["body"]
- assert body.index("01-02 05:00 ET") < body.index("01-01 05:00 ET")
+ assert body.index("01-02 05:00 EST") < body.index("01-01 05:00 EST")
with patch("app.process.send_email", mock_send):
process_messages([msg2, msg1], ack_fn=Mock())
assert mock_send.call_count == 2
body = mock_send.call_args.kwargs["body"]
- assert body.index("01-02 05:00 ET") < body.index("01-01 05:00 ET")
+ assert body.index("01-02 05:00 EST") < body.index("01-01 05:00 EST")
@pytest.mark.usefixtures("db_session")
def test_subject_uses_paper_categories():