From ce92f58fede6861f6352ef66f7ab85d22486d482 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 8 Oct 2014 16:28:04 -0400 Subject: [PATCH] Add mailer app to add support to send document or document links via email --- .tx/config | 7 + mayan/apps/mailer/__init__.py | 13 ++ mayan/apps/mailer/forms.py | 23 ++++ mayan/apps/mailer/links.py | 8 ++ .../mailer/locale/en/LC_MESSAGES/django.po | 123 ++++++++++++++++++ mayan/apps/mailer/models.py | 3 + mayan/apps/mailer/permissions.py | 10 ++ mayan/apps/mailer/settings.py | 16 +++ mayan/apps/mailer/tasks.py | 20 +++ mayan/apps/mailer/urls.py | 6 + mayan/apps/mailer/views.py | 91 +++++++++++++ mayan/settings/base.py | 1 + mayan/urls.py | 1 + 13 files changed, 322 insertions(+) create mode 100644 mayan/apps/mailer/__init__.py create mode 100644 mayan/apps/mailer/forms.py create mode 100644 mayan/apps/mailer/links.py create mode 100644 mayan/apps/mailer/locale/en/LC_MESSAGES/django.po create mode 100644 mayan/apps/mailer/models.py create mode 100644 mayan/apps/mailer/permissions.py create mode 100644 mayan/apps/mailer/settings.py create mode 100644 mayan/apps/mailer/tasks.py create mode 100644 mayan/apps/mailer/urls.py create mode 100644 mayan/apps/mailer/views.py diff --git a/.tx/config b/.tx/config index 383dc2b475..8c9ce77e80 100644 --- a/.tx/config +++ b/.tx/config @@ -174,3 +174,10 @@ file_filter = mayan/apps/user_management/locale//LC_MESSAGES/django.po source_lang = en source_file = mayan/apps/user_management/locale/en/LC_MESSAGES/django.po type = PO + +[mayan-edms.apps-mailer] +file_filter = mayan/apps/mailer/locale//LC_MESSAGES/django.po +source_lang = en +source_file = mayan/apps/mailer/locale/en/LC_MESSAGES/django.po +type = PO + diff --git a/mayan/apps/mailer/__init__.py b/mayan/apps/mailer/__init__.py new file mode 100644 index 0000000000..862148eef4 --- /dev/null +++ b/mayan/apps/mailer/__init__.py @@ -0,0 +1,13 @@ +from __future__ import absolute_import + +from acls.api import class_permissions +from documents.models import Document +from navigation.api import register_links + +from .links import send_document_link, send_document +from .permissions import PERMISSION_MAILING_LINK, PERMISSION_MAILING_SEND_DOCUMENT + +register_links([Document], [send_document_link, send_document]) + +class_permissions(Document, [PERMISSION_MAILING_LINK, + PERMISSION_MAILING_SEND_DOCUMENT]) diff --git a/mayan/apps/mailer/forms.py b/mayan/apps/mailer/forms.py new file mode 100644 index 0000000000..95716677fe --- /dev/null +++ b/mayan/apps/mailer/forms.py @@ -0,0 +1,23 @@ +from __future__ import absolute_import + +from django import forms +from django.utils.translation import ugettext as _ + +from .settings import (DOCUMENT_BODY_TEMPLATE, DOCUMENT_SUBJECT_TEMPLATE, + LINK_BODY_TEMPLATE, LINK_SUBJECT_TEMPLATE) + + +class DocumentMailForm(forms.Form): + def __init__(self, *args, **kwargs): + as_attachment = kwargs.pop('as_attachment', False) + super(DocumentMailForm, self).__init__(*args, **kwargs) + if as_attachment: + self.fields['subject'].initial = DOCUMENT_SUBJECT_TEMPLATE + self.fields['body'].initial = DOCUMENT_BODY_TEMPLATE + else: + self.fields['subject'].initial = LINK_SUBJECT_TEMPLATE + self.fields['body'].initial = LINK_BODY_TEMPLATE + + email = forms.EmailField(label=_(u'Email address')) + subject = forms.CharField(label=_(u'Subject'), required=False) + body = forms.CharField(label=_(u'Body'), widget=forms.widgets.Textarea(), required=False) diff --git a/mayan/apps/mailer/links.py b/mayan/apps/mailer/links.py new file mode 100644 index 0000000000..589abdaef9 --- /dev/null +++ b/mayan/apps/mailer/links.py @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +from django.utils.translation import ugettext_lazy as _ + +from .permissions import PERMISSION_MAILING_LINK, PERMISSION_MAILING_SEND_DOCUMENT + +send_document_link = {'text': _('Email link'), 'view': 'mailer:send_document_link', 'args': 'object.pk', 'famfam': 'email_link', 'permissions': [PERMISSION_MAILING_LINK]} +send_document = {'text': _(u'Email document'), 'view': 'mailer:send_document', 'args': 'object.pk', 'famfam': 'email_open', 'permissions': [PERMISSION_MAILING_SEND_DOCUMENT]} diff --git a/mayan/apps/mailer/locale/en/LC_MESSAGES/django.po b/mayan/apps/mailer/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000000..010b264435 --- /dev/null +++ b/mayan/apps/mailer/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,123 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-10-08 16:27-0400\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: forms.py:21 +msgid "Email address" +msgstr "" + +#: forms.py:22 +msgid "Subject" +msgstr "" + +#: forms.py:23 +msgid "Body" +msgstr "" + +#: links.py:7 +msgid "Email link" +msgstr "" + +#: links.py:8 +msgid "Email document" +msgstr "" + +#: permissions.py:7 +msgid "Mailing" +msgstr "" + +#: permissions.py:9 +msgid "Send document link via email" +msgstr "" + +#: permissions.py:10 +msgid "Send document via email" +msgstr "" + +#: settings.py:11 +msgid "Link for document: {{ document }}" +msgstr "" + +#: settings.py:11 +msgid "Template for the document link email form subject line." +msgstr "" + +#: settings.py:12 +msgid "" +"To access this document click on the following link: {{ link }}

