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
|
2015-02-18 13:17:51 +01:00
|
|
|
from trytond.pyson import Eval
|
2014-01-14 17:03:00 +01:00
|
|
|
import threading
|
|
|
|
import logging
|
2015-02-20 16:35:11 +01:00
|
|
|
from time import sleep
|
2012-09-17 12:40:18 +02:00
|
|
|
|
2012-10-25 13:49:54 +02:00
|
|
|
__all__ = ['TemplateEmailStart', 'TemplateEmailResult',
|
2014-12-18 15:56:01 +01:00
|
|
|
'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')
|
2015-02-18 15:45:07 +01:00
|
|
|
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'])
|
2015-02-18 13:17:51 +01:00
|
|
|
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),
|
2015-02-18 15:45:07 +01:00
|
|
|
'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')
|
2015-02-18 13:17:51 +01:00
|
|
|
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')
|
2015-02-18 15:45:07 +01:00
|
|
|
single = fields.Boolean('Single Email',
|
2015-02-18 15:49:34 +01:00
|
|
|
help='Send Single Email')
|
2015-02-18 15:45:07 +01:00
|
|
|
|
|
|
|
@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({
|
2014-06-02 12:37:58 +02:00
|
|
|
'template_deleted': 'This template has been deactivated or '
|
|
|
|
'deleted.',
|
2012-09-17 12:55:42 +02:00
|
|
|
})
|
|
|
|
|
2014-02-13 19:20:43 +01: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
|
2012-10-25 14:33:02 +02:00
|
|
|
: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
|
|
|
|
2014-01-14 15:28:22 +01:00
|
|
|
message = MIMEMultipart()
|
2015-02-18 13:17:51 +01:00
|
|
|
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)
|
2015-02-18 13:17:51 +01:00
|
|
|
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:
|
2014-07-04 10:39:03 +02:00
|
|
|
language = template.eval(template.language, record)
|
2012-09-17 12:40:18 +02:00
|
|
|
|
2014-02-13 19:20:43 +01:00
|
|
|
with Transaction().set_context(language=language):
|
2012-10-25 14:33:02 +02:00
|
|
|
template = Template(template.id)
|
2014-07-04 10:39:03 +02:00
|
|
|
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
|
|
|
|
2015-02-18 13:17:51 +01: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 = """
|
2015-02-18 13:17:51 +01:00
|
|
|
<html>
|
|
|
|
<head><head>
|
|
|
|
<body>
|
2015-02-18 13:46:46 +01:00
|
|
|
%s
|
2015-02-18 13:17:51 +01:00
|
|
|
</body>
|
|
|
|
</html>
|
2015-02-18 13:46:46 +01:00
|
|
|
""" % html
|
2015-02-18 13:17:51 +01:00
|
|
|
|
2015-02-18 13:46:46 +01:00
|
|
|
# MIME HTML or Text
|
2015-02-18 13:17:51 +01:00
|
|
|
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:
|
2014-07-04 10:39:03 +02:00
|
|
|
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)
|
2015-02-18 13:17:51 +01:00
|
|
|
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 = {}
|
|
|
|
|
2015-02-18 15:45:07 +01:00
|
|
|
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')
|
|
|
|
|
2014-06-02 12:37:58 +02:00
|
|
|
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])
|
2014-01-15 11:21:36 +01:00
|
|
|
#load data in language when send a record
|
|
|
|
if template.language and total == 1:
|
2014-07-04 10:39:03 +02:00
|
|
|
language = template.eval(template.language, record)
|
2014-02-13 19:20:43 +01:00
|
|
|
with Transaction().set_context(language=language):
|
2014-01-15 11:21:36 +01:00
|
|
|
template = Template(template.id)
|
|
|
|
|
2014-07-04 10:39:03 +02:00
|
|
|
default['from_'] = template.eval(template.from_, record)
|
2012-09-17 12:40:18 +02:00
|
|
|
default['total'] = total
|
2015-02-18 15:45:07 +01:00
|
|
|
default['single'] = False if total > 1 else True
|
2012-09-17 12:40:18 +02:00
|
|
|
default['template'] = template.id
|
2014-02-13 19:20:43 +01:00
|
|
|
if total > 1: # show fields with tags
|
2015-02-18 13:17:51 +01:00
|
|
|
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
|
2015-02-18 13:17:51 +01:00
|
|
|
default['html'] = template.html
|
2014-02-13 19:20:43 +01:00
|
|
|
else: # show fields with rendered tags
|
2013-05-13 10:02:37 +02:00
|
|
|
record = Pool().get(template.model.model)(active_ids[0])
|
2015-02-18 13:17:51 +01:00
|
|
|
default['message_id'] = template.eval(template.message_id, record)
|
|
|
|
default['in_reply_to'] = template.eval(template.in_reply_to,
|
|
|
|
record)
|
2014-07-04 10:39:03 +02:00
|
|
|
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,
|
2014-02-13 19:20:43 +01:00
|
|
|
record)
|
2014-07-04 10:39:03 +02:00
|
|
|
default['plain'] = template.eval(template.plain, record)
|
2015-02-18 13:17:51 +01:00
|
|
|
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')
|
2015-02-18 15:45:07 +01:00
|
|
|
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
|
|
|
|
2015-02-18 15:45:07 +01:00
|
|
|
active_ids = Transaction().context.get('active_ids')
|
|
|
|
total = len(active_ids)
|
|
|
|
|
|
|
|
for active_id in active_ids:
|
2014-07-04 12:27:09 +02:00
|
|
|
record = pool.get(template.model.model)(active_id)
|
2012-09-17 12:40:18 +02:00
|
|
|
values = {}
|
2015-02-18 13:17:51 +01:00
|
|
|
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
|
2015-02-18 13:17:51 +01:00
|
|
|
values['send_html'] = self.start.send_html
|
2015-02-18 15:45:07 +01:00
|
|
|
|
|
|
|
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 = []
|
2015-02-18 13:17:51 +01:00
|
|
|
if self.start.from_:
|
2014-07-04 12:27:09 +02:00
|
|
|
emails += template.eval(self.start.from_, record).split(',')
|
2014-03-24 11:36:23 +01:00
|
|
|
if self.start.to:
|
2014-07-04 12:27:09 +02:00
|
|
|
emails += template.eval(self.start.to, record).split(',')
|
2014-03-24 11:36:23 +01:00
|
|
|
if self.start.cc:
|
2014-07-04 12:27:09 +02:00
|
|
|
emails += template.eval(self.start.cc, record).split(',')
|
2014-03-24 11:36:23 +01:00
|
|
|
if self.start.bcc:
|
2014-07-04 12:27:09 +02:00
|
|
|
emails += template.eval(self.start.bcc, record).split(',')
|
2014-03-24 11:36:23 +01:00
|
|
|
|
2015-02-20 16:35:11 +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
|
2014-02-13 19:20:43 +01:00
|
|
|
thread1 = threading.Thread(target=self.render_and_send_thread,
|
|
|
|
args=(db_name, Transaction().user, template, active_id,
|
2015-02-20 16:35:11 +01:00
|
|
|
electronic_email,))
|
2014-01-14 17:03:00 +01:00
|
|
|
thread1.start()
|
|
|
|
|
2014-02-13 19:20:43 +01:00
|
|
|
def render_and_send_thread(self, db_name, user, template, active_id,
|
2015-02-20 16:35:11 +01:00
|
|
|
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')
|
2015-02-20 16:35:11 +01:00
|
|
|
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)
|
2015-02-20 16:35:11 +01:00
|
|
|
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
|
|
|
|
2015-02-20 16:35:11 +01:00
|
|
|
template.add_event(record, electronic_email) # add event
|
2014-02-13 19:20:43 +01:00
|
|
|
transaction.cursor.commit()
|