Skip to content

Commit 947c82c

Browse files
citos88Łukasz Sitko
andauthored
additional fields in email attachment & black update (#36)
* additional fields in email attachment & black update * tests Co-authored-by: Łukasz Sitko <[email protected]>
1 parent fb3bfec commit 947c82c

30 files changed

+1039
-423
lines changed

README.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ Assumptions
1616
Changelog
1717
=========
1818

19+
1.1.14
20+
------
21+
* Additional fields for email attachment - https://github.com/deployed/django-emailtemplates/pull/36
22+
1923
1.1.13
2024
------
2125
* Change default auto field to BigAutoField - https://github.com/deployed/django-emailtemplates/pull/35

emailtemplates/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
default_app_config = 'emailtemplates.apps.EmailtempatesConfig'
1+
default_app_config = "emailtemplates.apps.EmailtempatesConfig"
22

3-
VERSION = (1, 1, 13)
3+
VERSION = (1, 1, 14)
44

55
# Dynamically calculate the version based on VERSION tuple
66
if len(VERSION) > 2 and VERSION[2] is not None:

emailtemplates/admin.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55
from django.utils.translation import gettext_lazy as _
66

77
from .forms import EmailTemplateAdminForm, MassEmailMessageForm, MassEmailAttachmentForm
8-
from .models import EmailTemplate, MassEmailMessage, MassEmailAttachment, EmailAttachment
8+
from .models import (
9+
EmailTemplate,
10+
MassEmailMessage,
11+
MassEmailAttachment,
12+
EmailAttachment,
13+
)
914

1015

1116
class EmailTemplateAttachmentInline(admin.TabularInline):
@@ -19,33 +24,42 @@ class EmailTemplateAdmin(admin.ModelAdmin):
1924
"""
2025
Admin view of EmailTemplate
2126
"""
22-
list_display = ('title', 'language', 'subject',)
23-
list_display_links = ('title',)
24-
list_filter = ('title', 'language',)
25-
search_fields = ('title', 'subject')
27+
28+
list_display = (
29+
"title",
30+
"language",
31+
"subject",
32+
)
33+
list_display_links = ("title",)
34+
list_filter = (
35+
"title",
36+
"language",
37+
)
38+
search_fields = ("title", "subject")
2639
form = EmailTemplateAdminForm
2740
save_on_top = True
2841
save_as = True
29-
readonly_fields = ['show_links', 'created', 'modified']
42+
readonly_fields = ["show_links", "created", "modified"]
3043
inlines = [EmailTemplateAttachmentInline]
3144

3245
def show_links(self, obj):
3346
if not obj.pk:
34-
return ''
35-
return mark_safe(u'<a href="%s" target="_blank">%s</a>' % (
36-
reverse('email_preview', kwargs={'pk': obj.pk}), _('Show email preview')
37-
))
47+
return ""
48+
return mark_safe(
49+
'<a href="%s" target="_blank">%s</a>'
50+
% (reverse("email_preview", kwargs={"pk": obj.pk}), _("Show email preview"))
51+
)
3852

3953
show_links.allow_tags = True
40-
show_links.short_description = _('Actions')
54+
show_links.short_description = _("Actions")
4155

4256

4357
admin.site.register(EmailTemplate, EmailTemplateAdmin)
4458

4559

4660
class EmailAttachmentAdmin(admin.ModelAdmin):
47-
list_display = ["name"]
48-
search_fields = ["name"]
61+
list_display = ["name", "comment", "ordering"]
62+
search_fields = ["name", "comment"]
4963

5064

5165
admin.site.register(EmailAttachment, EmailAttachmentAdmin)
@@ -57,8 +71,8 @@ class MassEmailAttachmentInline(admin.TabularInline):
5771

5872

5973
class MassEmailMessageAdmin(admin.ModelAdmin):
60-
list_display = ('subject', 'date_sent')
61-
readonly_fields = ['date_sent']
74+
list_display = ("subject", "date_sent")
75+
readonly_fields = ["date_sent"]
6276
form = MassEmailMessageForm
6377
inlines = [MassEmailAttachmentInline]
6478

emailtemplates/apps.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55

66
class EmailtempatesConfig(AppConfig):
7-
name = 'emailtemplates'
8-
verbose_name = _('E-MAIL TEMPLATES')
9-
default_auto_field = 'django.db.models.BigAutoField'
7+
name = "emailtemplates"
8+
verbose_name = _("E-MAIL TEMPLATES")
9+
default_auto_field = "django.db.models.BigAutoField"

emailtemplates/email.py

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# coding=utf-8
22
import logging
33
import os
4+
import re
45
from smtplib import SMTPException
6+
from urllib.parse import urljoin
57

68
from django.conf import settings
79
from django.core.exceptions import ObjectDoesNotExist
@@ -11,8 +13,6 @@
1113

1214
from .models import now, EmailTemplate
1315
from .registry import email_templates
14-
import re
15-
from urllib.parse import urljoin
1616

1717
logger = logging.getLogger(__name__)
1818

@@ -28,9 +28,17 @@ class EmailFromTemplate(object):
2828
Site Admins should be familiar with Django Template System.
2929
"""
3030

31-
def __init__(self, name="", from_email=settings.DEFAULT_FROM_EMAIL, base_url="",
32-
language=settings.LANGUAGE_CODE, subject="", template_class=EmailTemplate,
33-
registry_validation=True, template_object=None):
31+
def __init__(
32+
self,
33+
name="",
34+
from_email=settings.DEFAULT_FROM_EMAIL,
35+
base_url="",
36+
language=settings.LANGUAGE_CODE,
37+
subject="",
38+
template_class=EmailTemplate,
39+
registry_validation=True,
40+
template_object=None,
41+
):
3442
"""
3543
Class constructor
3644
@@ -55,18 +63,18 @@ def __init__(self, name="", from_email=settings.DEFAULT_FROM_EMAIL, base_url="",
5563

5664
self.template = None
5765
self.compiled_template = None # for storing compiled template
58-
self.context = {'date': now()} # default context
66+
self.context = {"date": now()} # default context
5967
self.sent = 0 # number of messages sent
6068
self.message = ""
61-
self.content_subtype = 'html'
62-
self._template_source = 'default'
69+
self.content_subtype = "html"
70+
self._template_source = "default"
6371

6472
@property
6573
def template_source(self):
6674
"""Source of the template. One of the following:
67-
* default
68-
* filesystem
69-
* database
75+
* default
76+
* filesystem
77+
* database
7078
"""
7179
return self._template_source
7280

@@ -78,9 +86,12 @@ def __get_template_from_file(self):
7886
try:
7987
self.compiled_template = get_template(path)
8088
except (TemplateDoesNotExist, IOError):
81-
logger.warning("Can't find %s template in the filesystem, will use very default one.", path)
89+
logger.warning(
90+
"Can't find %s template in the filesystem, will use very default one.",
91+
path,
92+
)
8293
else:
83-
self._template_source = 'filesystem'
94+
self._template_source = "filesystem"
8495

8596
def build_absolute_uri(self, url: str):
8697
"""
@@ -106,17 +117,20 @@ def get_object(self):
106117
try:
107118
tmp = self.get_template_object()
108119
except ObjectDoesNotExist:
109-
logger.warning("Can't find EmailTemplate object in database, using default file template.")
120+
logger.warning(
121+
"Can't find EmailTemplate object in database, using default file template."
122+
)
110123
break
111124
except UnicodeError:
112125
logger.warning(
113-
"Can't convert to unicode EmailTemplate object from database, using default file template.")
126+
"Can't convert to unicode EmailTemplate object from database, using default file template."
127+
)
114128
break
115129
else:
116130
self.template = str(tmp.content)
117131
self.subject = self.get_subject(tmp)
118-
self._template_source = 'database'
119-
logger.debug(u"Got template %s from database", self.name)
132+
self._template_source = "database"
133+
logger.debug("Got template %s from database", self.name)
120134
return
121135
# fallback
122136
self.__get_template_from_file()
@@ -126,9 +140,9 @@ def __compile_template(self):
126140
self.compiled_template = Template(self.template)
127141

128142
def get_context(self):
129-
self.context.update({
130-
"default_attachments": self.get_default_attachments(as_links=True)
131-
})
143+
self.context.update(
144+
{"default_attachments": self.get_default_attachments(as_links=True)}
145+
)
132146
return self.context
133147

134148
def render_message(self):
@@ -141,26 +155,30 @@ def render_message(self):
141155
self.message = message
142156

143157
def get_message_object(self, send_to, attachment_paths, *args, **kwargs):
144-
if kwargs.get('reply_to') is None:
145-
defaut_reply_to_email = getattr(settings, 'DEFAULT_REPLY_TO_EMAIL', None)
158+
if kwargs.get("reply_to") is None:
159+
defaut_reply_to_email = getattr(settings, "DEFAULT_REPLY_TO_EMAIL", None)
146160
if defaut_reply_to_email:
147-
kwargs['reply_to'] = [defaut_reply_to_email]
161+
kwargs["reply_to"] = [defaut_reply_to_email]
148162

149-
msg = EmailMessage(self.subject, self.message, self.from_email, send_to, *args, **kwargs)
163+
msg = EmailMessage(
164+
self.subject, self.message, self.from_email, send_to, *args, **kwargs
165+
)
150166
if attachment_paths:
151167
for path in attachment_paths:
152168
msg.attach_file(path)
153169
return msg
154170

155-
def send_email(self, send_to, attachment_paths=None, fail_silently=True, *args, **kwargs):
171+
def send_email(
172+
self, send_to, attachment_paths=None, fail_silently=True, *args, **kwargs
173+
):
156174
"""
157175
Sends email to recipient based on self object parameters.
158176
159177
@param fail_silently: When it’s False, msg.send() will raise an smtplib.SMTPException if an error occurs.
160178
@param send_to: recipient email
161179
@param args: additional args passed to EmailMessage
162180
@param kwargs: kwargs passed to EmailMessage
163-
@param attachment_paths: paths to attachments as received by django EmailMessage.attach_file(path) method
181+
@param attachment_paths: paths to attachments as received by django EmailMessage.attach_file(path) method
164182
@return: number of sent messages
165183
"""
166184
msg = self.get_message_object(send_to, attachment_paths, *args, **kwargs)
@@ -171,7 +189,7 @@ def send_email(self, send_to, attachment_paths=None, fail_silently=True, *args,
171189
except SMTPException as e:
172190
if not fail_silently:
173191
raise
174-
logger.error(u'Problem sending email to %s: %s', send_to, e)
192+
logger.error("Problem sending email to %s: %s", send_to, e)
175193

176194
return self.sent
177195

@@ -188,29 +206,35 @@ def get_default_attachments(self, as_links=False):
188206
for attachment in tmp.attachments.filter(send_as_link=as_links):
189207
if as_links:
190208
attachments.append(
191-
(attachment.get_name(), self.build_absolute_uri(attachment.attachment_file.url))
209+
(
210+
attachment.get_name(),
211+
self.build_absolute_uri(attachment.attachment_file.url),
212+
)
192213
)
193214
else:
194215
attachments.append(
195-
(os.path.basename(attachment.attachment_file.name), attachment.attachment_file.read())
216+
(
217+
os.path.basename(attachment.attachment_file.name),
218+
attachment.attachment_file.read(),
219+
)
196220
)
197221
return attachments
198222

199223
def send(self, to, attachment_paths=None, *args, **kwargs):
200224
"""This function does all the operations on eft object, that are necessary to send email.
201-
Usually one would use eft object like this:
202-
eft = EmailFromTemplate(name='sth/sth.html')
203-
eft.get_object()
204-
eft.render_message()
205-
eft.send_email(['[email protected]'])
206-
return eft.sent
225+
Usually one would use eft object like this:
226+
eft = EmailFromTemplate(name='sth/sth.html')
227+
eft.get_object()
228+
eft.render_message()
229+
eft.send_email(['[email protected]'])
230+
return eft.sent
207231
"""
208232
attachments = self.get_default_attachments(as_links=False)
209-
attachments.extend(kwargs.pop('attachments', []))
233+
attachments.extend(kwargs.pop("attachments", []))
210234

211235
self.get_object()
212236
self.render_message()
213237
self.send_email(to, attachment_paths, attachments=attachments, *args, **kwargs)
214238
if self.sent:
215-
logger.info(u"Mail has been sent to: %s ", to)
239+
logger.info("Mail has been sent to: %s ", to)
216240
return self.sent

emailtemplates/forms.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,49 +16,55 @@
1616

1717

1818
class EmailTemplateAdminForm(forms.ModelForm):
19-
title = forms.ChoiceField(choices=lazy(email_templates.email_template_choices, list), label=_("template"))
19+
title = forms.ChoiceField(
20+
choices=lazy(email_templates.email_template_choices, list), label=_("template")
21+
)
2022

2123
class Meta:
2224
model = EmailTemplate
2325
fields = [
24-
'title',
25-
'subject',
26-
'content',
27-
'language',
28-
'created',
29-
'modified',
26+
"title",
27+
"subject",
28+
"content",
29+
"language",
30+
"created",
31+
"modified",
3032
]
3133

3234
def __init__(self, *args, **kwargs):
3335
super(EmailTemplateAdminForm, self).__init__(*args, **kwargs)
34-
self.fields['title'].help_text = mark_safe(email_templates.get_form_help_text(self.initial.get('title')))
36+
self.fields["title"].help_text = mark_safe(
37+
email_templates.get_form_help_text(self.initial.get("title"))
38+
)
3539
if self.instance.pk:
36-
self.fields['title'].widget = forms.TextInput(attrs={'readonly': 'readonly', 'style': 'width:480px'})
40+
self.fields["title"].widget = forms.TextInput(
41+
attrs={"readonly": "readonly", "style": "width:480px"}
42+
)
3743
else:
38-
self.fields['content'].widget = forms.HiddenInput()
39-
self.fields['content'].required = False
40-
self.fields['subject'].widget = forms.HiddenInput()
44+
self.fields["content"].widget = forms.HiddenInput()
45+
self.fields["content"].required = False
46+
self.fields["subject"].widget = forms.HiddenInput()
4147

4248
def clean_content(self):
43-
content = self.cleaned_data['content']
49+
content = self.cleaned_data["content"]
4450
try:
4551
Template(content)
4652
except TemplateSyntaxError as e:
47-
raise ValidationError(u"Syntax error in custom email template: %s" % e)
53+
raise ValidationError("Syntax error in custom email template: %s" % e)
4854
return content
4955

5056

5157
class MassEmailAttachmentForm(forms.ModelForm):
5258
class Meta:
5359
model = MassEmailAttachment
54-
fields = ['attachment_file']
60+
fields = ["attachment_file"]
5561

5662

5763
class MassEmailMessageForm(forms.ModelForm):
5864
class Meta:
5965
model = MassEmailMessage
6066
fields = [
61-
'subject',
62-
'content',
63-
'date_sent',
67+
"subject",
68+
"content",
69+
"date_sent",
6470
]

0 commit comments

Comments
 (0)