\n" +"\n" +"--------
\n" +"This email has been sent from Mayan EDMS (http://www.mayan-edms.com)" +msgstr "" + +#: settings.py:12 +msgid "Template for the document link email form body line." +msgstr "" + +#: settings.py:13 +msgid "Document: {{ document }}" +msgstr "" + +#: settings.py:13 +msgid "Template for the document email form subject line." +msgstr "" + +#: settings.py:14 +msgid "" +"Attached to this email is the document: {{ document }}

\n" +"\n" +"--------
\n" +"This email has been sent from Mayan EDMS (http://www.mayan-edms.com)" +msgstr "" + +#: settings.py:14 +msgid "Template for the document email form body line." +msgstr "" + +#: views.py:41 +msgid "Must provide at least one document." +msgstr "" + +#: views.py:66 +msgid "Successfully queued for delivery via email." +msgstr "" + +#: views.py:75 +msgid "Send" +msgstr "" + +#: views.py:81 +#, python-format +msgid "Email document: %s" +msgstr "" + +#: views.py:83 +#, python-format +msgid "Email link for document: %s" +msgstr "" + +#: views.py:86 +#, python-format +msgid "Email documents: %s" +msgstr "" + +#: views.py:88 +#, python-format +msgid "Email links for documents: %s" +msgstr "" diff --git a/mayan/apps/mailer/models.py b/mayan/apps/mailer/models.py new file mode 100644 index 0000000000..71a8362390 --- /dev/null +++ b/mayan/apps/mailer/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/mayan/apps/mailer/permissions.py b/mayan/apps/mailer/permissions.py new file mode 100644 index 0000000000..a318bd7085 --- /dev/null +++ b/mayan/apps/mailer/permissions.py @@ -0,0 +1,10 @@ +from __future__ import absolute_import + +from django.utils.translation import ugettext_lazy as _ + +from permissions.models import Permission, PermissionNamespace + +mailer_namespace = PermissionNamespace('mailing', _(u'Mailing')) + +PERMISSION_MAILING_LINK = Permission.objects.register(mailer_namespace, 'mail_link', _(u'Send document link via email')) +PERMISSION_MAILING_SEND_DOCUMENT = Permission.objects.register(mailer_namespace, 'mail_document', _(u'Send document via email')) diff --git a/mayan/apps/mailer/settings.py b/mayan/apps/mailer/settings.py new file mode 100644 index 0000000000..e1e58936ed --- /dev/null +++ b/mayan/apps/mailer/settings.py @@ -0,0 +1,16 @@ +"""Configuration options for the mailer app""" + +from django.utils.translation import ugettext_lazy as _ + +from smart_settings.api import register_settings + +register_settings( + namespace='mailer', + module='mailer.settings', + settings=[ + {'name': 'LINK_SUBJECT_TEMPLATE', 'global_name': 'MAILER_LINK_SUBJECT_TEMPLATE', 'default': _('Link for document: {{ document }}'), 'description': _('Template for the document link email form subject line.')}, + {'name': 'LINK_BODY_TEMPLATE', 'global_name': 'MAILER_LINK_BODY_TEMPLATE', 'default': _(u'To access this document click on the following link: {{ link }}

\n\n--------
\nThis email has been sent from Mayan EDMS (http://www.mayan-edms.com)'), 'description': _(u'Template for the document link email form body line.')}, + {'name': 'DOCUMENT_SUBJECT_TEMPLATE', 'global_name': 'MAILER_DOCUMENT_SUBJECT_TEMPLATE', 'default': _(u'Document: {{ document }}'), 'description': _(u'Template for the document email form subject line.')}, + {'name': 'DOCUMENT_BODY_TEMPLATE', 'global_name': 'MAILER_DOCUMENT_BODY_TEMPLATE', 'default': _(u'Attached to this email is the document: {{ document }}

\n\n--------
\nThis email has been sent from Mayan EDMS (http://www.mayan-edms.com)'), 'description': _(u'Template for the document email form body line.')}, + ] +) diff --git a/mayan/apps/mailer/tasks.py b/mayan/apps/mailer/tasks.py new file mode 100644 index 0000000000..42fbd75a13 --- /dev/null +++ b/mayan/apps/mailer/tasks.py @@ -0,0 +1,20 @@ +from __future__ import absolute_import + +from django.core.mail import EmailMultiAlternatives + +from documents.models import Document +from mayan.celery import app + + +@app.task +def task_send_document(subject_text, body_text_content, sender, recipient, document_ids=None): + email_msg = EmailMultiAlternatives(subject_text, body_text_content, sender, [recipient]) + + if document_ids: + documents = [Document.objects.get(pk=document_id) for document_id in document_ids] + for document in documents: + descriptor = document.open() + email_msg.attach(document.filename, descriptor.read(), document.file_mimetype) + descriptor.close() + + email_msg.send() diff --git a/mayan/apps/mailer/urls.py b/mayan/apps/mailer/urls.py new file mode 100644 index 0000000000..f880bd7fd9 --- /dev/null +++ b/mayan/apps/mailer/urls.py @@ -0,0 +1,6 @@ +from django.conf.urls import patterns, url + +urlpatterns = patterns('mailer.views', + url(r'^(?P\d+)/send/link/$', 'send_document_link', (), 'send_document_link'), + url(r'^(?P\d+)/send/document/$', 'send_document_link', {'as_attachment': True}, 'send_document'), +) diff --git a/mayan/apps/mailer/views.py b/mayan/apps/mailer/views.py new file mode 100644 index 0000000000..c021ab8d58 --- /dev/null +++ b/mayan/apps/mailer/views.py @@ -0,0 +1,91 @@ +from __future__ import absolute_import + +from django.contrib import messages +from django.contrib.sites.models import Site +from django.core.exceptions import PermissionDenied +from django.core.mail import EmailMultiAlternatives +from django.core.urlresolvers import reverse +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render_to_response +from django.template import Context, RequestContext, Template +from django.utils.html import strip_tags +from django.utils.translation import ugettext_lazy as _ + +from acls.models import AccessEntry +from documents.models import Document, RecentDocument +from permissions.models import Permission + +from .forms import DocumentMailForm +from .permissions import (PERMISSION_MAILING_LINK, + PERMISSION_MAILING_SEND_DOCUMENT) +from .tasks import task_send_document + + +def send_document_link(request, document_id=None, document_id_list=None, as_attachment=False): + if document_id: + documents = [get_object_or_404(Document, pk=document_id)] + elif document_id_list: + documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')] + + if as_attachment: + permission = PERMISSION_MAILING_SEND_DOCUMENT + else: + permission = PERMISSION_MAILING_LINK + + try: + Permission.objects.check_permissions(request.user, [permission]) + except PermissionDenied: + documents = AccessEntry.objects.filter_objects_by_access(permission, request.user, documents) + + if not documents: + messages.error(request, _('Must provide at least one document.')) + return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('main:home'))) + + post_action_redirect = reverse('documents:document_list_recent') + + next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', post_action_redirect))) + + for document in documents: + RecentDocument.objects.add_document_for_user(request.user, document) + + if request.method == 'POST': + form = DocumentMailForm(request.POST, as_attachment=as_attachment) + if form.is_valid(): + context = Context({ + 'link': 'http://%s%s' % (Site.objects.get_current().domain, reverse('documents:document_view_simple', args=[document.pk])), + 'document': document + }) + 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)) + + task_send_document.apply_async(args=(subject_text, body_text_content, request.user.email, form.cleaned_data['email']), kwargs={'document_ids': [document.pk for document in documents]}, queue='mailing') + messages.success(request, _('Successfully queued for delivery via email.')) + + return HttpResponseRedirect(next) + else: + form = DocumentMailForm(as_attachment=as_attachment) + + context = { + 'form': form, + 'next': next, + 'submit_label': _('Send'), + 'submit_icon_famfam': 'email_go' + } + if len(documents) == 1: + context['object'] = documents[0] + if as_attachment: + context['title'] = _('Email document: %s') % ', '.join([unicode(d) for d in documents]) + else: + context['title'] = _('Email link for document: %s') % ', '.join([unicode(d) for d in documents]) + elif len(documents) > 1: + if as_attachment: + context['title'] = _('Email documents: %s') % ', '.join([unicode(d) for d in documents]) + else: + context['title'] = _('Email links for documents: %s') % ', '.join([unicode(d) for d in documents]) + + return render_to_response('main/generic_form.html', context, + context_instance=RequestContext(request)) diff --git a/mayan/settings/base.py b/mayan/settings/base.py index 9ff4b4966c..b6fac767f8 100644 --- a/mayan/settings/base.py +++ b/mayan/settings/base.py @@ -95,6 +95,7 @@ INSTALLED_APPS = ( 'document_signatures', 'checkouts', 'bootstrap', + 'mailer', 'registration', ) diff --git a/mayan/urls.py b/mayan/urls.py index 2f1390bca5..982073893e 100644 --- a/mayan/urls.py +++ b/mayan/urls.py @@ -37,6 +37,7 @@ urlpatterns = patterns('', (r'^bootstrap/', include('bootstrap.urls', namespace='bootstrap')), (r'^registration/', include('registration.urls', namespace='registration')), (r'^statistics/', include('statistics.urls', namespace='statistics')), + (r'^mailer/', include('mailer.urls', namespace='mailer')), )