NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

generator.py (6604B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\email\generator.py
      2 __all__ = ['Generator', 'DecodedGenerator']
      3 import re
      4 import sys
      5 import time
      6 import random
      7 import warnings
      8 from cStringIO import StringIO
      9 from email.header import Header
     10 UNDERSCORE = '_'
     11 NL = '\n'
     12 fcre = re.compile('^From ', re.MULTILINE)
     13 
     14 def _is8bitstring(s):
     15     if isinstance(s, str):
     16         try:
     17             unicode(s, 'us-ascii')
     18         except UnicodeError:
     19             return True
     20 
     21     return False
     22 
     23 
     24 class Generator():
     25 
     26     def __init__(self, outfp, mangle_from_ = True, maxheaderlen = 78):
     27         self._fp = outfp
     28         self._mangle_from_ = mangle_from_
     29         self._maxheaderlen = maxheaderlen
     30 
     31     def write(self, s):
     32         self._fp.write(s)
     33 
     34     def flatten(self, msg, unixfrom = False):
     35         if unixfrom:
     36             ufrom = msg.get_unixfrom()
     37             if not ufrom:
     38                 ufrom = 'From nobody ' + time.ctime(time.time())
     39             print >> self._fp, ufrom
     40         self._write(msg)
     41 
     42     def clone(self, fp):
     43         return self.__class__(fp, self._mangle_from_, self._maxheaderlen)
     44 
     45     def _write(self, msg):
     46         oldfp = self._fp
     47         try:
     48             self._fp = sfp = StringIO()
     49             self._dispatch(msg)
     50         finally:
     51             self._fp = oldfp
     52 
     53         meth = getattr(msg, '_write_headers', None)
     54         if meth is None:
     55             self._write_headers(msg)
     56         else:
     57             meth(self)
     58         self._fp.write(sfp.getvalue())
     59 
     60     def _dispatch(self, msg):
     61         main = msg.get_content_maintype()
     62         sub = msg.get_content_subtype()
     63         specific = UNDERSCORE.join((main, sub)).replace('-', '_')
     64         meth = getattr(self, '_handle_' + specific, None)
     65         if meth is None:
     66             generic = main.replace('-', '_')
     67             meth = getattr(self, '_handle_' + generic, None)
     68             if meth is None:
     69                 meth = self._writeBody
     70         meth(msg)
     71 
     72     def _write_headers(self, msg):
     73         for h, v in msg.items():
     74             print >> self._fp, '%s:' % h,
     75             if self._maxheaderlen == 0:
     76                 print >> self._fp, v
     77             elif isinstance(v, Header):
     78                 print >> self._fp, v.encode()
     79             elif _is8bitstring(v):
     80                 print >> self._fp, v
     81             else:
     82                 print >> self._fp, Header(v, maxlinelen=self._maxheaderlen, header_name=h).encode()
     83 
     84         print >> self._fp
     85 
     86     def _handle_text(self, msg):
     87         payload = msg.get_payload()
     88         if payload is None:
     89             return
     90         if not isinstance(payload, basestring):
     91             raise TypeError('string payload expected: %s' % type(payload))
     92         if self._mangle_from_:
     93             payload = fcre.sub('>From ', payload)
     94         self._fp.write(payload)
     95 
     96     _writeBody = _handle_text
     97 
     98     def _handle_multipart(self, msg):
     99         msgtexts = []
    100         subparts = msg.get_payload()
    101         if subparts is None:
    102             subparts = []
    103         else:
    104             if isinstance(subparts, basestring):
    105                 self._fp.write(subparts)
    106                 return
    107             if not isinstance(subparts, list):
    108                 subparts = [subparts]
    109         for part in subparts:
    110             s = StringIO()
    111             g = self.clone(s)
    112             g.flatten(part, unixfrom=False)
    113             msgtexts.append(s.getvalue())
    114 
    115         alltext = NL.join(msgtexts)
    116         boundary = msg.get_boundary(failobj=_make_boundary(alltext))
    117         if msg.get_boundary() != boundary:
    118             msg.set_boundary(boundary)
    119         if msg.preamble is not None:
    120             print >> self._fp, msg.preamble
    121         print >> self._fp, '--' + boundary
    122         if msgtexts:
    123             self._fp.write(msgtexts.pop(0))
    124         for body_part in msgtexts:
    125             print >> self._fp, '\n--' + boundary
    126             self._fp.write(body_part)
    127 
    128         self._fp.write('\n--' + boundary + '--')
    129         if msg.epilogue is not None:
    130             print >> self._fp
    131             self._fp.write(msg.epilogue)
    132 
    133     def _handle_multipart_signed(self, msg):
    134         old_maxheaderlen = self._maxheaderlen
    135         try:
    136             self._maxheaderlen = 0
    137             self._handle_multipart(msg)
    138         finally:
    139             self._maxheaderlen = old_maxheaderlen
    140 
    141     def _handle_message_delivery_status(self, msg):
    142         blocks = []
    143         for part in msg.get_payload():
    144             s = StringIO()
    145             g = self.clone(s)
    146             g.flatten(part, unixfrom=False)
    147             text = s.getvalue()
    148             lines = text.split('\n')
    149             if lines and lines[-1] == '':
    150                 blocks.append(NL.join(lines[:-1]))
    151             else:
    152                 blocks.append(text)
    153 
    154         self._fp.write(NL.join(blocks))
    155 
    156     def _handle_message(self, msg):
    157         s = StringIO()
    158         g = self.clone(s)
    159         payload = msg.get_payload()
    160         if isinstance(payload, list):
    161             g.flatten(msg.get_payload(0), unixfrom=False)
    162             payload = s.getvalue()
    163         self._fp.write(payload)
    164 
    165 
    166 _FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]'
    167 
    168 class DecodedGenerator(Generator):
    169 
    170     def __init__(self, outfp, mangle_from_ = True, maxheaderlen = 78, fmt = None):
    171         Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
    172         if fmt is None:
    173             self._fmt = _FMT
    174         else:
    175             self._fmt = fmt
    176 
    177     def _dispatch(self, msg):
    178         for part in msg.walk():
    179             maintype = part.get_content_maintype()
    180             if maintype == 'text':
    181                 print >> self, part.get_payload(decode=True)
    182             elif maintype == 'multipart':
    183                 pass
    184             else:
    185                 print >> self, self._fmt % {'type': part.get_content_type(),
    186                  'maintype': part.get_content_maintype(),
    187                  'subtype': part.get_content_subtype(),
    188                  'filename': part.get_filename('[no filename]'),
    189                  'description': part.get('Content-Description', '[no description]'),
    190                  'encoding': part.get('Content-Transfer-Encoding', '[no encoding]')}
    191 
    192 
    193 _width = len(repr(sys.maxint - 1))
    194 _fmt = '%%0%dd' % _width
    195 
    196 def _make_boundary(text = None):
    197     token = random.randrange(sys.maxint)
    198     boundary = '===============' + _fmt % token + '=='
    199     if text is None:
    200         return boundary
    201     b = boundary
    202     counter = 0
    203     while True:
    204         cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
    205         if not cre.search(text):
    206             break
    207         b = boundary + '.' + str(counter)
    208         counter += 1
    209 
    210     return b