Adding missing Date header to outbound emails

NousResearch/hermes-agent · cluster 15160

Data as of

Nothing open on GitHub. Fix merged in #16568. Check it covers your case.

The short answer

0open issues
0open PRs
5items grouped
Known?
Yes. 5 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #16568. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #16568. That is separate from the fix event.
Still open
Nothing open on GitHub.

Multiple fixes and a bug report addressing the absence of a required Date header in outbound emails, which caused messages to be bounced by mail filters. Several parallel or iterative PRs target different code paths where the header was missing.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #16568 fix(email): add required Date header to outbound mail (salvage #15164)

    merged to main

    files: gateway/platforms/email.py, scripts/release.py, tests/gateway/test_email.py, tools/send_message_tool.py

    Show the diff
    • gateway/platforms/email.py
      @@ -28,6 +28,7 @@
       from email.mime.multipart import MIMEMultipart
       from email.mime.text import MIMEText
       from email.mime.base import MIMEBase
      +from email.utils import formatdate
       from email import encoders
       from pathlib import Path
       from typing import Any, Dict, List, Optional
      @@ -504,6 +505,7 @@ def _send_email(
                   msg["In-Reply-To"] = original_msg_id
                   msg["References"] = original_msg_id
       
      +        msg["Date"] = formatdate(localtime=True)
               msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._address.split('@')[1]}>"
               msg["Message-ID"] = msg_id
       
      @@ -586,6 +588,7 @@ def _send_email_with_attachment(
                   msg["In-Reply-To"] = original_msg_id
                   msg["References"] = original_msg_id
       
      +        msg["Date"] = formatdate(localtime=True)
               msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._address.split('@')[1]}>"
               msg["Message-ID"] = msg_id
       
    • scripts/release.py
      @@ -53,6 +53,7 @@
           "[redacted:email]": "say8hi",
           "[redacted:email]": "web3blind",
           "[redacted:email]": "alexg0bot",
      +    "[redacted:email]": "scheidti",
           "[redacted:email]": "benjaminsehl",
           "[redacted:email]": "Nerijusas",
           "[redacted:email]": "Ito-69",
    • tests/gateway/test_email.py
      @@ -488,6 +488,7 @@ def test_reply_uses_re_prefix(self):
                   self.assertEqual(send_call["Subject"], "Re: Project question")
                   self.assertEqual(send_call["In-Reply-To"], "<[redacted:email]>")
                   self.assertEqual(send_call["References"], "<[redacted:email]>")
      +            self.assertIn("Date", send_call)
       
           def test_reply_does_not_double_re(self):
               """If subject already has Re:, don't add another."""
      @@ -519,6 +520,7 @@ def test_no_thread_context_uses_default_subject(self):
       
                   send_call = mock_server.send_message.call_args[0][0]
                   self.assertEqual(send_call["Subject"], "Re: Hermes Agent")
      +            self.assertIn("Date", send_call)
       
       
       class TestSendMethods(unittest.TestCase):
      @@ -889,6 +891,11 @@ def test_send_email_tool_success(self):
                   self.assertEqual(result["platform"], "email")
                   _, kwargs = mock_server.starttls.call_args
                   self.assertIsInstance(kwargs["context"], ssl.SSLContext)
      +            send_call = mock_server.send_message.call_args[0][0]
      +            self.assertEqual(send_call["Subject"], "Hermes Agent")
      +            self.assertIn("Date", send_call)
      +            self.assertEqual(send_call["To"], "[redacted:email]")
      +            self.assertEqual(send_call["From"], "[redacted:email]")
       
           @patch.dict(os.environ, {
               "EMAIL_ADDRESS": "[redacted:email]",
    • tools/send_message_tool.py
      @@ -1075,6 +1075,7 @@ async def _send_email(extra, chat_id, message):
           """Send via SMTP (one-shot, no persistent connection needed)."""
           import smtplib
           from email.mime.text import MIMEText
      +    from email.utils import formatdate
       
           address = extra.get("address") or os.getenv("EMAIL_ADDRESS", "")
           password = [redacted:secret-assignment]"EMAIL_PASSWORD", "")
      @@ -1092,6 +1093,7 @@ async def _send_email(extra, chat_id, message):
               msg["From"] = address
               msg["To"] = chat_id
               msg["Subject"] = "Hermes Agent"
      +        msg["Date"] = formatdate(localtime=True)
       
               server = smtplib.SMTP(smtp_host, smtp_port)
               server.starttls(context=ssl.create_default_context())
  • #19646 fix(cli,email): quoted-relative file-drop paths + Date header on tool email path

    merged to main

    files: cli.py, tools/send_message_tool.py

    Show the diff
    • cli.py
      @@ -1505,6 +1505,10 @@ def _detect_file_drop(user_input: str) -> "dict | None":
               or stripped.startswith('"~')
               or stripped.startswith("'/")
               or stripped.startswith("'~")
      +        or stripped.startswith('"./')
      +        or stripped.startswith('"../')
      +        or stripped.startswith("'./")
      +        or stripped.startswith("'../")
               or (len(stripped) >= 4 and stripped[0] in ("'", '"') and stripped[2] == ":" and stripped[3] in ("\\", "/") and stripped[1].isalpha())
           )
           if not starts_like_path:
    • tools/send_message_tool.py
      @@ -10,9 +10,10 @@
       import logging
       import os
       import re
      -from typing import Dict, Optional
       import ssl
       import time
      +from email.utils import formatdate
      +from typing import Dict, Optional
       
       from agent.redact import redact_sensitive_text
       

2 PRs closed without merging

From the close comments: merged via another change 1 · superseded by another PR 1

  • #15164 fix(email): add required Date header to outbound mail · merged via another change → #16568, #15160
  • #15230 fix(email): add Date header to send_message_tool._send_email (closes #15160) · superseded by another PR → #16568, #15160, #15164
Closed issues · 1
  • Closed#15160[Bug]: Outbound Hermes emails missing Date header — bounced by mail filter
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.40: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Merged PRs
#16568, #19646
Closed issues
1
Attempts
2 PRs closed without merging
Fix link checked
4 May 2026

For your agent

The same facts, typed.