##// END OF EJS Templates
mail: let all charset values be native strings...
Denis Laxalde -
r44025:bdb0ddab default
parent child Browse files
Show More
@@ -253,17 +253,13 b' def validateconfig(ui):'
253 253
254 254
255 255 def codec2iana(cs):
256 # type: (bytes) -> bytes
256 # type: (str) -> str
257 257 ''''''
258 cs = pycompat.sysbytes(
259 email.charset.Charset(
260 cs # pytype: disable=wrong-arg-types
261 ).input_charset.lower()
262 )
258 cs = email.charset.Charset(cs).input_charset.lower()
263 259
264 260 # "latin1" normalizes to "iso8859-1", standard calls for "iso-8859-1"
265 if cs.startswith(b"iso") and not cs.startswith(b"iso-"):
266 return b"iso-" + cs[3:]
261 if cs.startswith("iso") and not cs.startswith("iso-"):
262 return "iso-" + cs[3:]
267 263 return cs
268 264
269 265
@@ -275,27 +271,30 b" def mimetextpatch(s, subtype=b'plain', d"
275 271 ISO-8859-1, an encoding with that allows all byte sequences.
276 272 Transfer encodings will be used if necessary.'''
277 273
278 cs = [b'us-ascii', b'utf-8', encoding.encoding, encoding.fallbackencoding]
274 cs = [
275 'us-ascii',
276 'utf-8',
277 pycompat.sysstr(encoding.encoding),
278 pycompat.sysstr(encoding.fallbackencoding),
279 ]
279 280 if display:
280 cs = [b'us-ascii']
281 cs = ['us-ascii']
281 282 for charset in cs:
282 283 try:
283 s.decode(pycompat.sysstr(charset))
284 s.decode(charset)
284 285 return mimetextqp(s, subtype, codec2iana(charset))
285 286 except UnicodeDecodeError:
286 287 pass
287 288
288 return mimetextqp(s, subtype, b"iso-8859-1")
289 return mimetextqp(s, subtype, "iso-8859-1")
289 290
290 291
291 292 def mimetextqp(body, subtype, charset):
292 # type: (bytes, bytes, bytes) -> email.message.Message
293 # type: (bytes, bytes, str) -> email.message.Message
293 294 '''Return MIME message.
294 295 Quoted-printable transfer encoding will be used if necessary.
295 296 '''
296 # Experimentally charset is okay as a bytes even if the type
297 # stubs disagree.
298 cs = email.charset.Charset(charset) # pytype: disable=wrong-arg-types
297 cs = email.charset.Charset(charset)
299 298 msg = email.message.Message()
300 299 msg.set_type(pycompat.sysstr(b'text/' + subtype))
301 300
@@ -317,24 +316,25 b' def mimetextqp(body, subtype, charset):'
317 316
318 317
319 318 def _charsets(ui):
320 # type: (Any) -> List[bytes]
319 # type: (Any) -> List[str]
321 320 '''Obtains charsets to send mail parts not containing patches.'''
322 321 charsets = [
323 cs.lower() for cs in ui.configlist(b'email', b'charsets')
324 ] # type: List[bytes]
322 pycompat.sysstr(cs.lower())
323 for cs in ui.configlist(b'email', b'charsets')
324 ]
325 325 fallbacks = [
326 encoding.fallbackencoding.lower(),
327 encoding.encoding.lower(),
328 b'utf-8',
329 ] # type: List[bytes]
326 pycompat.sysstr(encoding.fallbackencoding.lower()),
327 pycompat.sysstr(encoding.encoding.lower()),
328 'utf-8',
329 ]
330 330 for cs in fallbacks: # find unique charsets while keeping order
331 331 if cs not in charsets:
332 332 charsets.append(cs)
333 return [cs for cs in charsets if not cs.endswith(b'ascii')]
333 return [cs for cs in charsets if not cs.endswith('ascii')]
334 334
335 335
336 336 def _encode(ui, s, charsets):
337 # type: (Any, bytes, List[bytes]) -> Tuple[bytes, bytes]
337 # type: (Any, bytes, List[str]) -> Tuple[bytes, str]
338 338 '''Returns (converted) string, charset tuple.
339 339 Finds out best charset by cycling through sendcharsets in descending
340 340 order. Tries both encoding and fallbackencoding for input. Only as
@@ -347,14 +347,17 b' def _encode(ui, s, charsets):'
347 347 # wants, and fall back to garbage-in-ascii.
348 348 for ocs in sendcharsets:
349 349 try:
350 return s.encode(pycompat.sysstr(ocs)), ocs
350 return s.encode(ocs), ocs
351 351 except UnicodeEncodeError:
352 352 pass
353 353 except LookupError:
354 ui.warn(_(b'ignoring invalid sendcharset: %s\n') % ocs)
354 ui.warn(
355 _(b'ignoring invalid sendcharset: %s\n')
356 % pycompat.sysbytes(ocs)
357 )
355 358 else:
356 359 # Everything failed, ascii-armor what we've got and send it.
357 return s.encode('ascii', 'backslashreplace'), b'us-ascii'
360 return s.encode('ascii', 'backslashreplace'), 'us-ascii'
358 361 # We have a bytes of unknown encoding. We'll try and guess a valid
359 362 # encoding, falling back to pretending we had ascii even though we
360 363 # know that's wrong.
@@ -369,29 +372,30 b' def _encode(ui, s, charsets):'
369 372 continue
370 373 for ocs in sendcharsets:
371 374 try:
372 return u.encode(pycompat.sysstr(ocs)), ocs
375 return u.encode(ocs), ocs
373 376 except UnicodeEncodeError:
374 377 pass
375 378 except LookupError:
376 ui.warn(_(b'ignoring invalid sendcharset: %s\n') % ocs)
379 ui.warn(
380 _(b'ignoring invalid sendcharset: %s\n')
381 % pycompat.sysbytes(ocs)
382 )
377 383 # if ascii, or all conversion attempts fail, send (broken) ascii
378 return s, b'us-ascii'
384 return s, 'us-ascii'
379 385
380 386
381 387 def headencode(ui, s, charsets=None, display=False):
382 # type: (Any, Union[bytes, str], List[bytes], bool) -> str
388 # type: (Any, Union[bytes, str], List[str], bool) -> str
383 389 '''Returns RFC-2047 compliant header from given string.'''
384 390 if not display:
385 391 # split into words?
386 392 s, cs = _encode(ui, s, charsets)
387 return email.header.Header(
388 s, cs # pytype: disable=wrong-arg-types
389 ).encode()
393 return email.header.Header(s, cs).encode()
390 394 return encoding.strfromlocal(s)
391 395
392 396
393 397 def _addressencode(ui, name, addr, charsets=None):
394 # type: (Any, str, bytes, List[bytes]) -> str
398 # type: (Any, str, bytes, List[str]) -> str
395 399 assert isinstance(addr, bytes)
396 400 name = headencode(ui, name, charsets)
397 401 try:
@@ -411,7 +415,7 b' def _addressencode(ui, name, addr, chars'
411 415
412 416
413 417 def addressencode(ui, address, charsets=None, display=False):
414 # type: (Any, bytes, List[bytes], bool) -> str
418 # type: (Any, bytes, List[str], bool) -> str
415 419 '''Turns address into RFC-2047 compliant header.'''
416 420 if display or not address:
417 421 return encoding.strfromlocal(address or b'')
@@ -420,7 +424,7 b' def addressencode(ui, address, charsets='
420 424
421 425
422 426 def addrlistencode(ui, addrs, charsets=None, display=False):
423 # type: (Any, List[bytes], List[bytes], bool) -> List[str]
427 # type: (Any, List[bytes], List[str], bool) -> List[str]
424 428 '''Turns a list of addresses into a list of RFC-2047 compliant headers.
425 429 A single element of input list may contain multiple addresses, but output
426 430 always has one address per item'''
@@ -440,10 +444,10 b' def addrlistencode(ui, addrs, charsets=N'
440 444
441 445
442 446 def mimeencode(ui, s, charsets=None, display=False):
443 # type: (Any, bytes, List[bytes], bool) -> email.message.Message
447 # type: (Any, bytes, List[str], bool) -> email.message.Message
444 448 '''creates mime text object, encodes it if needed, and sets
445 449 charset and transfer-encoding accordingly.'''
446 cs = b'us-ascii'
450 cs = 'us-ascii'
447 451 if not display:
448 452 s, cs = _encode(ui, s, charsets)
449 453 return mimetextqp(s, b'plain', cs)
General Comments 0
You need to be logged in to leave comments. Login now