Skip to content

Commit 6baa0a5

Browse files
Issue #6598: Increased time precision and random number range in
email.utils.make_msgid() to strengthen the uniqueness of the message ID.
2 parents 8687275 + ae760c0 commit 6baa0a5

File tree

3 files changed

+31
-6
lines changed

3 files changed

+31
-6
lines changed

Lib/email/utils.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,24 +202,23 @@ def format_datetime(dt, usegmt=False):
202202
def make_msgid(idstring=None, domain=None):
203203
"""Returns a string suitable for RFC 2822 compliant Message-ID, e.g:
204204
205-
<20020201195627.33539.96671@nightshade.la.mastaler.com>
205+
<142480216486.20800.16526388040877946887@nightshade.la.mastaler.com>
206206
207207
Optional idstring if given is a string used to strengthen the
208208
uniqueness of the message id. Optional domain if given provides the
209209
portion of the message id after the '@'. It defaults to the locally
210210
defined hostname.
211211
"""
212-
timeval = time.time()
213-
utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval))
212+
timeval = int(time.time()*100)
214213
pid = os.getpid()
215-
randint = random.randrange(100000)
214+
randint = random.getrandbits(64)
216215
if idstring is None:
217216
idstring = ''
218217
else:
219218
idstring = '.' + idstring
220219
if domain is None:
221220
domain = socket.getfqdn()
222-
msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, domain)
221+
msgid = '<%d.%d.%d%s@%s>' % (timeval, pid, randint, idstring, domain)
223222
return msgid
224223

225224

Lib/test/test_email/test_email.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
from io import StringIO, BytesIO
1212
from itertools import chain
1313
from random import choice
14+
try:
15+
from threading import Thread
16+
except ImportError:
17+
from dummy_threading import Thread
1418

1519
import email
1620
import email.policy
@@ -34,7 +38,7 @@
3438
from email import base64mime
3539
from email import quoprimime
3640

37-
from test.support import unlink
41+
from test.support import unlink, start_threads
3842
from test.test_email import openfile, TestEmailBase
3943

4044
# These imports are documented to work, but we are testing them using a
@@ -3167,6 +3171,25 @@ def test_getaddresses_embedded_comment(self):
31673171
addrs = utils.getaddresses(['User ((nested comment)) <[email protected]>'])
31683172
eq(addrs[0][1], '[email protected]')
31693173

3174+
def test_make_msgid_collisions(self):
3175+
# Test make_msgid uniqueness, even with multiple threads
3176+
class MsgidsThread(Thread):
3177+
def run(self):
3178+
# generate msgids for 3 seconds
3179+
self.msgids = []
3180+
append = self.msgids.append
3181+
make_msgid = utils.make_msgid
3182+
clock = time.clock
3183+
tfin = clock() + 3.0
3184+
while clock() < tfin:
3185+
append(make_msgid(domain='testdomain-string'))
3186+
3187+
threads = [MsgidsThread() for i in range(5)]
3188+
with start_threads(threads):
3189+
pass
3190+
all_ids = sum([t.msgids for t in threads], [])
3191+
self.assertEqual(len(set(all_ids)), len(all_ids))
3192+
31703193
def test_utils_quote_unquote(self):
31713194
eq = self.assertEqual
31723195
msg = Message()

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ Core and Builtins
4949
Library
5050
-------
5151

52+
- Issue #6598: Increased time precision and random number range in
53+
email.utils.make_msgid() to strengthen the uniqueness of the message ID.
54+
5255
- Issue #24091: Fixed various crashes in corner cases in C implementation of
5356
ElementTree.
5457

0 commit comments

Comments
 (0)