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' |