Add attachments to email
issue6675 review40581002
This commit is contained in:
@@ -8,6 +8,7 @@ from . import ir
|
||||
def register():
|
||||
Pool.register(
|
||||
notification.Email,
|
||||
notification.EmailAttachment,
|
||||
notification.Log,
|
||||
ir.Trigger,
|
||||
module='notification_email', type_='model')
|
||||
|
||||
@@ -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
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user