Add support for emailing documents to a recipient list. GitLab #396
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
2.5.3 (2017-07-XX)
|
||||
==================
|
||||
- Fix HTML mark up in window title. GitLab issue #397.
|
||||
|
||||
- Fix HTML mark up in window title. GitLab #397.
|
||||
- Add support for emailing documents to a recipient list. GitLab #396
|
||||
|
||||
2.5.2 (2017-07-08)
|
||||
==================
|
||||
- Improve new document creation signal handling.
|
||||
|
||||
@@ -14,3 +14,5 @@ DEFAULT_LINK_BODY_TEMPLATE = _(
|
||||
'{{ link }}\n\n--------\n '
|
||||
'This email has been sent from %(project_title)s (%(project_website)s)'
|
||||
)
|
||||
|
||||
EMAIL_SEPARATORS = (',', ';')
|
||||
|
||||
@@ -8,6 +8,8 @@ from django.db import models
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .utils import split_recipient_list
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -80,36 +82,28 @@ class UserMailer(models.Model):
|
||||
self.backend_data = json.dumps(data)
|
||||
self.save()
|
||||
|
||||
def send(self, **kwargs):
|
||||
"""
|
||||
https://docs.djangoproject.com/en/1.11/topics/email
|
||||
#django.core.mail.EmailMessage
|
||||
subject: The subject line of the email.
|
||||
body: The body text. This should be a plain text message.
|
||||
from_email: The sender's address. Both fred@example.com and Fred
|
||||
<fred@example.com> forms are legal. If omitted,
|
||||
the DEFAULT_FROM_EMAIL setting is used.
|
||||
to: A list or tuple of recipient addresses.
|
||||
bcc: A list or tuple of addresses used in the "Bcc" header when
|
||||
sending the email.
|
||||
connection: An email backend instance. Use this parameter if you want
|
||||
to use the same connection for multiple messages. If omitted, a new
|
||||
connection is created when send() is called.
|
||||
attachments: A list of attachments to put on the message. These can be
|
||||
either email.MIMEBase.MIMEBase instances, or (filename, content,
|
||||
mimetype) triples.
|
||||
headers: A dictionary of extra headers to put on the message. The
|
||||
keys are the header name, values are the header values. It's up to
|
||||
the caller to ensure header names and values are in the correct
|
||||
format for an email message. The corresponding attribute is
|
||||
extra_headers.
|
||||
cc: A list or tuple of recipient addresses used in the "Cc"
|
||||
header when sending the email.
|
||||
reply_to: A list or tuple of recipient addresses used in the
|
||||
"Reply-To" header when sending the email.
|
||||
"""
|
||||
def send(self, subject='', body='', to=None, document=None, as_attachment=False):
|
||||
recipient_list = split_recipient_list(recipients=[to])
|
||||
|
||||
with self.get_connection() as connection:
|
||||
mail.EmailMessage(connection=connection, **kwargs).send()
|
||||
email_message = mail.EmailMultiAlternatives(
|
||||
subject=subject, body=body, to=recipient_list,
|
||||
connection=connection
|
||||
)
|
||||
|
||||
if as_attachment:
|
||||
with document.open() as descriptor:
|
||||
email_message.attach(
|
||||
filename=document.label, content=descriptor.read(),
|
||||
mimetype=document.file_mimetype
|
||||
)
|
||||
|
||||
try:
|
||||
email_message.send()
|
||||
except Exception as exception:
|
||||
self.error_log.create(message=exception)
|
||||
else:
|
||||
self.error_log.all().delete()
|
||||
|
||||
def test(self, to):
|
||||
self.send(to=to, subject=_('Test email from Mayan EDMS'))
|
||||
|
||||
@@ -1,37 +1,27 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
|
||||
from documents.models import Document
|
||||
from mayan.celery import app
|
||||
|
||||
|
||||
@app.task(ignore_result=True)
|
||||
def task_send_document(subject_text, body_text_content, sender, recipient, document_id, user_mailer_id, as_attachment=False):
|
||||
def task_send_document(subject_text, body_text_content, sender, recipient, user_mailer_id, as_attachment=False, document_id=None):
|
||||
Document = apps.get_model(
|
||||
app_label='documents', model_name='Document'
|
||||
)
|
||||
UserMailer = apps.get_model(
|
||||
app_label='mailer', model_name='UserMailer'
|
||||
)
|
||||
|
||||
if document_id:
|
||||
document = Document.objects.get(pk=document_id)
|
||||
else:
|
||||
document = None
|
||||
|
||||
user_mailer = UserMailer.objects.get(pk=user_mailer_id)
|
||||
|
||||
connection = user_mailer.get_connection()
|
||||
|
||||
email_msg = EmailMultiAlternatives(
|
||||
subject_text, body_text_content, sender, [recipient],
|
||||
connection=connection,
|
||||
user_mailer.send(
|
||||
subject=subject_text, body=body_text_content, to=recipient,
|
||||
document=document, as_attachment=as_attachment
|
||||
)
|
||||
|
||||
if as_attachment:
|
||||
document = Document.objects.get(pk=document_id)
|
||||
with document.open() as descriptor:
|
||||
email_msg.attach(
|
||||
document.label, descriptor.read(), document.file_mimetype
|
||||
)
|
||||
|
||||
try:
|
||||
email_msg.send()
|
||||
except Exception as exception:
|
||||
user_mailer.error_log.create(message=exception)
|
||||
else:
|
||||
user_mailer.error_log.all().delete()
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
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'
|
||||
TEST_RECIPIENTS_MULTIPLE_MIXED = 'test@example.com,test2@example.com;test2@example.com'
|
||||
TEST_RECIPIENTS_MULTIPLE_MIXED_LIST = (
|
||||
'test@example.com', 'test2@example.com', 'test2@example.com',
|
||||
)
|
||||
TEST_USER_MAILER_LABEL = 'test user mailer label'
|
||||
TEST_USER_MAILER_BACKEND_PATH = 'mailer.tests.mailers.TestBackend'
|
||||
|
||||
@@ -4,5 +4,8 @@ from ..classes import MailerBackend
|
||||
|
||||
|
||||
class TestBackend(MailerBackend):
|
||||
"""
|
||||
User mailer backend to use with tests
|
||||
"""
|
||||
class_path = 'django.core.mail.backends.locmem.EmailBackend'
|
||||
label = 'Django local memory backend'
|
||||
|
||||
75
mayan/apps/mailer/tests/test_models.py
Normal file
75
mayan/apps/mailer/tests/test_models.py
Normal file
@@ -0,0 +1,75 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.core import mail
|
||||
|
||||
from documents.tests.test_models import GenericDocumentTestCase
|
||||
|
||||
from ..models import UserMailer
|
||||
|
||||
from .literals import (
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
class ModelTestCase(GenericDocumentTestCase):
|
||||
def _create_user_mailer(self):
|
||||
self.user_mailer = UserMailer.objects.create(
|
||||
default=True,
|
||||
enabled=True,
|
||||
label=TEST_USER_MAILER_LABEL,
|
||||
backend_path=TEST_USER_MAILER_BACKEND_PATH,
|
||||
backend_data='{}'
|
||||
)
|
||||
|
||||
def test_send_simple(self):
|
||||
self._create_user_mailer()
|
||||
self.user_mailer.send(to=TEST_EMAIL_ADDRESS)
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
|
||||
|
||||
def test_send_attachment(self):
|
||||
self._create_user_mailer()
|
||||
self.user_mailer.send(
|
||||
to=TEST_EMAIL_ADDRESS, document=self.document, as_attachment=True
|
||||
)
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
|
||||
with self.document.open() as file_object:
|
||||
self.assertEqual(
|
||||
mail.outbox[0].attachments[0], (
|
||||
self.document.label, file_object.read(),
|
||||
self.document.file_mimetype
|
||||
)
|
||||
)
|
||||
|
||||
def test_send_multiple_recipients_comma(self):
|
||||
self._create_user_mailer()
|
||||
self.user_mailer.send(to=TEST_RECIPIENTS_MULTIPLE_COMMA)
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(
|
||||
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_COMMA.split(',')
|
||||
)
|
||||
|
||||
def test_send_multiple_recipients_semicolon(self):
|
||||
self._create_user_mailer()
|
||||
self.user_mailer.send(to=TEST_RECIPIENTS_MULTIPLE_SEMICOLON)
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(
|
||||
mail.outbox[0].to, TEST_RECIPIENTS_MULTIPLE_SEMICOLON.split(';')
|
||||
)
|
||||
|
||||
def test_send_multiple_recipient_mixed(self):
|
||||
self._create_user_mailer()
|
||||
self.user_mailer.send(to=TEST_RECIPIENTS_MULTIPLE_MIXED)
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(
|
||||
list(mail.outbox[0].to), list(TEST_RECIPIENTS_MULTIPLE_MIXED_LIST)
|
||||
)
|
||||
21
mayan/apps/mailer/utils.py
Normal file
21
mayan/apps/mailer/utils.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .literals import EMAIL_SEPARATORS
|
||||
|
||||
|
||||
def split_recipient_list(recipients, separator_list=None, separator_index=0):
|
||||
separator_list = separator_list or EMAIL_SEPARATORS
|
||||
|
||||
try:
|
||||
separator = separator_list[separator_index]
|
||||
except IndexError:
|
||||
return recipients
|
||||
else:
|
||||
result = []
|
||||
for recipient in recipients:
|
||||
result.extend(recipient.split(separator))
|
||||
|
||||
return split_recipient_list(
|
||||
recipients=result, separator_list=separator_list,
|
||||
separator_index=separator_index + 1
|
||||
)
|
||||
Reference in New Issue
Block a user