comparison mercurial/mail.py @ 39810:eabdf3c25b8b

mail: cope with Py3 unicode antics on email addresses Differential Revision: https://phab.mercurial-scm.org/D3954
author Augie Fackler <augie@google.com>
date Mon, 16 Jul 2018 17:49:17 -0400 (2018-07-16)
parents 858fe9625dab
children 569d662816de
comparison
equal deleted inserted replaced
39809:858fe9625dab 39810:eabdf3c25b8b
297 return s 297 return s
298 298
299 def _addressencode(ui, name, addr, charsets=None): 299 def _addressencode(ui, name, addr, charsets=None):
300 name = headencode(ui, name, charsets) 300 name = headencode(ui, name, charsets)
301 try: 301 try:
302 acc, dom = addr.split('@') 302 acc, dom = addr.split(r'@')
303 acc = acc.encode('ascii') 303 acc = acc.encode('ascii')
304 dom = dom.decode(encoding.encoding).encode('idna') 304 dom = dom.decode(encoding.encoding).encode('idna')
305 addr = '%s@%s' % (acc, dom) 305 addr = '%s@%s' % (acc, dom)
306 except UnicodeDecodeError: 306 except UnicodeDecodeError:
307 raise error.Abort(_('invalid email address: %s') % addr) 307 raise error.Abort(_('invalid email address: %s') % addr)
309 try: 309 try:
310 # too strict? 310 # too strict?
311 addr = addr.encode('ascii') 311 addr = addr.encode('ascii')
312 except UnicodeDecodeError: 312 except UnicodeDecodeError:
313 raise error.Abort(_('invalid local address: %s') % addr) 313 raise error.Abort(_('invalid local address: %s') % addr)
314 return email.utils.formataddr((name, addr)) 314 return pycompat.bytesurl(
315 email.utils.formataddr((name, encoding.strfromlocal(addr))))
315 316
316 def addressencode(ui, address, charsets=None, display=False): 317 def addressencode(ui, address, charsets=None, display=False):
317 '''Turns address into RFC-2047 compliant header.''' 318 '''Turns address into RFC-2047 compliant header.'''
318 if display or not address: 319 if display or not address:
319 return address or '' 320 return address or ''
320 name, addr = email.utils.parseaddr(address) 321 name, addr = email.utils.parseaddr(encoding.strfromlocal(address))
321 return _addressencode(ui, name, addr, charsets) 322 return _addressencode(ui, name, addr, charsets)
322 323
323 def addrlistencode(ui, addrs, charsets=None, display=False): 324 def addrlistencode(ui, addrs, charsets=None, display=False):
324 '''Turns a list of addresses into a list of RFC-2047 compliant headers. 325 '''Turns a list of addresses into a list of RFC-2047 compliant headers.
325 A single element of input list may contain multiple addresses, but output 326 A single element of input list may contain multiple addresses, but output
326 always has one address per item''' 327 always has one address per item'''
328 for a in addrs:
329 assert isinstance(a, bytes), (r'%r unexpectedly not a bytestr' % a)
327 if display: 330 if display:
328 return [a.strip() for a in addrs if a.strip()] 331 return [a.strip() for a in addrs if a.strip()]
329 332
330 result = [] 333 result = []
331 for name, addr in email.utils.getaddresses(addrs): 334 for name, addr in email.utils.getaddresses(
335 [encoding.strfromlocal(a) for a in addrs]):
332 if name or addr: 336 if name or addr:
333 result.append(_addressencode(ui, name, addr, charsets)) 337 result.append(_addressencode(ui, name, addr, charsets))
334 return result 338 return [pycompat.bytesurl(r) for r in result]
335 339
336 def mimeencode(ui, s, charsets=None, display=False): 340 def mimeencode(ui, s, charsets=None, display=False):
337 '''creates mime text object, encodes it if needed, and sets 341 '''creates mime text object, encodes it if needed, and sets
338 charset and transfer-encoding accordingly.''' 342 charset and transfer-encoding accordingly.'''
339 cs = 'us-ascii' 343 cs = 'us-ascii'