[Zope] Mime tag not flexible enough

Jay, Dylan djay@lucent.com
Thu, 7 Oct 1999 17:14:35 +1000


I needed the ability to be able to conditionally include attachments to a
mail message. Unfortunately the mime tag syntax made this impossible. I've
updated it by splitting the tag into two tags. 

I've submitted it to the bug collector. Anyone have any constructive
criticism?

Here is an example of my syntax.

<dtml-sendmail mailhost=MailHost>
To: blah@lucent.com
From: <dtml-var AUTHENTICATED_USER>@lucent.com
Subject: Bug submission: <dtml-var description> 
<dtml-mime>
<dtml-boundary type="'text/plain'" encode="'7bit'">
<dtml-var mailContent>
</dtml-boundary>
<dtml-with event_log><dtml-if filename><dtml-boundary name=filename
description="'Event Log'"><dtml-var
read></dtml-boundary></dtml-if></dtml-with>
<dtml-with comm_mon><dtml-if filename><dtml-boundary name=filename
description="'Communication Monitor'"><dtml-var
read></dtml-boundary></dtml-if></dtml-with>
<dtml-with archive><dtml-if filename><dtml-boundary name=filename
description="'Archive'"><dtml-var
read></dtml-boundary></dtml-if></dtml-with>
</dtml-mime>
</dtml-sendmail>


Here is the code from my revise MIMETag.py file

from DocumentTemplate.DT_Util import *
from DocumentTemplate.DT_String import String
from DocumentTemplate.DT_Let import Let, parse_let_params
from MimeWriter import MimeWriter
from cStringIO import StringIO
import string, mimetools

MIMEError = "MIME Tag Error"

class MIMETag:
    '''
    '''

    name='mime'
    blockContinuations=()
    encode=None

    def __init__(self, blocks):

        tname, args, section = blocks[0]
        args = parse_params(args, name=None)

        has_key=args.has_key

        self.section = section.blocks


    def render(self, md):
        contents=[]
        mw = MimeWriter(StringIO())
        outer = mw.startmultipartbody('mixed')
        d={}; md._push(d)
        try:
            d['mime-writer']= mw
            outer.write(render_blocks(self.section, md))                  
            mw.lastpart()
            outer.seek(0)
            return outer.read()
        finally: md._pop(1)


    __call__=render



class BOUNDARYTag:
    '''
    '''

    name='boundary'
    blockContinuations=()
    encode=None

    def __init__(self, blocks):
        tname, args, section = blocks[0]
        self.__name__ = args
        self.section = section.blocks
        self.args = args = parse_let_params(args)

        for i in range(len(args)):
            name,expr = args[i]
            if expr[:1]=='"' and expr[-1:]=='"' and len(expr) > 1:
				# expr shorthand
                expr=expr[1:-1]
                try: args[i] = name, (1,Eval(expr, expr_globals).eval)
                except SyntaxError, v:
                    m,(huh,l,c,src) = v
                    raise ParseError, (
                        '<strong>Expression (Python) Syntax error</strong>:'
                        '\n<pre>\n%s\n</pre>\n' % v[0],
                        'boundary')


    def render(self, md):
        contents=[]
        try: mw = md['mime-writer'].nextpart()
        except: mw = MimeWrite()
         
        args = {}
        # evaluate any expressions
        for name,expr in self.args:
           try: isExpr, expr = expr
           except: isExpr = 0 
           if not isExpr: args[name]=md[expr]
           else: args[name]=expr(md)

        has_key=args.has_key

        if has_key('type'): 
           type = args['type']
        else:
           type = 'application/octet-stream'

        if has_key('disposition'):
           disposition = args['disposition']
        else:
           disposition = ''

        if has_key('encode'):
           encode = args['encode']
        else:
           encode = 'base64'

        if has_key('name'):
           name = args['name']
        else:
           name = ''
           
        if encode not in \
        ('base64', 'quoted-printable', 'uuencode', 'x-uuencode',
         'uue', 'x-uue', '7bit'):
           raise MIMEError, (
           'An unsupported encoding was specified in tag')
        
        b = self.section

        if disposition:
           mw.addheader('Content-Disposition', disposition)

        if args.has_key('description'):
           mw.addheader('Content-Description', args['description'])

        mw.addheader('Content-Transfer-Encoding', encode)
        if name:
           plist = [('name', name)]
        else:
           plist = []

        mfile = mw.startbody(type, plist, 1)

        output = StringIO()
        if encode == '7bit':
           mfile.write(render_blocks(b, md))
        else:
           mimetools.encode(StringIO(render_blocks(b, md)), 
                            output, encode)
           output.seek(0)
           mfile.write(output.read())

        return mfile.read()


    __call__=render




String.commands['mime'] = MIMETag
String.commands['boundary'] = BOUNDARYTag