Add support for HTML bodies to the user mailers. Closes GitLab issue #470.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2018-04-10 17:53:15 -04:00
parent 3484dc8f33
commit 8496ea7072
9 changed files with 78 additions and 43 deletions

View File

@@ -150,6 +150,7 @@
- Add locking for interval sources. This reduces the chance of repeated documents from long running email downloads.
- Add the option to enable or disable parsing when uploading a document for each document type.
- Add a new setting option to enable automatic parsing for each new document type created.
- Add support for HTML bodies to the user mailers.
2.7.3 (2017-09-11)
==================

View File

@@ -469,7 +469,7 @@ Other changes worth mentioning
- Add locking for interval sources. This reduces the chance of repeated documents from long running email downloads.
- Add the option to enable or disable parsing when uploading a document for each document type.
- Add a new setting option to enable automatic parsing for each new document type created.
- Add support for HTML bodies to the user mailers.
Removals
--------
@@ -541,6 +541,7 @@ Bugs fixed or issues closed
* `GitLab issue #454 <https://gitlab.com/mayan-edms/mayan-edms/issues/454>`_ Invalid next month calculation in statistics app, causes failstop
* `GitLab issue #467 <https://gitlab.com/mayan-edms/mayan-edms/issues/467>`_ mail attachments without content-disposition are lost
* `GitLab issue #468 <https://gitlab.com/mayan-edms/mayan-edms/issues/468>`_ plain text e-mails without charset do not work
* `GitLab issue #470 <https://gitlab.com/mayan-edms/mayan-edms/issues/470>`_ Enable Django variable for HTML encoded emails
* `GitHub issue #264 <https://github.com/mayan-edms/mayan-edms/issues/264>`_ migrate fails on document_states 0004_workflow_internal_name
* `GitHub issue #269 <https://github.com/mayan-edms/mayan-edms/issues/269>`_ Lack of authentication for document previews

View File

@@ -3,8 +3,11 @@ from __future__ import unicode_literals
import json
import logging
from django.contrib.sites.models import Site
from django.core import mail
from django.db import models
from django.template import Context, Template
from django.utils.html import strip_tags
from django.utils.module_loading import import_string
from django.utils.translation import ugettext_lazy as _
@@ -82,21 +85,28 @@ class UserMailer(models.Model):
return super(UserMailer, self).save(*args, **kwargs)
def send(self, subject='', body='', to=None, document=None, as_attachment=False):
def send(self, to, subject='', body='', attachments=None):
"""
Send a simple email. There is no document or template knowledge.
attachments is a list of dictionaries with the keys:
filename, content, and mimetype.
"""
recipient_list = split_recipient_list(recipients=[to])
with self.get_connection() as connection:
email_message = mail.EmailMultiAlternatives(
subject=subject, body=body, to=recipient_list,
connection=connection
body=strip_tags(body), connection=connection, subject=subject,
to=recipient_list,
)
if as_attachment:
with document.open() as descriptor:
email_message.attach(
filename=document.label, content=descriptor.read(),
mimetype=document.file_mimetype
)
for attachment in attachments or []:
email_message.attach(
filename=attachment['filename'],
content=attachment['content'],
mimetype=attachment['mimetype']
)
email_message.attach_alternative(body, 'text/html')
try:
email_message.send()
@@ -105,8 +115,39 @@ class UserMailer(models.Model):
else:
self.error_log.all().delete()
def send_document(self, document, to, subject='', body='', as_attachment=False):
context_dictionary = {
'link': 'http://%s%s' % (
Site.objects.get_current().domain,
document.get_absolute_url()
),
'document': document
}
context = Context(context_dictionary)
body_template = Template(body)
body_html_content = body_template.render(context)
subject_template = Template(subject)
subject_text = strip_tags(subject_template.render(context))
attachments = []
if as_attachment:
with document.open() as file_object:
attachments.append(
{
'filename': document.label, 'content': file_object.read(),
'mimetype': document.file_mimetype
}
)
return self.send(
subject=subject_text, body=body_html_content, to=to, attachments=attachments
)
def test(self, to):
self.send(to=to, subject=_('Test email from Mayan EDMS'))
self.send(subject=_('Test email from Mayan EDMS'), to=to)
class UserMailerLogEntry(models.Model):

View File

