Commit ae760c0a authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #6598: Increased time precision and random number range in

email.utils.make_msgid() to strengthen the uniqueness of the message ID.
parent 315e104d
...@@ -202,24 +202,23 @@ def format_datetime(dt, usegmt=False): ...@@ -202,24 +202,23 @@ def format_datetime(dt, usegmt=False):
def make_msgid(idstring=None, domain=None): def make_msgid(idstring=None, domain=None):
"""Returns a string suitable for RFC 2822 compliant Message-ID, e.g: """Returns a string suitable for RFC 2822 compliant Message-ID, e.g:
<20020201195627.33539.96671@nightshade.la.mastaler.com> <142480216486.20800.16526388040877946887@nightshade.la.mastaler.com>
Optional idstring if given is a string used to strengthen the Optional idstring if given is a string used to strengthen the
uniqueness of the message id. Optional domain if given provides the uniqueness of the message id. Optional domain if given provides the
portion of the message id after the '@'. It defaults to the locally portion of the message id after the '@'. It defaults to the locally
defined hostname. defined hostname.
""" """
timeval = time.time() timeval = int(time.time()*100)
utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval))
pid = os.getpid() pid = os.getpid()
randint = random.randrange(100000) randint = random.getrandbits(64)
if idstring is None: if idstring is None:
idstring = '' idstring = ''
else: else:
idstring = '.' + idstring idstring = '.' + idstring
if domain is None: if domain is None:
domain = socket.getfqdn() domain = socket.getfqdn()
msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, domain) msgid = '<%d.%d.%d%s@%s>' % (timeval, pid, randint, idstring, domain)
return msgid return msgid
......
...@@ -11,6 +11,10 @@ import textwrap ...@@ -11,6 +11,10 @@ import textwrap
from io import StringIO, BytesIO from io import StringIO, BytesIO
from itertools import chain from itertools import chain
from random import choice from random import choice
try:
from threading import Thread
except ImportError:
from dummy_threading import Thread
import email import email
import email.policy import email.policy
...@@ -34,7 +38,7 @@ from email import iterators ...@@ -34,7 +38,7 @@ from email import iterators
from email import base64mime from email import base64mime
from email import quoprimime from email import quoprimime
from test.support import unlink from test.support import unlink, start_threads
from test.test_email import openfile, TestEmailBase from test.test_email import openfile, TestEmailBase
# These imports are documented to work, but we are testing them using a # These imports are documented to work, but we are testing them using a
...@@ -3152,6 +3156,25 @@ Foo ...@@ -3152,6 +3156,25 @@ Foo
addrs = utils.getaddresses(['User ((nested comment)) <foo@bar.com>']) addrs = utils.getaddresses(['User ((nested comment)) <foo@bar.com>'])
eq(addrs[0][1], 'foo@bar.com') eq(addrs[0][1], 'foo@bar.com')
def test_make_msgid_collisions(self):
# Test make_msgid uniqueness, even with multiple threads
class MsgidsThread(Thread):
def run(self):
# generate msgids for 3 seconds
self.msgids = []
append = self.msgids.append
make_msgid = utils.make_msgid
clock = time.clock
tfin = clock() + 3.0
while clock() < tfin:
append(make_msgid(domain='testdomain-string'))
threads = [MsgidsThread() for i in range(5)]
with start_threads(threads):
pass
all_ids = sum([t.msgids for t in threads], [])
self.assertEqual(len(set(all_ids)), len(all_ids))
def test_utils_quote_unquote(self): def test_utils_quote_unquote(self):
eq = self.assertEqual eq = self.assertEqual
msg = Message() msg = Message()
......
...@@ -50,6 +50,9 @@ Core and Builtins ...@@ -50,6 +50,9 @@ Core and Builtins
Library Library
------- -------
- Issue #6598: Increased time precision and random number range in
email.utils.make_msgid() to strengthen the uniqueness of the message ID.
- Issue #24091: Fixed various crashes in corner cases in C implementation of - Issue #24091: Fixed various crashes in corner cases in C implementation of
ElementTree. ElementTree.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment