Add attachments to email

issue6675
review40581002
This commit is contained in:
Cédric Krier
2017-08-02 22:53:56 +02:00
parent 65e9641271
commit 2d7090df28
5 changed files with 136 additions and 2 deletions
+1
View File
@@ -8,6 +8,7 @@ from . import ir
def register():
Pool.register(
notification.Email,
notification.EmailAttachment,
notification.Log,
ir.Trigger,
module='notification_email', type_='model')
+1
View File
@@ -3,3 +3,4 @@ Notification Email Module
The notification email module allows to define email templates which will be
sent to a list of recipients when a trigger is fired on a record event.
Extra reports from the same record can be attached to the email.
+64 -2
View File
@@ -1,6 +1,7 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from email.header import Header
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr, getaddresses
@@ -17,7 +18,7 @@ from trytond.pyson import Eval
from trytond.sendmail import sendmail_transactional, SMTPDataManager
from trytond.transaction import Transaction
__all__ = ['Email', 'Log']
__all__ = ['Email', 'EmailAttachment', 'Log']
def _formataddr(name, email):
@@ -85,6 +86,14 @@ class Email(ModelSQL, ModelView):
'ir.action.report', "Content", required=True,
domain=[('template_extension', 'in', ['plain', 'html', 'xhtml'])],
help="The report used as email template.")
attachments = fields.Many2Many(
'notification.email.attachment', 'notification', 'report',
"Attachments",
domain=[
('model', '=', Eval('model')),
],
depends=['model'],
help="The reports used as attachments.")
triggers = fields.One2Many(
'ir.trigger', 'notification_email', "Triggers",
@@ -170,8 +179,21 @@ class Email(ModelSQL, ModelView):
return {self._get_language(value)}
def get_email(self, record, from_, to, cc, bcc, languages):
msg, title = _get_email_template(
pool = Pool()
Attachment = pool.get('notification.email.attachment')
content, title = _get_email_template(
self.content.report_name, record, languages)
if self.attachments:
msg = MIMEMultipart('mixed')
msg.attach(content)
language = list(languages)[-1]
for report in self.attachments:
msg.attach(Attachment.get_mime(report, record, language))
else:
msg = content
msg['From'] = from_
msg['To'] = ', '.join(to)
msg['Cc'] = ', '.join(cc)
@@ -238,6 +260,46 @@ class Email(ModelSQL, ModelView):
Log.create(logs)
class EmailAttachment(ModelSQL):
"Email Notification Attachment"
__name__ = 'notification.email.attachment'
notification = fields.Many2One(
'notification.email', "Notification",
required=True, select=True)
report = fields.Many2One(
'ir.action.report', "Report", required=True,
domain=[
('model', '=', Eval('model')),
],
depends=['model'])
model = fields.Function(fields.Char("Model"), 'get_model')
def get_model(self, name):
return self.notification.model
@classmethod
def get_mime(cls, report, record, language):
pool = Pool()
Report = pool.get(report.report_name, type='report')
with Transaction().set_context(language=language):
ext, content, _, title = Report.execute(
[record.id], {
'action_id': report.id,
})
name = '%s.%s' % (title, ext)
msg = MIMEApplication(content)
if not isinstance(name, str):
name = name.encode('utf-8')
if not isinstance(language, str):
language = language.encode('utf-8')
msg.add_header(
'Content-Disposition', 'attachment',
filename=('utf-8', language, name))
return msg
class Log(ModelSQL, ModelView):
"Notitification Log"
__name__ = 'notification.log'
+69
View File
@@ -105,6 +105,75 @@ class NotificationEmailTestCase(ModuleTestCase):
self.assertEqual(log.recipients_secondary, '')
self.assertEqual(log.recipients_hidden, '')
@with_transaction()
def test_notification_email_attachment(self):
"Test email notificiation with attachment"
pool = Pool()
Model = pool.get('ir.model')
ModelField = pool.get('ir.model.field')
Action = pool.get('ir.action')
Report = pool.get('ir.action.report')
User = pool.get('res.user')
NotificationEmail = pool.get('notification.email')
model, = Model.search([
('model', '=', User.__name__),
])
action_model, = Model.search([
('model', '=', 'notification.email'),
])
action = Action(name="Notification Email", type='ir.action.report')
action.save()
report = Report()
report.report_name = 'notification_notification.test.report'
report.action = action
report.template_extension = 'plain'
report.report_content = b'Hello ${records[0].name}'
report.model = model.model
report.save()
attachment = Report()
attachment.name = "Attachment"
attachment.report_name = 'notification_notification.test.report'
attachment.template_extension = 'plain'
attachment.report_content = b'attachment for ${records[0].name}'
attachment.model = model.model
attachment.save()
user = User(Transaction().user)
user.email = 'user@example.com'
user.save()
notification_email = NotificationEmail()
notification_email.recipients, = ModelField.search([
('model.model', '=', model.model),
('name', '=', 'create_uid'),
])
notification_email.content = report
notification_email.attachments = [attachment]
notification_email.save()
user, = User.create([{'name': "Michael Scott", 'login': "msc"}])
msg = notification_email.get_email(
user, FROM, ['Administrator <user@example.com>'], [], [], ['en'])
self.assertEqual(msg['From'], FROM)
self.assertEqual(msg['Subject'], 'Notification Email')
self.assertEqual(msg['To'], 'Administrator <user@example.com>')
self.assertEqual(msg.get_content_type(), 'multipart/mixed')
self.assertEqual(
msg.get_payload(0).get_content_type(), 'multipart/alternative')
attachment = msg.get_payload(1)
self.assertEqual(
attachment.get_payload(None, True),
'attachment for Michael Scott')
self.assertEqual(
attachment.get_content_type(), 'application/octet-stream')
self.assertEqual(attachment.get_filename(), "Attachment.plain")
def suite():
suite = test_suite()
+1
View File
@@ -12,5 +12,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="recipients_secondary"/>
<label name="recipients_hidden"/>
<field name="recipients_hidden"/>
<field name="attachments" colspan="2"/>
<field name="triggers" colspan="2"/>
</form>