clone(): A new method for creating a clone of this generator (for
recursive generation). _dispatch(): If the message object doesn't have a Content-Type: header, check its default type instead of assuming it's text/plain. This makes for correct generation of message/rfc822 containers. _handle_multipart(): We can get rid of the isdigest kludge. Just print the message as normal and everything will work out correctly. _handle_mulitpart_digest(): We don't need this anymore either.
This commit is contained in:
parent
ed53bdb02d
commit
93c40f0c3a
|
@ -83,6 +83,10 @@ class Generator:
|
||||||
# For backwards compatibility, but this is slower
|
# For backwards compatibility, but this is slower
|
||||||
__call__ = flatten
|
__call__ = flatten
|
||||||
|
|
||||||
|
def clone(self, fp):
|
||||||
|
"""Clone this generator with the exact same options."""
|
||||||
|
return self.__class__(fp, self._mangle_from_, self.__maxheaderlen)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Protected interface - undocumented ;/
|
# Protected interface - undocumented ;/
|
||||||
#
|
#
|
||||||
|
@ -121,18 +125,20 @@ class Generator:
|
||||||
# missing too, then dispatch to self._writeBody().
|
# missing too, then dispatch to self._writeBody().
|
||||||
ctype = msg.get_type()
|
ctype = msg.get_type()
|
||||||
if ctype is None:
|
if ctype is None:
|
||||||
# No Content-Type: header so try the default handler
|
# No Content-Type: header so use the default type, which must be
|
||||||
self._writeBody(msg)
|
# either text/plain or message/rfc822.
|
||||||
else:
|
ctype = msg.get_default_type()
|
||||||
# We do have a Content-Type: header.
|
assert ctype in ('text/plain', 'message/rfc822')
|
||||||
specific = UNDERSCORE.join(ctype.split('/')).replace('-', '_')
|
# We do have a Content-Type: header.
|
||||||
meth = getattr(self, '_handle_' + specific, None)
|
main, sub = ctype.split('/')
|
||||||
|
specific = UNDERSCORE.join((main, sub)).replace('-', '_')
|
||||||
|
meth = getattr(self, '_handle_' + specific, None)
|
||||||
|
if meth is None:
|
||||||
|
generic = main.replace('-', '_')
|
||||||
|
meth = getattr(self, '_handle_' + generic, None)
|
||||||
if meth is None:
|
if meth is None:
|
||||||
generic = msg.get_main_type().replace('-', '_')
|
meth = self._writeBody
|
||||||
meth = getattr(self, '_handle_' + generic, None)
|
meth(msg)
|
||||||
if meth is None:
|
|
||||||
meth = self._writeBody
|
|
||||||
meth(msg)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Default handlers
|
# Default handlers
|
||||||
|
@ -196,14 +202,14 @@ class Generator:
|
||||||
# Default body handler
|
# Default body handler
|
||||||
_writeBody = _handle_text
|
_writeBody = _handle_text
|
||||||
|
|
||||||
def _handle_multipart(self, msg, isdigest=0):
|
def _handle_multipart(self, msg):
|
||||||
# The trick here is to write out each part separately, merge them all
|
# The trick here is to write out each part separately, merge them all
|
||||||
# together, and then make sure that the boundary we've chosen isn't
|
# together, and then make sure that the boundary we've chosen isn't
|
||||||
# present in the payload.
|
# present in the payload.
|
||||||
msgtexts = []
|
msgtexts = []
|
||||||
subparts = msg.get_payload()
|
subparts = msg.get_payload()
|
||||||
if subparts is None:
|
if subparts is None:
|
||||||
# Nothing has every been attached
|
# Nothing has ever been attached
|
||||||
boundary = msg.get_boundary(failobj=_make_boundary())
|
boundary = msg.get_boundary(failobj=_make_boundary())
|
||||||
print >> self._fp, '--' + boundary
|
print >> self._fp, '--' + boundary
|
||||||
print >> self._fp, '\n'
|
print >> self._fp, '\n'
|
||||||
|
@ -214,7 +220,7 @@ class Generator:
|
||||||
subparts = [subparts]
|
subparts = [subparts]
|
||||||
for part in subparts:
|
for part in subparts:
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
g = self.__class__(s, self._mangle_from_, self.__maxheaderlen)
|
g = self.clone(s)
|
||||||
g.flatten(part, unixfrom=0)
|
g.flatten(part, unixfrom=0)
|
||||||
msgtexts.append(s.getvalue())
|
msgtexts.append(s.getvalue())
|
||||||
# Now make sure the boundary we've selected doesn't appear in any of
|
# Now make sure the boundary we've selected doesn't appear in any of
|
||||||
|
@ -236,14 +242,8 @@ class Generator:
|
||||||
# First boundary is a bit different; it doesn't have a leading extra
|
# First boundary is a bit different; it doesn't have a leading extra
|
||||||
# newline.
|
# newline.
|
||||||
print >> self._fp, '--' + boundary
|
print >> self._fp, '--' + boundary
|
||||||
if isdigest:
|
|
||||||
print >> self._fp
|
|
||||||
# Join and write the individual parts
|
# Join and write the individual parts
|
||||||
joiner = '\n--' + boundary + '\n'
|
joiner = '\n--' + boundary + '\n'
|
||||||
if isdigest:
|
|
||||||
# multipart/digest types effectively add an extra newline between
|
|
||||||
# the boundary and the body part.
|
|
||||||
joiner += '\n'
|
|
||||||
self._fp.write(joiner.join(msgtexts))
|
self._fp.write(joiner.join(msgtexts))
|
||||||
print >> self._fp, '\n--' + boundary + '--',
|
print >> self._fp, '\n--' + boundary + '--',
|
||||||
# Write out any epilogue
|
# Write out any epilogue
|
||||||
|
@ -252,9 +252,6 @@ class Generator:
|
||||||
print >> self._fp
|
print >> self._fp
|
||||||
self._fp.write(msg.epilogue)
|
self._fp.write(msg.epilogue)
|
||||||
|
|
||||||
def _handle_multipart_digest(self, msg):
|
|
||||||
self._handle_multipart(msg, isdigest=1)
|
|
||||||
|
|
||||||
def _handle_message_delivery_status(self, msg):
|
def _handle_message_delivery_status(self, msg):
|
||||||
# We can't just write the headers directly to self's file object
|
# We can't just write the headers directly to self's file object
|
||||||
# because this will leave an extra newline between the last header
|
# because this will leave an extra newline between the last header
|
||||||
|
@ -262,7 +259,7 @@ class Generator:
|
||||||
blocks = []
|
blocks = []
|
||||||
for part in msg.get_payload():
|
for part in msg.get_payload():
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
g = self.__class__(s, self._mangle_from_, self.__maxheaderlen)
|
g = self.clone(s)
|
||||||
g.flatten(part, unixfrom=0)
|
g.flatten(part, unixfrom=0)
|
||||||
text = s.getvalue()
|
text = s.getvalue()
|
||||||
lines = text.split('\n')
|
lines = text.split('\n')
|
||||||
|
@ -278,11 +275,11 @@ class Generator:
|
||||||
|
|
||||||
def _handle_message(self, msg):
|
def _handle_message(self, msg):
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
g = self.__class__(s, self._mangle_from_, self.__maxheaderlen)
|
g = self.clone(s)
|
||||||
# The payload of a message/rfc822 part should be a multipart sequence
|
# The payload of a message/rfc822 part should be a multipart sequence
|
||||||
# of length 1. The zeroth element of the list should be the Message
|
# of length 1. The zeroth element of the list should be the Message
|
||||||
# object for the subpart.Extract that object, stringify it, and write
|
# object for the subpart. Extract that object, stringify it, and
|
||||||
# that out.
|
# write it out.
|
||||||
g.flatten(msg.get_payload(0), unixfrom=0)
|
g.flatten(msg.get_payload(0), unixfrom=0)
|
||||||
self._fp.write(s.getvalue())
|
self._fp.write(s.getvalue())
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue