Commit da7af4d7 authored by R David Murray's avatar R David Murray

Merge #7484: no more <> around addresses in VRFY or EXPN

parents a8713b14 4634676c
...@@ -152,6 +152,13 @@ def quoteaddr(addr): ...@@ -152,6 +152,13 @@ def quoteaddr(addr):
else: else:
return "<%s>" % m return "<%s>" % m
def _addr_only(addrstring):
displayname, addr = email.utils.parseaddr(addrstring)
if (displayname, addr) == ('', ''):
# parseaddr couldn't parse it, so use it as is.
return addrstring
return addr
# Legacy method kept for backward compatibility. # Legacy method kept for backward compatibility.
def quotedata(data): def quotedata(data):
"""Quote data for email. """Quote data for email.
...@@ -507,14 +514,14 @@ class SMTP: ...@@ -507,14 +514,14 @@ class SMTP:
def verify(self, address): def verify(self, address):
"""SMTP 'verify' command -- checks for address validity.""" """SMTP 'verify' command -- checks for address validity."""
self.putcmd("vrfy", quoteaddr(address)) self.putcmd("vrfy", _addr_only(address))
return self.getreply() return self.getreply()
# a.k.a. # a.k.a.
vrfy = verify vrfy = verify
def expn(self, address): def expn(self, address):
"""SMTP 'expn' command -- expands a mailing list.""" """SMTP 'expn' command -- expands a mailing list."""
self.putcmd("expn", quoteaddr(address)) self.putcmd("expn", _addr_only(address))
return self.getreply() return self.getreply()
# some useful methods # some useful methods
......
...@@ -293,6 +293,23 @@ class DebuggingServerTests(unittest.TestCase): ...@@ -293,6 +293,23 @@ class DebuggingServerTests(unittest.TestCase):
mexpect = '%s%s\n%s' % (MSG_BEGIN, m, MSG_END) mexpect = '%s%s\n%s' % (MSG_BEGIN, m, MSG_END)
self.assertEqual(self.output.getvalue(), mexpect) self.assertEqual(self.output.getvalue(), mexpect)
def testSendNullSender(self):
m = 'A test message'
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3)
smtp.sendmail('<>', 'Sally', m)
# XXX (see comment in testSend)
time.sleep(0.01)
smtp.quit()
self.client_evt.set()
self.serv_evt.wait()
self.output.flush()
mexpect = '%s%s\n%s' % (MSG_BEGIN, m, MSG_END)
self.assertEqual(self.output.getvalue(), mexpect)
debugout = smtpd.DEBUGSTREAM.getvalue()
sender = re.compile("^sender: <>$", re.MULTILINE)
self.assertRegex(debugout, sender)
def testSendMessage(self): def testSendMessage(self):
m = email.mime.text.MIMEText('A test message') m = email.mime.text.MIMEText('A test message')
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3)
...@@ -523,7 +540,7 @@ class BadHELOServerTests(unittest.TestCase): ...@@ -523,7 +540,7 @@ class BadHELOServerTests(unittest.TestCase):
sim_users = {'Mr.A@somewhere.com':'John A', sim_users = {'Mr.A@somewhere.com':'John A',
'Ms.B@somewhere.com':'Sally B', 'Ms.B@xn--fo-fka.com':'Sally B',
'Mrs.C@somewhereesle.com':'Ruth C', 'Mrs.C@somewhereesle.com':'Ruth C',
} }
...@@ -539,7 +556,7 @@ sim_auth_credentials = { ...@@ -539,7 +556,7 @@ sim_auth_credentials = {
sim_auth_login_password = 'C29TZXBHC3N3B3JK' sim_auth_login_password = 'C29TZXBHC3N3B3JK'
sim_lists = {'list-1':['Mr.A@somewhere.com','Mrs.C@somewhereesle.com'], sim_lists = {'list-1':['Mr.A@somewhere.com','Mrs.C@somewhereesle.com'],
'list-2':['Ms.B@somewhere.com',], 'list-2':['Ms.B@xn--fo-fka.com',],
} }
# Simulated SMTP channel & server # Simulated SMTP channel & server
...@@ -563,15 +580,14 @@ class SimSMTPChannel(smtpd.SMTPChannel): ...@@ -563,15 +580,14 @@ class SimSMTPChannel(smtpd.SMTPChannel):
self.push(resp) self.push(resp)
def smtp_VRFY(self, arg): def smtp_VRFY(self, arg):
raw_addr = email.utils.parseaddr(arg)[1] # For max compatibility smtplib should be sending the raw address.
quoted_addr = smtplib.quoteaddr(arg) if arg in sim_users:
if raw_addr in sim_users: self.push('250 %s %s' % (sim_users[arg], smtplib.quoteaddr(arg)))
self.push('250 %s %s' % (sim_users[raw_addr], quoted_addr))
else: else:
self.push('550 No such user: %s' % arg) self.push('550 No such user: %s' % arg)
def smtp_EXPN(self, arg): def smtp_EXPN(self, arg):
list_name = email.utils.parseaddr(arg)[1].lower() list_name = arg.lower()
if list_name in sim_lists: if list_name in sim_lists:
user_list = sim_lists[list_name] user_list = sim_lists[list_name]
for n, user_email in enumerate(user_list): for n, user_email in enumerate(user_list):
...@@ -703,8 +719,7 @@ class SMTPSimTests(unittest.TestCase): ...@@ -703,8 +719,7 @@ class SMTPSimTests(unittest.TestCase):
self.assertEqual(smtp.vrfy(email), expected_known) self.assertEqual(smtp.vrfy(email), expected_known)
u = 'nobody@nowhere.com' u = 'nobody@nowhere.com'
expected_unknown = (550, ('No such user: %s' expected_unknown = (550, ('No such user: %s' % u).encode('ascii'))
% smtplib.quoteaddr(u)).encode('ascii'))
self.assertEqual(smtp.vrfy(u), expected_unknown) self.assertEqual(smtp.vrfy(u), expected_unknown)
smtp.quit() smtp.quit()
......
...@@ -234,6 +234,9 @@ Core and Builtins ...@@ -234,6 +234,9 @@ Core and Builtins
Library Library
------- -------
- Issue #7484: smtplib no longer puts <> around addresses in VRFY and EXPN
commands; they aren't required and in fact postfix doesn't support that form.
- Issue #12273: Remove ast.__version__. AST changes can be accounted for by - Issue #12273: Remove ast.__version__. AST changes can be accounted for by
checking sys.version_info or sys._mercurial. checking sys.version_info or sys._mercurial.
......
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