diff options
Diffstat (limited to 'Lib/email')
-rw-r--r-- | Lib/email/_policybase.py | 19 | ||||
-rw-r--r-- | Lib/email/message.py | 10 | ||||
-rw-r--r-- | Lib/email/policy.py | 8 |
3 files changed, 37 insertions, 0 deletions
diff --git a/Lib/email/_policybase.py b/Lib/email/_policybase.py index 6bc298b..d5e8df9 100644 --- a/Lib/email/_policybase.py +++ b/Lib/email/_policybase.py @@ -194,6 +194,25 @@ class Policy(_PolicyBase, metaclass=_DocstringExtenderMetaclass): """ obj.defects.append(defect) + def header_max_count(self, name): + """Return the maximum allowed number of headers named 'name'. + + Called when a header is added to a Message object. If the returned + value is not 0 or None, and there are already a number of headers with + the name 'name' equal to the value returned, a ValueError is raised. + + Because the default behavior of Message's __setitem__ is to append the + value to the list of headers, it is easy to create duplicate headers + without realizing it. This method allows certain headers to be limited + in the number of instances of that header that may be added to a + Message programmatically. (The limit is not observed by the parser, + which will faithfully produce as many headers as exist in the message + being parsed.) + + The default implementation returns None for all header names. + """ + return None + @abc.abstractmethod def header_source_parse(self, sourcelines): """Given a list of linesep terminated strings constituting the lines of diff --git a/Lib/email/message.py b/Lib/email/message.py index 62b82b7..9b06207 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -346,6 +346,16 @@ class Message: Note: this does not overwrite an existing header with the same field name. Use __delitem__() first to delete any existing headers. """ + max_count = self.policy.header_max_count(name) + if max_count: + lname = name.lower() + found = 0 + for k, v in self._headers: + if k.lower() == lname: + found += 1 + if found >= max_count: + raise ValueError("There may be at most {} {} headers " + "in a message".format(max_count, name)) self._headers.append(self.policy.header_store_parse(name, val)) def __delitem__(self, name): diff --git a/Lib/email/policy.py b/Lib/email/policy.py index 47ed66b..bfffb45 100644 --- a/Lib/email/policy.py +++ b/Lib/email/policy.py @@ -69,6 +69,14 @@ class EmailPolicy(Policy): object.__setattr__(self, 'header_factory', HeaderRegistry()) super().__init__(**kw) + def header_max_count(self, name): + """+ + The implementation for this class returns the max_count attribute from + the specialized header class that would be used to construct a header + of type 'name'. + """ + return self.header_factory[name].max_count + # The logic of the next three methods is chosen such that it is possible to # switch a Message object between a Compat32 policy and a policy derived # from this class and have the results stay consistent. This allows a |