Back to index

python3.2  3.2.2
Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes
email.generator.Generator Class Reference
Inheritance diagram for email.generator.Generator:
Inheritance graph
[legend]
Collaboration diagram for email.generator.Generator:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def __init__
def write
def flatten
def clone

Private Member Functions

def _new_buffer
def _encode
def _write
def _dispatch
def _write_headers
def _handle_text
def _handle_multipart
def _handle_multipart_signed
def _handle_message_delivery_status
def _handle_message
def _make_boundary
def _compile_re

Private Attributes

 _fp
 _mangle_from_
 _maxheaderlen
 _NL
 _encoded_NL
 _EMPTY
 _encoded_EMTPY

Static Private Attributes

string _encoded_EMPTY = ''
 _writeBody = _handle_text

Detailed Description

Generates output from a Message object tree.

This basic generator writes the message to the given file object as plain
text.

Definition at line 26 of file generator.py.


Constructor & Destructor Documentation

def email.generator.Generator.__init__ (   self,
  outfp,
  mangle_from_ = True,
  maxheaderlen = 78 
)
Create the generator for message flattening.

outfp is the output file-like object for writing the message to.  It
must have a write() method.

Optional mangle_from_ is a flag that, when True (the default), escapes
From_ lines in the body of the message by putting a `>' in front of
them.

Optional maxheaderlen specifies the longest length for a non-continued
header.  When a header line is longer (in characters, with tabs
expanded to 8 spaces) than maxheaderlen, the header will split as
defined in the Header class.  Set maxheaderlen to zero to disable
header wrapping.  The default is 78, as recommended (but not required)
by RFC 2822.

Definition at line 36 of file generator.py.

00036 
00037     def __init__(self, outfp, mangle_from_=True, maxheaderlen=78):
00038         """Create the generator for message flattening.
00039 
00040         outfp is the output file-like object for writing the message to.  It
00041         must have a write() method.
00042 
00043         Optional mangle_from_ is a flag that, when True (the default), escapes
00044         From_ lines in the body of the message by putting a `>' in front of
00045         them.
00046 
00047         Optional maxheaderlen specifies the longest length for a non-continued
00048         header.  When a header line is longer (in characters, with tabs
00049         expanded to 8 spaces) than maxheaderlen, the header will split as
00050         defined in the Header class.  Set maxheaderlen to zero to disable
00051         header wrapping.  The default is 78, as recommended (but not required)
00052         by RFC 2822.
00053         """
00054         self._fp = outfp
00055         self._mangle_from_ = mangle_from_
00056         self._maxheaderlen = maxheaderlen

Here is the caller graph for this function:


Member Function Documentation

def email.generator.Generator._compile_re (   cls,
  s,
  flags 
) [private]

Reimplemented in email.generator.BytesGenerator.

Definition at line 330 of file generator.py.

00330 
00331     def _compile_re(cls, s, flags):
00332         return re.compile(s, flags)
00333 


Here is the call graph for this function:

def email.generator.Generator._dispatch (   self,
  msg 
) [private]

Reimplemented in email.generator.DecodedGenerator.

Definition at line 149 of file generator.py.

00149 
00150     def _dispatch(self, msg):
00151         # Get the Content-Type: for the message, then try to dispatch to
00152         # self._handle_<maintype>_<subtype>().  If there's no handler for the
00153         # full MIME type, then dispatch to self._handle_<maintype>().  If
00154         # that's missing too, then dispatch to self._writeBody().
00155         main = msg.get_content_maintype()
00156         sub = msg.get_content_subtype()
00157         specific = UNDERSCORE.join((main, sub)).replace('-', '_')
00158         meth = getattr(self, '_handle_' + specific, None)
00159         if meth is None:
00160             generic = main.replace('-', '_')
00161             meth = getattr(self, '_handle_' + generic, None)
00162             if meth is None:
00163                 meth = self._writeBody
00164         meth(msg)

Here is the call graph for this function:

Here is the caller graph for this function:

def email.generator.Generator._encode (   self,
  s 
) [private]

Reimplemented in email.generator.BytesGenerator.

Definition at line 118 of file generator.py.

00118 
00119     def _encode(self, s):
00120         # BytesGenerator overrides this to encode strings to bytes.
00121         return s

def email.generator.Generator._handle_message (   self,
  msg 
) [private]

Definition at line 288 of file generator.py.

00288 
00289     def _handle_message(self, msg):
00290         s = self._new_buffer()
00291         g = self.clone(s)
00292         # The payload of a message/rfc822 part should be a multipart sequence
00293         # of length 1.  The zeroth element of the list should be the Message
00294         # object for the subpart.  Extract that object, stringify it, and
00295         # write it out.
00296         # Except, it turns out, when it's a string instead, which happens when
00297         # and only when HeaderParser is used on a message of mime type
00298         # message/rfc822.  Such messages are generated by, for example,
00299         # Groupwise when forwarding unadorned messages.  (Issue 7970.)  So
00300         # in that case we just emit the string body.
00301         payload = msg.get_payload()
00302         if isinstance(payload, list):
00303             g.flatten(msg.get_payload(0), unixfrom=False, linesep=self._NL)
00304             payload = s.getvalue()
00305         self._fp.write(payload)

Here is the call graph for this function:

def email.generator.Generator._handle_message_delivery_status (   self,
  msg 
) [private]

Definition at line 267 of file generator.py.

00267 
00268     def _handle_message_delivery_status(self, msg):
00269         # We can't just write the headers directly to self's file object
00270         # because this will leave an extra newline between the last header
00271         # block and the boundary.  Sigh.
00272         blocks = []
00273         for part in msg.get_payload():
00274             s = self._new_buffer()
00275             g = self.clone(s)
00276             g.flatten(part, unixfrom=False, linesep=self._NL)
00277             text = s.getvalue()
00278             lines = text.split(self._encoded_NL)
00279             # Strip off the unnecessary trailing empty line
00280             if lines and lines[-1] == self._encoded_EMPTY:
00281                 blocks.append(self._encoded_NL.join(lines[:-1]))
00282             else:
00283                 blocks.append(text)
00284         # Now join all the blocks with an empty line.  This has the lovely
00285         # effect of separating each block with an empty line, but not adding
00286         # an extra one after the last one.
00287         self._fp.write(self._encoded_NL.join(blocks))

Here is the call graph for this function:

def email.generator.Generator._handle_multipart (   self,
  msg 
) [private]

Definition at line 206 of file generator.py.

00206 
00207     def _handle_multipart(self, msg):
00208         # The trick here is to write out each part separately, merge them all
00209         # together, and then make sure that the boundary we've chosen isn't
00210         # present in the payload.
00211         msgtexts = []
00212         subparts = msg.get_payload()
00213         if subparts is None:
00214             subparts = []
00215         elif isinstance(subparts, str):
00216             # e.g. a non-strict parse of a message with no starting boundary.
00217             self.write(subparts)
00218             return
00219         elif not isinstance(subparts, list):
00220             # Scalar payload
00221             subparts = [subparts]
00222         for part in subparts:
00223             s = self._new_buffer()
00224             g = self.clone(s)
00225             g.flatten(part, unixfrom=False, linesep=self._NL)
00226             msgtexts.append(s.getvalue())
00227         # BAW: What about boundaries that are wrapped in double-quotes?
00228         boundary = msg.get_boundary()
00229         if not boundary:
00230             # Create a boundary that doesn't appear in any of the
00231             # message texts.
00232             alltext = self._encoded_NL.join(msgtexts)
00233             boundary = self._make_boundary(alltext)
00234             msg.set_boundary(boundary)
00235         # If there's a preamble, write it out, with a trailing CRLF
00236         if msg.preamble is not None:
00237             self.write(msg.preamble + self._NL)
00238         # dash-boundary transport-padding CRLF
00239         self.write('--' + boundary + self._NL)
00240         # body-part
00241         if msgtexts:
00242             self._fp.write(msgtexts.pop(0))
00243         # *encapsulation
00244         # --> delimiter transport-padding
00245         # --> CRLF body-part
00246         for body_part in msgtexts:
00247             # delimiter transport-padding CRLF
00248             self.write(self._NL + '--' + boundary + self._NL)
00249             # body-part
00250             self._fp.write(body_part)
00251         # close-delimiter transport-padding
00252         self.write(self._NL + '--' + boundary + '--')
00253         if msg.epilogue is not None:
00254             self.write(self._NL)
00255             self.write(msg.epilogue)

Here is the call graph for this function:

Here is the caller graph for this function:

def email.generator.Generator._handle_multipart_signed (   self,
  msg 
) [private]

Definition at line 256 of file generator.py.

00256 
00257     def _handle_multipart_signed(self, msg):
00258         # The contents of signed parts has to stay unmodified in order to keep
00259         # the signature intact per RFC1847 2.1, so we disable header wrapping.
00260         # RDM: This isn't enough to completely preserve the part, but it helps.
00261         old_maxheaderlen = self._maxheaderlen
00262         try:
00263             self._maxheaderlen = 0
00264             self._handle_multipart(msg)
00265         finally:
00266             self._maxheaderlen = old_maxheaderlen

Here is the call graph for this function:

def email.generator.Generator._handle_text (   self,
  msg 
) [private]

Reimplemented in email.generator.BytesGenerator.

Definition at line 187 of file generator.py.

00187 
00188     def _handle_text(self, msg):
00189         payload = msg.get_payload()
00190         if payload is None:
00191             return
00192         if not isinstance(payload, str):
00193             raise TypeError('string payload expected: %s' % type(payload))
00194         if _has_surrogates(msg._payload):
00195             charset = msg.get_param('charset')
00196             if charset is not None:
00197                 del msg['content-transfer-encoding']
00198                 msg.set_payload(payload, charset)
00199                 payload = msg.get_payload()
00200         if self._mangle_from_:
00201             payload = fcre.sub('>From ', payload)
00202         self.write(payload)

Here is the call graph for this function:

def email.generator.Generator._make_boundary (   cls,
  text = None 
) [private]

Definition at line 312 of file generator.py.

00312 
00313     def _make_boundary(cls, text=None):
00314         # Craft a random boundary.  If text is given, ensure that the chosen
00315         # boundary doesn't appear in the text.
00316         token = random.randrange(sys.maxsize)
00317         boundary = ('=' * 15) + (_fmt % token) + '=='
00318         if text is None:
00319             return boundary
00320         b = boundary
00321         counter = 0
00322         while True:
00323             cre = cls._compile_re('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
00324             if not cre.search(text):
00325                 break
00326             b = boundary + '.' + str(counter)
00327             counter += 1
00328         return b

Here is the call graph for this function:

Here is the caller graph for this function:

def email.generator.Generator._new_buffer (   self) [private]

Reimplemented in email.generator.BytesGenerator.

Definition at line 114 of file generator.py.

00114 
00115     def _new_buffer(self):
00116         # BytesGenerator overrides this to return BytesIO.
00117         return StringIO()

Here is the caller graph for this function:

def email.generator.Generator._write (   self,
  msg 
) [private]

Definition at line 122 of file generator.py.

00122 
00123     def _write(self, msg):
00124         # We can't write the headers yet because of the following scenario:
00125         # say a multipart message includes the boundary string somewhere in
00126         # its body.  We'd have to calculate the new boundary /before/ we write
00127         # the headers so that we can write the correct Content-Type:
00128         # parameter.
00129         #
00130         # The way we do this, so as to make the _handle_*() methods simpler,
00131         # is to cache any subpart writes into a buffer.  The we write the
00132         # headers and the buffer contents.  That way, subpart handlers can
00133         # Do The Right Thing, and can still modify the Content-Type: header if
00134         # necessary.
00135         oldfp = self._fp
00136         try:
00137             self._fp = sfp = self._new_buffer()
00138             self._dispatch(msg)
00139         finally:
00140             self._fp = oldfp
00141         # Write the headers.  First we see if the message object wants to
00142         # handle that itself.  If not, we'll do it generically.
00143         meth = getattr(msg, '_write_headers', None)
00144         if meth is None:
00145             self._write_headers(msg)
00146         else:
00147             meth(self)
00148         self._fp.write(sfp.getvalue())

Here is the call graph for this function:

Here is the caller graph for this function:

def email.generator.Generator._write_headers (   self,
  msg 
) [private]

Reimplemented in email.generator.BytesGenerator.

Definition at line 169 of file generator.py.

00169 
00170     def _write_headers(self, msg):
00171         for h, v in msg.items():
00172             self.write('%s: ' % h)
00173             if isinstance(v, Header):
00174                 self.write(v.encode(
00175                     maxlinelen=self._maxheaderlen, linesep=self._NL)+self._NL)
00176             else:
00177                 # Header's got lots of smarts, so use it.
00178                 header = Header(v, maxlinelen=self._maxheaderlen,
00179                                 header_name=h)
00180                 self.write(header.encode(linesep=self._NL)+self._NL)
00181         # A blank line always separates headers from body
00182         self.write(self._NL)

Here is the call graph for this function:

Here is the caller graph for this function:

def email.generator.Generator.clone (   self,
  fp 
)
Clone this generator with the exact same options.

Definition at line 93 of file generator.py.

00093 
00094     def clone(self, fp):
00095         """Clone this generator with the exact same options."""
00096         return self.__class__(fp, self._mangle_from_, self._maxheaderlen)

Here is the caller graph for this function:

def email.generator.Generator.flatten (   self,
  msg,
  unixfrom = False,
  linesep = '\n' 
)

Definition at line 61 of file generator.py.

00061 
00062     def flatten(self, msg, unixfrom=False, linesep='\n'):
00063         r"""Print the message object tree rooted at msg to the output file
00064         specified when the Generator instance was created.
00065 
00066         unixfrom is a flag that forces the printing of a Unix From_ delimiter
00067         before the first object in the message tree.  If the original message
00068         has no From_ delimiter, a `standard' one is crafted.  By default, this
00069         is False to inhibit the printing of any From_ delimiter.
00070 
00071         Note that for subobjects, no From_ line is printed.
00072 
00073         linesep specifies the characters used to indicate a new line in
00074         the output.  The default value is the most useful for typical
00075         Python applications, but it can be set to \r\n to produce RFC-compliant
00076         line separators when needed.
00077 
00078         """
00079         # We use the _XXX constants for operating on data that comes directly
00080         # from the msg, and _encoded_XXX constants for operating on data that
00081         # has already been converted (to bytes in the BytesGenerator) and
00082         # inserted into a temporary buffer.
00083         self._NL = linesep
00084         self._encoded_NL = self._encode(linesep)
00085         self._EMPTY = ''
00086         self._encoded_EMTPY = self._encode('')
00087         if unixfrom:
00088             ufrom = msg.get_unixfrom()
00089             if not ufrom:
00090                 ufrom = 'From nobody ' + time.ctime(time.time())
00091             self.write(ufrom + self._NL)
00092         self._write(msg)

def email.generator.Generator.write (   self,
  s 
)

Reimplemented in email.generator.BytesGenerator.

Definition at line 57 of file generator.py.

00057 
00058     def write(self, s):
00059         # Just delegate to the file object
00060         self._fp.write(s)


Member Data Documentation

Definition at line 84 of file generator.py.

Reimplemented in email.generator.BytesGenerator.

Definition at line 112 of file generator.py.

Definition at line 85 of file generator.py.

Definition at line 83 of file generator.py.

Definition at line 53 of file generator.py.

Definition at line 54 of file generator.py.

Definition at line 55 of file generator.py.

Definition at line 82 of file generator.py.

Definition at line 204 of file generator.py.


The documentation for this class was generated from the following file: