Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
gh-148192: Fix Generator._make_boundary behavior with CRLF line endin…
…gs. (GH-148193)

The Generator._make_boundary regex did not match on boundary phrases correctly when using CRLF line endings due to re.MULTILINE not considering \r\n as a line ending.
(cherry picked from commit 4af46b4)

Co-authored-by: Henry Jones <[email protected]>
  • Loading branch information
henryivesjones authored and miss-islington committed Apr 14, 2026
commit 56bbb3d91080e180fcc6f75c4e1c810603177e2f
2 changes: 1 addition & 1 deletion Lib/email/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def _make_boundary(cls, text=None):
b = boundary
counter = 0
while True:
cre = cls._compile_re('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
cre = cls._compile_re('^--' + re.escape(b) + '(--)?\r?$', re.MULTILINE)
if not cre.search(text):
break
b = boundary + '.' + str(counter)
Expand Down
37 changes: 37 additions & 0 deletions Lib/test/test_email/test_generator.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import io
import textwrap
import unittest
import random
import sys
from email import message_from_string, message_from_bytes
from email.message import EmailMessage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.generator import Generator, BytesGenerator
import email.generator
from email.headerregistry import Address
from email import policy
import email.errors
from test.test_email import TestEmailBase, parameterize
import test.support



@parameterize
Expand Down Expand Up @@ -288,6 +295,36 @@ def test_keep_long_encoded_newlines(self):
g.flatten(msg)
self.assertEqual(s.getvalue(), self.typ(expected))

def _test_boundary_detection(self, linesep):
# Generate a boundary token in the same way as _make_boundary
token = random.randrange(sys.maxsize)

def _patch_random_randrange(*args, **kwargs):
return token

with test.support.swap_attr(
random, "randrange", _patch_random_randrange
):
boundary = self.genclass._make_boundary(text=None)
boundary_in_part = (
"this goes before the boundary\n--"
+ boundary
+ "\nthis goes after\n"
)
msg = MIMEMultipart()
msg.attach(MIMEText(boundary_in_part))
self.genclass(self.ioclass()).flatten(msg, linesep=linesep)
# Generator checks the message content for the string it is about
# to use as a boundary ('token' in this test) and when it finds it
# in our attachment appends .0 to make the boundary it uses unique.
self.assertEqual(msg.get_boundary(), boundary + ".0")

def test_lf_boundary_detection(self):
self._test_boundary_detection("\n")

def test_crlf_boundary_detection(self):
self._test_boundary_detection("\r\n")


class TestGenerator(TestGeneratorBase, TestEmailBase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
``email.generator.Generator._make_boundary`` could fail to detect a duplicate
boundary string if linesep was not \n. It now correctly detects boundary
strings when linesep is \r\n as well.
Loading