@@ -17,7 +17,7 @@ setting_link_subject_template = namespace.add_setting(
)
setting_link_body_template = namespace.add_setting(
default=DEFAULT_LINK_BODY_TEMPLATE,
help_text=_('Template for the document link email form body line.'),
help_text=_('Template for the document link email form body text. Can include HTML.'),
global_name='MAILER_LINK_BODY_TEMPLATE',
)
setting_document_subject_template = namespace.add_setting(
@@ -27,6 +27,6 @@ setting_document_subject_template = namespace.add_setting(
)
setting_document_body_template = namespace.add_setting(
default=DEFAULT_DOCUMENT_BODY_TEMPLATE,
help_text=_('Template for the document email form body line.'),
help_text=_('Template for the document email form body text. Can include HTML.'),
global_name='MAILER_DOCUMENT_BODY_TEMPLATE',
)

View File

@@ -6,7 +6,7 @@ from mayan.celery import app
@app.task(ignore_result=True)
def task_send_document(subject_text, body_text_content, sender, recipient, user_mailer_id, as_attachment=False, document_id=None):
def task_send_document(body, sender, subject, recipient, user_mailer_id, as_attachment=False, document_id=None):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
@@ -21,7 +21,7 @@ def task_send_document(subject_text, body_text_content, sender, recipient, user_
user_mailer = UserMailer.objects.get(pk=user_mailer_id)
user_mailer.send(
subject=subject_text, body=body_text_content, to=recipient,
document=document, as_attachment=as_attachment
user_mailer.send_document(
as_attachment=as_attachment, body=body, document=document,
subject=subject, to=recipient
)

View File

@@ -1,5 +1,6 @@
from __future__ import unicode_literals
TEST_BODY_HTML = '<strong>test body</strong>'
TEST_EMAIL_ADDRESS = 'test@example.com'
TEST_RECIPIENTS_MULTIPLE_COMMA = 'test@example.com,test2@example.com'
TEST_RECIPIENTS_MULTIPLE_SEMICOLON = 'test@example.com;test2@example.com'

View File

@@ -7,7 +7,7 @@ from documents.tests.test_models import GenericDocumentTestCase
from ..models import UserMailer
from .literals import (
TEST_EMAIL_ADDRESS, TEST_RECIPIENTS_MULTIPLE_COMMA,
TEST_BODY_HTML, TEST_EMAIL_ADDRESS, TEST_RECIPIENTS_MULTIPLE_COMMA,
TEST_RECIPIENTS_MULTIPLE_SEMICOLON, TEST_RECIPIENTS_MULTIPLE_MIXED,
TEST_RECIPIENTS_MULTIPLE_MIXED_LIST, TEST_USER_MAILER_LABEL,
TEST_USER_MAILER_BACKEND_PATH
@@ -31,9 +31,17 @@ class ModelTestCase(GenericDocumentTestCase):
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
def test_send_simple_with_html(self):
self._create_user_mailer()
self.user_mailer.send(to=TEST_EMAIL_ADDRESS, body=TEST_BODY_HTML)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
self.assertEqual(mail.outbox[0].alternatives[0][0], TEST_BODY_HTML)
def test_send_attachment(self):
self._create_user_mailer()
self.user_mailer.send(
self.user_mailer.send_document(
to=TEST_EMAIL_ADDRESS, document=self.document, as_attachment=True
)

View File

@@ -19,7 +19,6 @@ from .mailers import TestBackend
class MailerTestMixin(object):
def _create_user_mailer(self):
self.user_mailer = UserMailer.objects.create(
default=True,
enabled=True,

View File

@@ -1,11 +1,8 @@
from __future__ import absolute_import, unicode_literals
from django.contrib.sites.models import Site
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.template import Context, Template
from django.urls import reverse, reverse_lazy
from django.utils.html import strip_tags
from django.utils.translation import ungettext, ugettext_lazy as _
from acls.models import AccessControlList
@@ -84,33 +81,20 @@ class MailDocumentView(MultipleObjectFormActionView):
}
def object_action(self, form, instance):
context = Context({
'link': 'http://%s%s' % (
Site.objects.get_current().domain,
instance.get_absolute_url()
),
'document': instance
})
body_template = Template(form.cleaned_data['body'])
body_html_content = body_template.render(context)
body_text_content = strip_tags(body_html_content)
subject_template = Template(form.cleaned_data['subject'])
subject_text = strip_tags(subject_template.render(context))
AccessControlList.objects.check_access(
permissions=permission_user_mailer_use, user=self.request.user,
obj=form.cleaned_data['user_mailer']
)
task_send_document.apply_async(
args=(
subject_text, body_text_content, self.request.user.email,
form.cleaned_data['email']
), kwargs={
'document_id': instance.pk,
kwargs={
'as_attachment': self.as_attachment,
'user_mailer_id': form.cleaned_data['user_mailer'].pk
'body': form.cleaned_data['body'],
'document_id': instance.pk,
'recipient': form.cleaned_data['email'],
'sender': self.request.user.email,
'subject': form.cleaned_data['subject'],
'user_mailer_id': form.cleaned_data['user_mailer'].pk,
}
)