https://github.com/python/cpython/commit/7a7da86d66e146b82eaac8ccc47584e3c1b38008
commit: 7a7da86d66e146b82eaac8ccc47584e3c1b38008
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: bitdancer <[email protected]>
date: 2026-07-09T15:53:49-04:00
summary:

[3.14] gh-153406: Raise ValueError, not OverflowError, for out-of-range dates 
in email.utils.parsedate_to_datetime (GH-153407) (#153434)

email.utils.parsedate_to_datetime documented that it raises ValueError for an 
invalid date, but it leaked OverflowError when the parsed year or timezone 
offset was too large for the datetime and timedelta constructors, and that 
OverflowError also escaped the modern header parsing path since 
DateHeader.parse only caught ValueError. Wrap the datetime and timezone 
construction so an OverflowError is re-raised as a ValueError with the original 
chained as the cause, which restores the documented contract and lets the 
existing header handler record an InvalidDateDefect instead of raising.
(cherry picked from commit 37a26b9b94b147b5d683bfce0ef5a4c2fbc21085)

Co-authored-by: tonghuaroot (童话) <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-07-09-00-00-00.gh-issue-153406.vyMmB6.rst
M Lib/email/utils.py
M Lib/test/test_email/test_headerregistry.py
M Lib/test/test_email/test_utils.py

diff --git a/Lib/email/utils.py b/Lib/email/utils.py
index 3de1f0d24a15b0a..5838a8085687953 100644
--- a/Lib/email/utils.py
+++ b/Lib/email/utils.py
@@ -317,10 +317,13 @@ def parsedate_to_datetime(data):
     if parsed_date_tz is None:
         raise ValueError('Invalid date value or format "%s"' % str(data))
     *dtuple, tz = parsed_date_tz
-    if tz is None:
-        return datetime.datetime(*dtuple[:6])
-    return datetime.datetime(*dtuple[:6],
-            tzinfo=datetime.timezone(datetime.timedelta(seconds=tz)))
+    try:
+        if tz is None:
+            return datetime.datetime(*dtuple[:6])
+        return datetime.datetime(*dtuple[:6],
+                tzinfo=datetime.timezone(datetime.timedelta(seconds=tz)))
+    except OverflowError as exc:
+        raise ValueError('Invalid date value or format "%s"' % str(data)) from 
exc
 
 
 def parseaddr(addr, *, strict=True):
diff --git a/Lib/test/test_email/test_headerregistry.py 
b/Lib/test/test_email/test_headerregistry.py
index d0643be2ce0de80..ddf0fc64b0c676a 100644
--- a/Lib/test/test_email/test_headerregistry.py
+++ b/Lib/test/test_email/test_headerregistry.py
@@ -220,6 +220,14 @@ def test_invalid_date_value(self):
         self.assertEqual(len(h.defects), 1)
         self.assertIsInstance(h.defects[0], errors.InvalidDateDefect)
 
+    def test_out_of_range_date_value(self):
+        s = 'Mon, 20 Nov 9999999999 12:00:00 +0000'
+        h = self.make_header('date', s)
+        self.assertEqual(h, s)
+        self.assertIsNone(h.datetime)
+        self.assertEqual(len(h.defects), 1)
+        self.assertIsInstance(h.defects[0], errors.InvalidDateDefect)
+
     def test_datetime_read_only(self):
         h = self.make_header('date', self.datestring)
         with self.assertRaises(AttributeError):
diff --git a/Lib/test/test_email/test_utils.py 
b/Lib/test/test_email/test_utils.py
index c9d09098b502f9d..86d1bfff891a7e6 100644
--- a/Lib/test/test_email/test_utils.py
+++ b/Lib/test/test_email/test_utils.py
@@ -77,6 +77,15 @@ def 
test_parsedate_to_datetime_with_invalid_raises_valueerror(self):
             with self.subTest(dtstr=dtstr):
                 self.assertRaises(ValueError, utils.parsedate_to_datetime, 
dtstr)
 
+    def test_parsedate_to_datetime_out_of_range_raises_valueerror(self):
+        out_of_range_dates = [
+            'Mon, 20 Nov 9999999999 12:00:00 +0000',
+            'Mon, 20 Nov 2017 12:00:00 +24000000000000',
+        ]
+        for dtstr in out_of_range_dates:
+            with self.subTest(dtstr=dtstr):
+                self.assertRaises(ValueError, utils.parsedate_to_datetime, 
dtstr)
+
 class LocaltimeTests(unittest.TestCase):
 
     def test_localtime_is_tz_aware_daylight_true(self):
diff --git 
a/Misc/NEWS.d/next/Library/2026-07-09-00-00-00.gh-issue-153406.vyMmB6.rst 
b/Misc/NEWS.d/next/Library/2026-07-09-00-00-00.gh-issue-153406.vyMmB6.rst
new file mode 100644
index 000000000000000..c09575754e33804
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-09-00-00-00.gh-issue-153406.vyMmB6.rst
@@ -0,0 +1,3 @@
+:func:`email.utils.parsedate_to_datetime` now raises :exc:`ValueError`
+instead of :exc:`OverflowError` when the parsed year or timezone offset is
+out of range, matching its documented behavior.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to