Show More
@@ -36,6 +36,12 b' from .utils import (' | |||
|
36 | 36 | stringutil, |
|
37 | 37 | ) |
|
38 | 38 | |
|
39 | if not globals(): # hide this from non-pytype users | |
|
40 | from typing import Any, List, Tuple, Union | |
|
41 | ||
|
42 | # keep pyflakes happy | |
|
43 | assert all((Any, List, Tuple, Union)) | |
|
44 | ||
|
39 | 45 | |
|
40 | 46 | class STARTTLS(smtplib.SMTP): |
|
41 | 47 | '''Derived class to verify the peer certificate for STARTTLS. |
@@ -99,6 +105,7 b' class SMTPS(smtplib.SMTP):' | |||
|
99 | 105 | |
|
100 | 106 | |
|
101 | 107 | def _pyhastls(): |
|
108 | # type: () -> bool | |
|
102 | 109 | """Returns true iff Python has TLS support, false otherwise.""" |
|
103 | 110 | try: |
|
104 | 111 | import ssl |
@@ -246,8 +253,13 b' def validateconfig(ui):' | |||
|
246 | 253 | |
|
247 | 254 | |
|
248 | 255 | def codec2iana(cs): |
|
256 | # type: (bytes) -> bytes | |
|
249 | 257 | '''''' |
|
250 | cs = pycompat.sysbytes(email.charset.Charset(cs).input_charset.lower()) | |
|
258 | cs = pycompat.sysbytes( | |
|
259 | email.charset.Charset( | |
|
260 | cs # pytype: disable=wrong-arg-types | |
|
261 | ).input_charset.lower() | |
|
262 | ) | |
|
251 | 263 | |
|
252 | 264 | # "latin1" normalizes to "iso8859-1", standard calls for "iso-8859-1" |
|
253 | 265 | if cs.startswith(b"iso") and not cs.startswith(b"iso-"): |
@@ -256,6 +268,7 b' def codec2iana(cs):' | |||
|
256 | 268 | |
|
257 | 269 | |
|
258 | 270 | def mimetextpatch(s, subtype=b'plain', display=False): |
|
271 | # type: (bytes, bytes, bool) -> email.message.Message | |
|
259 | 272 | '''Return MIME message suitable for a patch. |
|
260 | 273 | Charset will be detected by first trying to decode as us-ascii, then utf-8, |
|
261 | 274 | and finally the global encodings. If all those fail, fall back to |
@@ -276,6 +289,7 b" def mimetextpatch(s, subtype=b'plain', d" | |||
|
276 | 289 | |
|
277 | 290 | |
|
278 | 291 | def mimetextqp(body, subtype, charset): |
|
292 | # type: (bytes, bytes, bytes) -> email.message.Message | |
|
279 | 293 | '''Return MIME message. |
|
280 | 294 | Quoted-printable transfer encoding will be used if necessary. |
|
281 | 295 | ''' |
@@ -303,13 +317,16 b' def mimetextqp(body, subtype, charset):' | |||
|
303 | 317 | |
|
304 | 318 | |
|
305 | 319 | def _charsets(ui): |
|
320 | # type: (Any) -> List[bytes] | |
|
306 | 321 | '''Obtains charsets to send mail parts not containing patches.''' |
|
307 | charsets = [cs.lower() for cs in ui.configlist(b'email', b'charsets')] | |
|
322 | charsets = [ | |
|
323 | cs.lower() for cs in ui.configlist(b'email', b'charsets') | |
|
324 | ] # type: List[bytes] | |
|
308 | 325 | fallbacks = [ |
|
309 | 326 | encoding.fallbackencoding.lower(), |
|
310 | 327 | encoding.encoding.lower(), |
|
311 | 328 | b'utf-8', |
|
312 | ] | |
|
329 | ] # type: List[bytes] | |
|
313 | 330 | for cs in fallbacks: # find unique charsets while keeping order |
|
314 | 331 | if cs not in charsets: |
|
315 | 332 | charsets.append(cs) |
@@ -317,6 +334,7 b' def _charsets(ui):' | |||
|
317 | 334 | |
|
318 | 335 | |
|
319 | 336 | def _encode(ui, s, charsets): |
|
337 | # type: (Any, bytes, List[bytes]) -> Tuple[bytes, bytes] | |
|
320 | 338 | '''Returns (converted) string, charset tuple. |
|
321 | 339 | Finds out best charset by cycling through sendcharsets in descending |
|
322 | 340 | order. Tries both encoding and fallbackencoding for input. Only as |
@@ -361,15 +379,19 b' def _encode(ui, s, charsets):' | |||
|
361 | 379 | |
|
362 | 380 | |
|
363 | 381 | def headencode(ui, s, charsets=None, display=False): |
|
382 | # type: (Any, Union[bytes, str], List[bytes], bool) -> str | |
|
364 | 383 | '''Returns RFC-2047 compliant header from given string.''' |
|
365 | 384 | if not display: |
|
366 | 385 | # split into words? |
|
367 | 386 | s, cs = _encode(ui, s, charsets) |
|
368 |
return email.header.Header( |
|
|
387 | return email.header.Header( | |
|
388 | s, cs # pytype: disable=wrong-arg-types | |
|
389 | ).encode() | |
|
369 | 390 | return encoding.strfromlocal(s) |
|
370 | 391 | |
|
371 | 392 | |
|
372 | 393 | def _addressencode(ui, name, addr, charsets=None): |
|
394 | # type: (Any, str, bytes, List[bytes]) -> str | |
|
373 | 395 | assert isinstance(addr, bytes) |
|
374 | 396 | name = headencode(ui, name, charsets) |
|
375 | 397 | try: |
@@ -389,6 +411,7 b' def _addressencode(ui, name, addr, chars' | |||
|
389 | 411 | |
|
390 | 412 | |
|
391 | 413 | def addressencode(ui, address, charsets=None, display=False): |
|
414 | # type: (Any, bytes, List[bytes], bool) -> str | |
|
392 | 415 | '''Turns address into RFC-2047 compliant header.''' |
|
393 | 416 | if display or not address: |
|
394 | 417 | return encoding.strfromlocal(address or b'') |
@@ -397,6 +420,7 b' def addressencode(ui, address, charsets=' | |||
|
397 | 420 | |
|
398 | 421 | |
|
399 | 422 | def addrlistencode(ui, addrs, charsets=None, display=False): |
|
423 | # type: (Any, List[bytes], List[bytes], bool) -> List[str] | |
|
400 | 424 | '''Turns a list of addresses into a list of RFC-2047 compliant headers. |
|
401 | 425 | A single element of input list may contain multiple addresses, but output |
|
402 | 426 | always has one address per item''' |
@@ -416,6 +440,7 b' def addrlistencode(ui, addrs, charsets=N' | |||
|
416 | 440 | |
|
417 | 441 | |
|
418 | 442 | def mimeencode(ui, s, charsets=None, display=False): |
|
443 | # type: (Any, bytes, List[bytes], bool) -> email.message.Message | |
|
419 | 444 | '''creates mime text object, encodes it if needed, and sets |
|
420 | 445 | charset and transfer-encoding accordingly.''' |
|
421 | 446 | cs = b'us-ascii' |
@@ -429,6 +454,7 b' if pycompat.ispy3:' | |||
|
429 | 454 | Generator = email.generator.BytesGenerator |
|
430 | 455 | |
|
431 | 456 | def parse(fp): |
|
457 | # type: (Any) -> email.message.Message | |
|
432 | 458 | ep = email.parser.Parser() |
|
433 | 459 | # disable the "universal newlines" mode, which isn't binary safe. |
|
434 | 460 | # I have no idea if ascii/surrogateescape is correct, but that's |
@@ -442,6 +468,7 b' if pycompat.ispy3:' | |||
|
442 | 468 | fp.detach() |
|
443 | 469 | |
|
444 | 470 | def parsebytes(data): |
|
471 | # type: (bytes) -> email.message.Message | |
|
445 | 472 | ep = email.parser.BytesParser() |
|
446 | 473 | return ep.parsebytes(data) |
|
447 | 474 | |
@@ -451,15 +478,18 b' else:' | |||
|
451 | 478 | Generator = email.generator.Generator |
|
452 | 479 | |
|
453 | 480 | def parse(fp): |
|
481 | # type: (Any) -> email.message.Message | |
|
454 | 482 | ep = email.parser.Parser() |
|
455 | 483 | return ep.parse(fp) |
|
456 | 484 | |
|
457 | 485 | def parsebytes(data): |
|
486 | # type: (str) -> email.message.Message | |
|
458 | 487 | ep = email.parser.Parser() |
|
459 | 488 | return ep.parsestr(data) |
|
460 | 489 | |
|
461 | 490 | |
|
462 | 491 | def headdecode(s): |
|
492 | # type: (Union[email.header.Header, bytes]) -> bytes | |
|
463 | 493 | '''Decodes RFC-2047 header''' |
|
464 | 494 | uparts = [] |
|
465 | 495 | for part, charset in email.header.decode_header(s): |
General Comments 0
You need to be logged in to leave comments.
Login now