trytond-electronic_mail_wiz.../electronic_mail_wizard.py

317 lines
12 KiB
Python
Raw Normal View History

2014-11-07 14:23:04 +01:00
# 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.
2012-09-17 12:40:18 +02:00
import mimetypes
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
2014-09-04 11:57:02 +02:00
from email.utils import formatdate, make_msgid
2013-11-27 14:20:53 +01:00
from email import Encoders
2013-12-09 12:50:02 +01:00
from email.header import Header
2012-09-17 12:40:18 +02:00
2013-04-26 13:04:35 +02:00
from trytond.model import ModelView, fields
2012-09-17 12:40:18 +02:00
from trytond.wizard import Wizard, StateTransition, StateView, Button
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.pyson import Eval
2014-01-14 17:03:00 +01:00
import threading
import logging
from time import sleep
2012-09-17 12:40:18 +02:00
2012-10-25 13:49:54 +02:00
__all__ = ['TemplateEmailStart', 'TemplateEmailResult',
'GenerateTemplateEmail']
2012-10-25 13:49:54 +02:00
2014-01-14 17:03:00 +01:00
2012-09-17 12:40:18 +02:00
class TemplateEmailStart(ModelView):
'Template Email Start'
2012-10-25 13:49:54 +02:00
__name__ = 'electronic.mail.wizard.templateemail.start'
2012-09-17 12:40:18 +02:00
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,
states={
'readonly': ~Eval('single', True),
}, depends=['single'])
plain = fields.Text('Plain Text Body', required=True,
states={
'readonly': ~Eval('single', True),
}, depends=['single'])
send_html = fields.Boolean('Send HTML',
help='Send email with text and html')
html = fields.Text('HTML Text Body',
states={
'invisible': ~Eval('send_html', True),
'required': Eval('send_html', True),
'readonly': ~Eval('single', True),
}, depends=['send_html', 'single'])
2012-09-17 12:40:18 +02:00
total = fields.Integer('Total', readonly=True,
help='Total emails to send')
message_id = fields.Char('Message-ID')
in_reply_to = fields.Char('In Repply To')
2012-09-17 12:40:18 +02:00
template = fields.Many2One("electronic.mail.template", 'Template')
single = fields.Boolean('Single Email',
2015-02-18 15:49:34 +01:00
help='Send Single Email')
@staticmethod
def default_single():
return True
2012-09-17 12:40:18 +02:00
class TemplateEmailResult(ModelView):
'Template Email Result'
2012-10-25 13:49:54 +02:00
__name__ = 'electronic.mail.wizard.templateemail.result'
2012-09-17 12:40:18 +02:00
name = fields.Char('Name', help='Name of Header Field')
class GenerateTemplateEmail(Wizard):
"Generate Email from template"
2012-10-25 13:49:54 +02:00
__name__ = "electronic_mail_wizard.templateemail"
2012-09-17 12:40:18 +02:00
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()
2012-10-25 13:49:54 +02:00
@classmethod
def __setup__(cls):
super(GenerateTemplateEmail, cls).__setup__()
cls._error_messages.update({
'template_deleted': 'This template has been deactivated or '
'deleted.',
2012-09-17 12:55:42 +02:00
})
def default_start(self, fields):
default = self.render_fields(self.__name__)
return default
def transition_send(self):
self.render_and_send()
return 'end'
2012-09-17 12:40:18 +02:00
def render(self, template, record, values):
'''Renders the template and returns as email object
:param template: Object of the template
:param record: Object of the template
2012-09-17 12:40:18 +02:00
:param values: Dicctionary values
:return: 'email.message.Message' instance
'''
2012-10-25 13:49:54 +02:00
Template = Pool().get('electronic.mail.template')
2012-09-17 12:40:18 +02:00
message = MIMEMultipart()
messageid = template.eval(values['message_id'], record)
message['message_id'] = messageid or make_msgid()
2012-09-17 12:40:18 +02:00
message['date'] = formatdate(localtime=1)
message['in_reply_to'] = ""
if values.get('in_reply_to'):
message['in_reply_to'] = template.eval(values['in_reply_to'],
record)
2012-09-17 12:40:18 +02:00
language = Transaction().context.get('language', 'en_US')
if template.language:
language = template.eval(template.language, record)
2012-09-17 12:40:18 +02:00
with Transaction().set_context(language=language):
template = Template(template.id)
message['from'] = template.eval(values['from_'], record)
message['to'] = template.eval(values['to'], record)
message['cc'] = template.eval(values['cc'], record)
#~ message['bcc'] = template.eval(values['bcc'], record)
message['subject'] = Header(template.eval(values['subject'],
record), 'utf-8')
2012-09-17 12:40:18 +02:00
plain = template.eval(values['plain'], record)
if template.signature:
User = Pool().get('res.user')
user = User(Transaction().user)
signature = user.signature.encode('utf-8')
plain = '%s\n--\n%s' % (plain, signature)
# HTML
send_html = values.get('send_html')
if send_html:
html = template.eval(values['html'], record)
if template.signature:
html = '%s<br>--<br>%s' % (html,
signature.replace('\n', '<br>'))
2015-02-18 13:46:46 +01:00
html = """
<html>
<head><head>
<body>
2015-02-18 13:46:46 +01:00
%s
</body>
</html>
2015-02-18 13:46:46 +01:00
""" % html
2015-02-18 13:46:46 +01:00
# MIME HTML or Text
if send_html:
body = MIMEMultipart('alternative')
body.attach(MIMEText(plain, 'plain', _charset='utf-8'))
body.attach(MIMEText(html, 'html', _charset='utf-8'))
message.attach(body)
else:
message.attach(MIMEText(plain, _charset='utf-8'))
2014-12-01 18:07:10 +01:00
2012-09-17 12:40:18 +02:00
# Attach reports
if template.reports:
2014-12-18 12:46:55 +01:00
reports = template.render_reports(record)
2012-09-17 12:40:18 +02:00
for report in reports:
ext, data, filename, file_name = report[0:5]
if file_name:
filename = template.eval(file_name, record)
2012-09-17 12:40:18 +02:00
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)
2013-11-27 14:20:53 +01:00
attachment.set_payload(data)
Encoders.encode_base64(attachment)
2012-09-17 12:40:18 +02:00
attachment.add_header(
'Content-Disposition', 'attachment', filename=filename)
attachment.add_header(
'Content-Transfer-Encoding', 'base64')
2012-09-17 12:40:18 +02:00
message.attach(attachment)
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 = {}
pool = Pool()
Wizard = pool.get('ir.action.wizard')
Template = pool.get('electronic.mail.template')
2012-09-17 12:40:18 +02:00
active_ids = Transaction().context.get('active_ids')
context = Transaction().context
action_id = context.get('action_id', None)
wizard = Wizard(action_id)
template = (wizard.template and wizard.template[0]
or self.raise_user_error('template_deleted'))
2012-09-17 12:40:18 +02:00
total = len(active_ids)
2014-03-21 09:00:55 +01:00
record = Pool().get(template.model.model)(active_ids[0])
#load data in language when send a record
if template.language and total == 1:
language = template.eval(template.language, record)
with Transaction().set_context(language=language):
template = Template(template.id)
default['from_'] = template.eval(template.from_, record)
2012-09-17 12:40:18 +02:00
default['total'] = total
default['single'] = False if total > 1 else True
2012-09-17 12:40:18 +02:00
default['template'] = template.id
if total > 1: # show fields with tags
default['message_id'] = template.message_id
default['in_reply_to'] = template.in_reply_to
2012-09-17 12:40:18 +02:00
default['to'] = template.to
default['cc'] = template.cc
default['bcc'] = template.bcc
default['subject'] = template.subject
default['plain'] = template.plain
default['html'] = template.html
else: # show fields with rendered tags
2013-05-13 10:02:37 +02:00
record = Pool().get(template.model.model)(active_ids[0])
default['message_id'] = template.eval(template.message_id, record)
default['in_reply_to'] = template.eval(template.in_reply_to,
record)
default['to'] = template.eval(template.to, record)
default['cc'] = template.eval(template.cc, record)
default['bcc'] = template.eval(template.bcc, record)
default['subject'] = template.eval(template.subject,
record)
default['plain'] = template.eval(template.plain, record)
default['html'] = template.eval(template.html, record)
2012-09-17 12:40:18 +02:00
return default
2012-10-25 13:49:54 +02:00
def render_and_send(self):
2014-03-24 11:36:23 +01:00
pool = Pool()
Mail = pool.get('electronic.mail')
Template = pool.get('electronic.mail.template')
2014-03-24 11:36:23 +01:00
2012-10-25 13:49:54 +02:00
template = self.start.template
2012-09-17 12:40:18 +02:00
active_ids = Transaction().context.get('active_ids')
total = len(active_ids)
for active_id in active_ids:
record = pool.get(template.model.model)(active_id)
2012-09-17 12:40:18 +02:00
values = {}
values['message_id'] = self.start.message_id
if self.start.in_reply_to:
values['in_reply_to'] = self.start.in_reply_to
2012-10-25 13:49:54 +02:00
values['from_'] = self.start.from_
values['to'] = self.start.to
values['cc'] = self.start.cc
values['bcc'] = self.start.bcc
values['send_html'] = self.start.send_html
if total > 1 and template.language: # multi emails by language
language = template.eval(template.language, record)
with Transaction().set_context(language=language):
template = Template(template.id)
values['subject'] = template.eval(template.subject, record)
values['plain'] = template.eval(template.plain, record)
values['html'] = template.eval(template.html, record)
else: # a single email
values['subject'] = self.start.subject
values['plain'] = self.start.plain
values['html'] = self.start.html
2013-05-13 10:02:37 +02:00
2014-03-24 11:36:23 +01:00
emails = []
if self.start.from_:
emails += template.eval(self.start.from_, record).split(',')
2014-03-24 11:36:23 +01:00
if self.start.to:
emails += template.eval(self.start.to, record).split(',')
2014-03-24 11:36:23 +01:00
if self.start.cc:
emails += template.eval(self.start.cc, record).split(',')
2014-03-24 11:36:23 +01:00
if self.start.bcc:
emails += template.eval(self.start.bcc, record).split(',')
2014-03-24 11:36:23 +01:00
email_message = self.render(template, record, values)
context = {}
if values.get('bcc'):
context['bcc'] = values.get('bcc')
electronic_email = Mail.create_from_email(
email_message, template.mailbox.id, context)
2014-03-24 11:36:23 +01:00
2014-01-14 17:03:00 +01:00
db_name = Transaction().cursor.dbname
thread1 = threading.Thread(target=self.render_and_send_thread,
args=(db_name, Transaction().user, template, active_id,
electronic_email,))
2014-01-14 17:03:00 +01:00
thread1.start()
def render_and_send_thread(self, db_name, user, template, active_id,
electronic_email):
2014-01-14 17:03:00 +01:00
with Transaction().start(db_name, user) as transaction:
pool = Pool()
Email = pool.get('electronic.mail')
Template = pool.get('electronic.mail.template')
sleep(5)
electronic_email = Email(electronic_email)
2014-01-14 17:03:00 +01:00
template, = Template.browse([template])
record = Pool().get(template.model.model)(active_id)
success = electronic_email.send_email()
if success:
logging.getLogger('Mail').info('Send template email: %s - %s' %
(template.name, active_id))
else:
electronic_email.mailbox = template.draft_mailbox
2014-01-14 17:03:00 +01:00
template.add_event(record, electronic_email) # add event
transaction.cursor.commit()