mirror of
https://github.com/python/cpython.git
synced 2025-11-24 12:20:42 +00:00
Some checks are pending
Tests / Change detection (push) Waiting to run
Tests / Docs (push) Blocked by required conditions
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / (push) Blocked by required conditions
Tests / Windows MSI (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / Ubuntu SSL tests with AWS-LC (push) Blocked by required conditions
Tests / Android (aarch64) (push) Blocked by required conditions
Tests / Android (x86_64) (push) Blocked by required conditions
Tests / iOS (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / Sanitizers (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/jit (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run
Update selected RFC 2822 references to RFC 5322 RFC 2822 was obsoleted by RFC 5322 in 2008. This updates references to use the current standard in documentation, docstrings, and comments. It preserves RFC 2822 references in legacy API components to maintain their historical context. RFC 822 → RFC 2822 → RFC 5322 progression is explained where relevant. In some places specific sections of RFC are referenced where it seems helpful. Scout rule was applied in some places and RFC mentions format was normalized in doc strings and comments.
127 lines
4.9 KiB
Python
127 lines
4.9 KiB
Python
# Copyright (C) 2001 Python Software Foundation
|
|
# Author: Barry Warsaw, Thomas Wouters, Anthony Baxter
|
|
# Contact: email-sig@python.org
|
|
|
|
"""A parser of RFC 5322 and MIME email messages."""
|
|
|
|
__all__ = ['Parser', 'HeaderParser', 'BytesParser', 'BytesHeaderParser',
|
|
'FeedParser', 'BytesFeedParser']
|
|
|
|
from io import StringIO, TextIOWrapper
|
|
|
|
from email.feedparser import FeedParser, BytesFeedParser
|
|
from email._policybase import compat32
|
|
|
|
|
|
class Parser:
|
|
def __init__(self, _class=None, *, policy=compat32):
|
|
"""Parser of RFC 5322 and MIME email messages.
|
|
|
|
Creates an in-memory object tree representing the email message, which
|
|
can then be manipulated and turned over to a Generator to return the
|
|
textual representation of the message.
|
|
|
|
The string must be formatted as a block of RFC 5322 headers and header
|
|
continuation lines, optionally preceded by a 'Unix-from' header. The
|
|
header block is terminated either by the end of the string or by a
|
|
blank line.
|
|
|
|
_class is the class to instantiate for new message objects when they
|
|
must be created. This class must have a constructor that can take
|
|
zero arguments. Default is Message.Message.
|
|
|
|
The policy keyword specifies a policy object that controls a number of
|
|
aspects of the parser's operation. The default policy maintains
|
|
backward compatibility.
|
|
|
|
"""
|
|
self._class = _class
|
|
self.policy = policy
|
|
|
|
def parse(self, fp, headersonly=False):
|
|
"""Create a message structure from the data in a file.
|
|
|
|
Reads all the data from the file and returns the root of the message
|
|
structure. Optional headersonly is a flag specifying whether to stop
|
|
parsing after reading the headers or not. The default is False,
|
|
meaning it parses the entire contents of the file.
|
|
"""
|
|
feedparser = FeedParser(self._class, policy=self.policy)
|
|
if headersonly:
|
|
feedparser._set_headersonly()
|
|
while data := fp.read(8192):
|
|
feedparser.feed(data)
|
|
return feedparser.close()
|
|
|
|
def parsestr(self, text, headersonly=False):
|
|
"""Create a message structure from a string.
|
|
|
|
Returns the root of the message structure. Optional headersonly is a
|
|
flag specifying whether to stop parsing after reading the headers or
|
|
not. The default is False, meaning it parses the entire contents of
|
|
the file.
|
|
"""
|
|
return self.parse(StringIO(text), headersonly=headersonly)
|
|
|
|
|
|
class HeaderParser(Parser):
|
|
def parse(self, fp, headersonly=True):
|
|
return Parser.parse(self, fp, True)
|
|
|
|
def parsestr(self, text, headersonly=True):
|
|
return Parser.parsestr(self, text, True)
|
|
|
|
|
|
class BytesParser:
|
|
|
|
def __init__(self, *args, **kw):
|
|
"""Parser of binary RFC 5322 and MIME email messages.
|
|
|
|
Creates an in-memory object tree representing the email message, which
|
|
can then be manipulated and turned over to a Generator to return the
|
|
textual representation of the message.
|
|
|
|
The input must be formatted as a block of RFC 5322 headers and header
|
|
continuation lines, optionally preceded by a 'Unix-from' header. The
|
|
header block is terminated either by the end of the input or by a
|
|
blank line.
|
|
|
|
_class is the class to instantiate for new message objects when they
|
|
must be created. This class must have a constructor that can take
|
|
zero arguments. Default is Message.Message.
|
|
"""
|
|
self.parser = Parser(*args, **kw)
|
|
|
|
def parse(self, fp, headersonly=False):
|
|
"""Create a message structure from the data in a binary file.
|
|
|
|
Reads all the data from the file and returns the root of the message
|
|
structure. Optional headersonly is a flag specifying whether to stop
|
|
parsing after reading the headers or not. The default is False,
|
|
meaning it parses the entire contents of the file.
|
|
"""
|
|
fp = TextIOWrapper(fp, encoding='ascii', errors='surrogateescape')
|
|
try:
|
|
return self.parser.parse(fp, headersonly)
|
|
finally:
|
|
fp.detach()
|
|
|
|
|
|
def parsebytes(self, text, headersonly=False):
|
|
"""Create a message structure from a byte string.
|
|
|
|
Returns the root of the message structure. Optional headersonly is a
|
|
flag specifying whether to stop parsing after reading the headers or
|
|
not. The default is False, meaning it parses the entire contents of
|
|
the file.
|
|
"""
|
|
text = text.decode('ASCII', errors='surrogateescape')
|
|
return self.parser.parsestr(text, headersonly)
|
|
|
|
|
|
class BytesHeaderParser(BytesParser):
|
|
def parse(self, fp, headersonly=True):
|
|
return BytesParser.parse(self, fp, headersonly=True)
|
|
|
|
def parsebytes(self, text, headersonly=True):
|
|
return BytesParser.parsebytes(self, text, headersonly=True)
|