comparison mercurial/mail.py @ 39106:ebf54a34b7b7

mail: pass in addr to _addressencode() in bytes _addressencode() doesn't process a unicode addr well. For example, acc.encode('ascii') would raise UnicodeEncodeError if acc was a unicode. This patch temporarily restores the pre-952bf3c948f0 _addressencode(). Several tests would be broken on Python 3.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 12 Aug 2018 12:11:36 +0900
parents f68ad9b4a43b
children c2327bb3505d
comparison
equal deleted inserted replaced
39105:f68ad9b4a43b 39106:ebf54a34b7b7
306 s, cs = _encode(ui, s, charsets) 306 s, cs = _encode(ui, s, charsets)
307 return str(email.header.Header(s, cs)) 307 return str(email.header.Header(s, cs))
308 return s 308 return s
309 309
310 def _addressencode(ui, name, addr, charsets=None): 310 def _addressencode(ui, name, addr, charsets=None):
311 assert isinstance(addr, bytes)
311 name = headencode(ui, name, charsets) 312 name = headencode(ui, name, charsets)
312 try: 313 try:
313 acc, dom = addr.split(r'@') 314 acc, dom = addr.split('@')
314 acc = acc.encode('ascii') 315 acc = acc.encode('ascii')
315 if isinstance(dom, bytes): 316 dom = dom.decode(encoding.encoding).encode('idna')
316 dom = dom.decode(encoding.encoding)
317 dom = dom.encode('idna')
318 addr = '%s@%s' % (acc, dom) 317 addr = '%s@%s' % (acc, dom)
319 except UnicodeDecodeError: 318 except UnicodeDecodeError:
320 raise error.Abort(_('invalid email address: %s') % addr) 319 raise error.Abort(_('invalid email address: %s') % addr)
321 except ValueError: 320 except ValueError:
322 try: 321 try:
330 def addressencode(ui, address, charsets=None, display=False): 329 def addressencode(ui, address, charsets=None, display=False):
331 '''Turns address into RFC-2047 compliant header.''' 330 '''Turns address into RFC-2047 compliant header.'''
332 if display or not address: 331 if display or not address:
333 return address or '' 332 return address or ''
334 name, addr = email.utils.parseaddr(encoding.strfromlocal(address)) 333 name, addr = email.utils.parseaddr(encoding.strfromlocal(address))
335 return _addressencode(ui, name, addr, charsets) 334 return _addressencode(ui, name, encoding.strtolocal(addr), charsets)
336 335
337 def addrlistencode(ui, addrs, charsets=None, display=False): 336 def addrlistencode(ui, addrs, charsets=None, display=False):
338 '''Turns a list of addresses into a list of RFC-2047 compliant headers. 337 '''Turns a list of addresses into a list of RFC-2047 compliant headers.
339 A single element of input list may contain multiple addresses, but output 338 A single element of input list may contain multiple addresses, but output
340 always has one address per item''' 339 always has one address per item'''
345 344
346 result = [] 345 result = []
347 for name, addr in email.utils.getaddresses( 346 for name, addr in email.utils.getaddresses(
348 [encoding.strfromlocal(a) for a in addrs]): 347 [encoding.strfromlocal(a) for a in addrs]):
349 if name or addr: 348 if name or addr:
350 result.append(_addressencode(ui, name, addr, charsets)) 349 r = _addressencode(ui, name, encoding.strtolocal(addr), charsets)
350 result.append(r)
351 return result 351 return result
352 352
353 def mimeencode(ui, s, charsets=None, display=False): 353 def mimeencode(ui, s, charsets=None, display=False):
354 '''creates mime text object, encodes it if needed, and sets 354 '''creates mime text object, encodes it if needed, and sets
355 charset and transfer-encoding accordingly.''' 355 charset and transfer-encoding accordingly.'''