trytond-electronic_mail_wizard /

Full commit
#This file is part electronic_mail_wizard module for Tryton.
#The COPYRIGHT file at the top level of this repository contains 
#the full copyright notices and license terms.

    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO
import mimetypes
import base64
import re
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.utils import formatdate

from trytond.model import ModelView, ModelSQL, fields
from trytond.wizard import Wizard, StateTransition, StateView, Button
from trytond.transaction import Transaction
from trytond.pool import Pool

__all__ = ['TemplateEmailStart', 'TemplateEmailResult',
    'GenerateTemplateEmail', 'ExampleGenerateTemplateEmail']

class TemplateEmailStart(ModelView):
    'Template Email Start'
    __name__ = 'electronic.mail.wizard.templateemail.start'

    from_ = fields.Char('From', readonly=True)
    sender = fields.Char('Sender', required=True)
    to = fields.Char('To', required=True)
    cc = fields.Char('CC')
    bcc = fields.Char('BCC')
    subject = fields.Char('Subject', required=True)
    plain = fields.Text('Plain Text Body', required=True)
    total = fields.Integer('Total', readonly=True,
        help='Total emails to send')
    template = fields.Many2One("electronic.mail.template", 'Template')
    model = fields.Many2One(
        'ir.model', 'Model', required=True, select="1")

class TemplateEmailResult(ModelView):
    'Template Email Result'
    __name__ = 'electronic.mail.wizard.templateemail.result'

    name = fields.Char('Name', help='Name of Header Field')

class GenerateTemplateEmail(Wizard):
    "Generate Email from template"
    __name__ = "electronic_mail_wizard.templateemail"

    start = StateView('electronic.mail.wizard.templateemail.start',
        'electronic_mail_wizard.templateemail_start', [
            Button('Cancel', 'end', 'tryton-cancel'),
            Button('Send', 'send', 'tryton-ok', default=True),
    send = StateTransition()

    def __setup__(cls):
        super(GenerateTemplateEmail, cls).__setup__()
            'template_missing': 'You can select a template in this wizard.',

    def render(self, template, record, values):
        '''Renders the template and returns as email object
        :param template: Browse Record of the template
        :param record: Browse Record of the template
        :param values: Dicctionary values
        :return: 'email.message.Message' instance
        Template = Pool().get('electronic.mail.template')

        message = MIMEMultipart('alternative')
        message['date'] = formatdate(localtime=1)

        language = Transaction().context.get('language', 'en_US')
        if template.language:
            language = Template.eval(template, template.language, record)

        with Transaction().set_context(language = language):
            template = Template.browse(

            message['from_'] = Template.eval(template, values['from_'], record)
            message['to'] = Template.eval(template, values['to'], record)
            message['cc'] = Template.eval(template, values['cc'], record)
            message['bcc'] = Template.eval(template, values['bcc'], record)
            message['subject'] = Template.eval(template, values['subject'], record)

            # Attach reports
            if template.reports:
                reports = Template.render_reports(
                    template, record
                for report in reports:
                    ext, data, filename, file_name = report[0:5]
                    if file_name:
                        filename = Template.eval(template, file_name, record)
                    filename = ext and '%s.%s' % (filename, ext) or filename
                    content_type, _ = mimetypes.guess_type(filename)
                    maintype, subtype = (
                        content_type or 'application/octet-stream'
                        ).split('/', 1)

                    attachment = MIMEBase(maintype, subtype)

                        'Content-Disposition', 'attachment', filename=filename)
                        'Content-Transfer-Encoding', 'base64')

            # HTML & Text Alternate parts
            plain = Template.eval(template, values['plain'], record)
            if template.signature:
                User = Pool().get('res.user')
                user = User.browse(Transaction().user)
                if user.signature:
                    signature = user.signature.encode("ASCII", 'ignore')
                    plain = '%s\n--\n%s' % (plain, signature)
            html = re.sub('\n', '<br/>', plain) #html body email as same as plain but \n replaced by <br/>
            message.attach(MIMEText(plain, 'plain'))
            message.attach(MIMEText(html, 'html'))

            # Add headers
            for header in template.headers:
                    unicode(self.eval(template, header.value, record))
        return message

    def render_fields(self, name):
        '''Get the fields before render and return a dicc
        :param name: Str ir.action.wizard
        :return: dicc
        default = {}

        Wizard = Pool().get('ir.action.wizard')
        Template = Pool().get('electronic.mail.template')
        active_ids = Transaction().context.get('active_ids')

        wizards =['wiz_name','=',name])
        if not len(wizards) > 0:
            return default
        wizard = Wizard.browse(wizards[0])
        if not wizard.template:
        template = wizard.template[0]
        total = len(active_ids)

        default['from_'] = template.from_
        default['total'] = total
        default['template'] =
        default['model'] =
        if total > 1: #show fields with tags
            default['to'] =
            default['cc'] =
            default['bcc'] = template.bcc
            default['subject'] = template.subject
            default['plain'] = template.plain
        else: #show fields with rendered tags
            record = Pool().get(template.model.model).browse(active_ids[0]) 
            default['to'] = Template.eval(template,, record)
            default['cc'] = Template.eval(template,, record)
            default['bcc'] = Template.eval(template, template.bcc, record)
            default['subject'] = Template.eval(template, template.subject, record)
            default['plain'] = Template.eval(template, template.plain, record)
        return default

    def render_and_send(self):
        Email = Pool().get('electronic.mail')
        Template = Pool().get('electronic.mail.template')

        template = self.start.template
        model = self.start.model

        for active_id in Transaction().context.get('active_ids'):
            record = Pool().get(model.model).browse(active_id)
            values = {}
            values['from_'] = self.start.from_
            values['to'] =
            values['cc'] =
            values['bcc'] = self.start.bcc
            values['subject'] = self.start.subject
            values['plain'] = self.start.plain
            email_message = self.render(template, record, values)
            email_id = Email.create_from_email(
            Template.send_email(email_id, template)

            Pool().get('electronic.mail.template').add_event(template, record, email_id, email_message) #add event
        return True

class ExampleGenerateTemplateEmail(GenerateTemplateEmail):
    "Example Wizard to Generate Email from template"
    __name__ = "electronic_mail_wizard.example"

    def default_start(self, fields):
        default = self.render_fields(self._name)
        return default

    def transition_send(self):
        return 'end'