wbmailing 2.2.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wbmailing might be problematic. Click here for more details.

Files changed (57) hide show
  1. wbmailing/__init__.py +1 -0
  2. wbmailing/admin.py +74 -0
  3. wbmailing/apps.py +14 -0
  4. wbmailing/backend.py +131 -0
  5. wbmailing/celery.py +0 -0
  6. wbmailing/dynamic_preferences_registry.py +35 -0
  7. wbmailing/factories.py +211 -0
  8. wbmailing/filters/__init__.py +8 -0
  9. wbmailing/filters/mailing_lists.py +84 -0
  10. wbmailing/filters/mails.py +74 -0
  11. wbmailing/management/__init__.py +22 -0
  12. wbmailing/migrations/0001_initial_squashed_squashed_0008_alter_mail_bcc_email_alter_mail_cc_email_and_more.py +649 -0
  13. wbmailing/migrations/0002_delete_mailingsettings.py +16 -0
  14. wbmailing/migrations/0003_alter_mailinglistsubscriberchangerequest_options.py +25 -0
  15. wbmailing/migrations/__init__.py +0 -0
  16. wbmailing/models/__init__.py +6 -0
  17. wbmailing/models/mailing_lists.py +386 -0
  18. wbmailing/models/mails.py +895 -0
  19. wbmailing/serializers/__init__.py +19 -0
  20. wbmailing/serializers/mailing_lists.py +209 -0
  21. wbmailing/serializers/mails.py +251 -0
  22. wbmailing/tasks.py +37 -0
  23. wbmailing/templatetags/__init__.py +0 -0
  24. wbmailing/templatetags/mailing_tags.py +22 -0
  25. wbmailing/tests/__init__.py +0 -0
  26. wbmailing/tests/conftest.py +30 -0
  27. wbmailing/tests/models/__init__.py +0 -0
  28. wbmailing/tests/models/test_mailing_lists.py +297 -0
  29. wbmailing/tests/models/test_mails.py +205 -0
  30. wbmailing/tests/signals.py +124 -0
  31. wbmailing/tests/test_serializers.py +28 -0
  32. wbmailing/tests/test_tasks.py +49 -0
  33. wbmailing/tests/test_viewsets.py +216 -0
  34. wbmailing/tests/tests.py +142 -0
  35. wbmailing/urls.py +90 -0
  36. wbmailing/viewsets/__init__.py +32 -0
  37. wbmailing/viewsets/analytics.py +110 -0
  38. wbmailing/viewsets/buttons/__init__.py +10 -0
  39. wbmailing/viewsets/buttons/mailing_lists.py +91 -0
  40. wbmailing/viewsets/buttons/mails.py +98 -0
  41. wbmailing/viewsets/display/__init__.py +16 -0
  42. wbmailing/viewsets/display/mailing_lists.py +175 -0
  43. wbmailing/viewsets/display/mails.py +318 -0
  44. wbmailing/viewsets/endpoints/__init__.py +8 -0
  45. wbmailing/viewsets/endpoints/mailing_lists.py +86 -0
  46. wbmailing/viewsets/endpoints/mails.py +51 -0
  47. wbmailing/viewsets/mailing_lists.py +320 -0
  48. wbmailing/viewsets/mails.py +425 -0
  49. wbmailing/viewsets/menu/__init__.py +5 -0
  50. wbmailing/viewsets/menu/mailing_lists.py +37 -0
  51. wbmailing/viewsets/menu/mails.py +25 -0
  52. wbmailing/viewsets/titles/__init__.py +17 -0
  53. wbmailing/viewsets/titles/mailing_lists.py +63 -0
  54. wbmailing/viewsets/titles/mails.py +55 -0
  55. wbmailing-2.2.1.dist-info/METADATA +5 -0
  56. wbmailing-2.2.1.dist-info/RECORD +57 -0
  57. wbmailing-2.2.1.dist-info/WHEEL +5 -0
@@ -0,0 +1,425 @@
1
+ import pandas as pd
2
+ import plotly.graph_objects as go
3
+ from django.contrib.messages import info
4
+ from django.db.models import CharField, Count, OuterRef, Q, Subquery, Value
5
+ from django.db.models.functions import Coalesce
6
+ from django.shortcuts import get_object_or_404
7
+ from django.utils.functional import cached_property
8
+ from django.utils.translation import gettext
9
+ from rest_framework import filters, status
10
+ from rest_framework.decorators import action
11
+ from rest_framework.response import Response
12
+ from wbcore import viewsets
13
+ from wbcore.contrib.directory.models import EmailContact
14
+ from wbcore.filters import DjangoFilterBackend
15
+ from wbcore.utils.strings import format_number
16
+ from wbmailing import models, serializers
17
+ from wbmailing.filters import MailFilter, MailStatusMassMailFilterSet, MassMailFilterSet
18
+ from wbmailing.models import MailEvent
19
+ from wbmailing.viewsets.buttons import (
20
+ MailButtonConfig,
21
+ MailStatusMassMailButtonConfig,
22
+ MassMailButtonConfig,
23
+ )
24
+ from wbmailing.viewsets.display import (
25
+ MailDisplayConfig,
26
+ MailEventDisplayConfig,
27
+ MailStatusMassMailDisplayConfig,
28
+ MailTemplateDisplayConfig,
29
+ MassMailDisplayConfig,
30
+ )
31
+ from wbmailing.viewsets.endpoints import (
32
+ MailEventMailEndpointConfig,
33
+ MailEventMassMailEndpointConfig,
34
+ MailMailingListChartEndpointConfig,
35
+ MailStatusMassMailEndpointConfig,
36
+ )
37
+ from wbmailing.viewsets.titles import (
38
+ MailEventMailTitleConfig,
39
+ MailEventMassMailTitleConfig,
40
+ MailMailingListChartTitleConfig,
41
+ MailStatusMassMailTitleConfig,
42
+ MailTemplateTitleConfig,
43
+ MailTitleConfig,
44
+ MassMailTitleConfig,
45
+ )
46
+
47
+
48
+ class MailTemplateRepresentationViewSet(viewsets.RepresentationViewSet):
49
+ IDENTIFIER = "wbmailing:mailtemplate"
50
+
51
+ filter_backends = (
52
+ filters.OrderingFilter,
53
+ filters.SearchFilter,
54
+ )
55
+ ordering_fields = ordering = ("title",)
56
+ search_fields = ("title",)
57
+
58
+ queryset = models.MailTemplate.objects.all()
59
+ serializer_class = serializers.MailTemplateRepresentationSerializer
60
+
61
+
62
+ class MailRepresentationViewSet(viewsets.RepresentationViewSet):
63
+ IDENTIFIER = "wbmailing:mail"
64
+ queryset = models.Mail.objects.all()
65
+ serializer_class = serializers.MailRepresentationSerializer
66
+
67
+
68
+ class MassMailRepresentationViewSet(viewsets.RepresentationViewSet):
69
+ IDENTIFIER = "wbmailing:massmail"
70
+
71
+ filter_backends = (
72
+ filters.OrderingFilter,
73
+ filters.SearchFilter,
74
+ )
75
+ ordering_fields = ("subject",)
76
+ search_fields = ("subject",)
77
+ queryset = models.MassMail.objects.all()
78
+ serializer_class = serializers.MassMailRepresentationSerializer
79
+
80
+
81
+ class MailMailingListChartViewSet(viewsets.ChartViewSet):
82
+ IDENTIFIER = "mailing:maileventchart"
83
+
84
+ queryset = models.Mail.objects.all()
85
+
86
+ title_config_class = MailMailingListChartTitleConfig
87
+ endpoint_config_class = MailMailingListChartEndpointConfig
88
+
89
+ def get_plotly(self, queryset):
90
+ mass_mail_name_map = dict(models.MassMail.objects.values_list("id", "subject"))
91
+ fig = go.Figure()
92
+ if queryset.exists():
93
+ df = pd.DataFrame(queryset.values("mass_mail", "CLICKED", "DELIVERED", "OPENED"))
94
+ df["TOTAL"] = 1
95
+ df = df.groupby("mass_mail").sum()
96
+ total = df["TOTAL"]
97
+ del df["TOTAL"]
98
+ df["FAILED"] = total - df["DELIVERED"]
99
+ df.index.name = None
100
+ df = df.divide(total.values, axis=0)
101
+ df["title"] = df.index
102
+ df.title = df.title.map(mass_mail_name_map)
103
+ df.index = range(df.shape[0])
104
+ for col in df.columns:
105
+ if col != "title":
106
+ fig.add_trace(
107
+ go.Scatter(
108
+ x=df.index,
109
+ y=df[col],
110
+ mode="lines",
111
+ name=str(models.MailEvent.EventType[col].label),
112
+ marker_color=models.MailEvent.EventType.get_color(col),
113
+ )
114
+ )
115
+ fig.update_layout(
116
+ xaxis=dict(tickmode="array", tickvals=df.index, ticktext=df.title), yaxis=dict(tickformat=".1%")
117
+ )
118
+ return fig
119
+
120
+ def get_queryset(self):
121
+ return models.Mail.objects.filter(
122
+ mass_mail__isnull=False, mass_mail__mailing_lists=self.kwargs["mailing_list_id"]
123
+ ).annotate(
124
+ CLICKED=Coalesce(
125
+ Subquery(
126
+ MailEvent.objects.filter(mail=OuterRef("pk"), event_type=MailEvent.EventType.CLICKED)
127
+ .annotate(c=Count("event_type"))
128
+ .values("c")[:1]
129
+ ),
130
+ 0,
131
+ ),
132
+ OPENED=Coalesce(
133
+ Subquery(
134
+ MailEvent.objects.filter(mail=OuterRef("pk"), event_type=MailEvent.EventType.OPENED)
135
+ .annotate(c=Count("event_type"))
136
+ .values("c")[:1]
137
+ ),
138
+ 0,
139
+ ),
140
+ DELIVERED=Coalesce(
141
+ Subquery(
142
+ MailEvent.objects.filter(mail=OuterRef("pk"), event_type=MailEvent.EventType.DELIVERED)
143
+ .annotate(c=Count("event_type"))
144
+ .values("c")[:1]
145
+ ),
146
+ 0,
147
+ ),
148
+ )
149
+
150
+
151
+ class MassMailModelViewSet(viewsets.ModelViewSet):
152
+ queryset = models.MassMail.objects.select_related("creator", "template").prefetch_related(
153
+ "mailing_lists",
154
+ "excluded_mailing_lists",
155
+ )
156
+
157
+ filterset_class = MassMailFilterSet
158
+ ordering_fields = (
159
+ "created",
160
+ "subject",
161
+ "from_email",
162
+ "template__title",
163
+ "creator__computed_str",
164
+ "sent",
165
+ "opened",
166
+ )
167
+ ordering = ("-created",)
168
+ search_fields = ("subject",)
169
+
170
+ display_config_class = MassMailDisplayConfig
171
+ title_config_class = MassMailTitleConfig
172
+ button_config_class = MassMailButtonConfig
173
+
174
+ def get_serializer_class(self):
175
+ if getattr(self, "action", None) == "list":
176
+ return serializers.MassMailListSerializer
177
+ return serializers.MassMailModelSerializer
178
+
179
+ @action(methods=["GET", "PATCH"], detail=True)
180
+ def sendtestmail(self, request, pk=None):
181
+ mass_mail = self.get_object()
182
+ email = request.POST.get("to_test_email", request.user.email)
183
+
184
+ mass_mail.send_test_mail(email)
185
+
186
+ return Response({"__notification": {"title": gettext("Mail sent.")}}, status=status.HTTP_200_OK)
187
+
188
+
189
+ class MailModelViewSet(viewsets.ModelViewSet):
190
+ queryset = models.Mail.objects.select_related(
191
+ "mass_mail",
192
+ "template",
193
+ ).prefetch_related(
194
+ "to_email",
195
+ "cc_email",
196
+ "bcc_email",
197
+ )
198
+ serializer_class = serializers.MailModelSerializer
199
+ filterset_class = MailFilter
200
+
201
+ ordering_fields = ("created", "subject", "mass_mail__subject", "from_email", "last_send")
202
+ ordering = "-last_send"
203
+ search_fields = ("subject", "from_email", "mass_mail__subject", "to_email__address")
204
+
205
+ display_config_class = MailDisplayConfig
206
+ title_config_class = MailTitleConfig
207
+ button_config_class = MailButtonConfig
208
+
209
+ def get_queryset(self):
210
+ user = self.request.user
211
+ emails = user.profile.emails.values("address")
212
+ qs = super().get_queryset()
213
+ if not user.has_perm("wbmailing:view_all_mails") and not user.is_superuser:
214
+ qs = qs.annotate(
215
+ is_in_charge_to_email=Coalesce(
216
+ Subquery(
217
+ EmailContact.objects.filter(mail_to=OuterRef("pk"))
218
+ .filter(Q(entry__relationship_managers=user.profile) | Q(address__in=emails))
219
+ .values("mail_to")
220
+ .annotate(number_of_charges=Count("*"))
221
+ .values("number_of_charges")[:1]
222
+ ),
223
+ 0,
224
+ ),
225
+ is_in_charge_cc_email=Coalesce(
226
+ Subquery(
227
+ EmailContact.objects.filter(mail_cc=OuterRef("pk"))
228
+ .filter(Q(entry__relationship_managers=user.profile) | Q(address__in=emails))
229
+ .values("mail_cc")
230
+ .annotate(number_of_charges=Count("*"))
231
+ .values("number_of_charges")[:1]
232
+ ),
233
+ 0,
234
+ ),
235
+ is_in_charge_bcc_email=Coalesce(
236
+ Subquery(
237
+ EmailContact.objects.filter(mail_bcc=OuterRef("pk"))
238
+ .filter(Q(entry__relationship_managers=user.profile) | Q(address__in=emails))
239
+ .values("mail_bcc")
240
+ .annotate(number_of_charges=Count("*"))
241
+ .values("number_of_charges")[:1]
242
+ ),
243
+ 0,
244
+ ),
245
+ ).filter(
246
+ Q(is_in_charge_to_email__gt=0)
247
+ | Q(is_in_charge_cc_email__gt=0)
248
+ | Q(is_in_charge_bcc_email__gt=0)
249
+ | Q(mass_mail__isnull=False)
250
+ )
251
+ return self.annotate(qs)
252
+
253
+ @action(methods=["GET", "PATCH"], detail=True)
254
+ def resend(self, request, pk=None):
255
+ mail = self.get_object()
256
+ mail.resend()
257
+ return Response({"__notification": {"title": gettext("Mail sent.")}}, status=status.HTTP_200_OK)
258
+
259
+ @classmethod
260
+ def annotate(cls, qs):
261
+ return qs.annotate(
262
+ status=Coalesce(
263
+ Subquery(
264
+ models.MailEvent.objects.filter(mail=OuterRef("pk"))
265
+ .order_by("-timestamp")
266
+ .values("event_type")[:1]
267
+ ),
268
+ None,
269
+ )
270
+ )
271
+
272
+
273
+ class MailStatusMassMailModelViewSet(viewsets.ModelViewSet):
274
+ IDENTIFIER = "wbmailing:massmail"
275
+
276
+ queryset = EmailContact.objects.select_related("entry")
277
+ serializer_class = serializers.MailStatusMassMailModelSerializer
278
+ filterset_class = MailStatusMassMailFilterSet
279
+
280
+ ordering_fields = ("address", "entry__computed_str")
281
+ ordering = ("address",)
282
+ search_fields = ("address", "entry__computed_str")
283
+
284
+ display_config_class = MailStatusMassMailDisplayConfig
285
+ title_config_class = MailStatusMassMailTitleConfig
286
+ endpoint_config_class = MailStatusMassMailEndpointConfig
287
+ button_config_class = MailStatusMassMailButtonConfig
288
+
289
+ def add_messages(
290
+ self,
291
+ request,
292
+ queryset=None,
293
+ paginated_queryset=None,
294
+ instance=None,
295
+ initial=False,
296
+ ):
297
+ df = pd.DataFrame(
298
+ MailEvent.objects.filter(mail__mass_mail=self.kwargs["mass_mail_id"]).values(
299
+ "event_type",
300
+ "recipient",
301
+ "timestamp",
302
+ ),
303
+ columns=["event_type", "recipient", "timestamp"],
304
+ )
305
+ df = df.sort_values(by="timestamp", ascending=False).groupby("recipient").first().reset_index()
306
+ total_mails = df.shape[0]
307
+ if not df.empty and total_mails:
308
+ nb_created = df[df["event_type"] == MailEvent.EventType.CREATED.value].shape[0]
309
+ nb_queued = df[df["event_type"] == MailEvent.EventType.QUEUED.value].shape[0]
310
+ nb_opened = df[df["event_type"] == MailEvent.EventType.OPENED.value].shape[0]
311
+ nb_clicked = df[df["event_type"] == MailEvent.EventType.CLICKED.value].shape[0]
312
+ nb_delivered = df[df["event_type"] == MailEvent.EventType.DELIVERED.value].shape[0]
313
+ nb_received = nb_opened + nb_delivered + nb_clicked
314
+ msg = f"""
315
+ <p> Total Sent: {total_mails}</p>
316
+ <p> Total Received: {format_number(nb_received / total_mails):.2%}</p>
317
+ <ul>
318
+ <li> Only Created: {format_number(nb_created / total_mails):.2%} </li>
319
+ <li> Only Queued: {format_number(nb_queued / total_mails):.2%} </li>
320
+ <li> Delivered: {format_number(nb_delivered / total_mails):.2%} </li>
321
+ <li> Opened: {format_number(nb_opened / total_mails):.2%} </li>
322
+ <li> Clicked: {format_number(nb_clicked / total_mails):.2%} </li>
323
+ <li> Not Received: {format_number(1 - nb_received / total_mails):.2%} </li>
324
+ </ul>
325
+ """
326
+ info(request, msg, extra_tags="auto_close=0")
327
+
328
+ @cached_property
329
+ def mass_mail(self):
330
+ return get_object_or_404(models.MassMail, id=self.kwargs["mass_mail_id"])
331
+
332
+ @cached_property
333
+ def included_mailing_list_ids(self):
334
+ return self.mass_mail.mailing_lists.values_list("id")
335
+
336
+ @cached_property
337
+ def excluded_mailing_list_ids(self):
338
+ return self.mass_mail.excluded_mailing_lists.values_list("id")
339
+
340
+ def get_queryset(self):
341
+ mass_mail = self.mass_mail
342
+ return (
343
+ models.MassMail.get_emails(self.included_mailing_list_ids, self.excluded_mailing_list_ids)
344
+ .annotate(
345
+ mail_id=Subquery(
346
+ models.Mail.objects.filter(mass_mail=mass_mail, to_email__id=OuterRef("id"))
347
+ .order_by("-created")
348
+ .values("id")[:1],
349
+ output_field=CharField(),
350
+ ),
351
+ status=Coalesce(
352
+ Subquery(
353
+ models.MailEvent.objects.filter(recipient=OuterRef("address"), mail__mass_mail=mass_mail)
354
+ .order_by("-timestamp")
355
+ .values("event_type")[:1]
356
+ ),
357
+ Value("NOT_SENT"),
358
+ ),
359
+ )
360
+ .select_related("entry")
361
+ )
362
+
363
+ @action(methods=["PATCH"], detail=False)
364
+ def resendbouncedmails(self, request, mass_mail_id=None):
365
+ mass_mail = models.MassMail.objects.get(id=mass_mail_id)
366
+ unsent_emails = MailModelViewSet.annotate(mass_mail.mails.all()).filter(
367
+ status__in=[
368
+ models.MailEvent.EventType.BOUNCED,
369
+ models.MailEvent.EventType.REJECTED,
370
+ models.MailEvent.EventType.DEFERRED,
371
+ models.MailEvent.EventType.UNKNOWN,
372
+ ]
373
+ )
374
+ for mail in unsent_emails.all():
375
+ mail.resend()
376
+ return Response(
377
+ {"__notification": {"title": gettext("Unsent emails resent with success")}}, status=status.HTTP_200_OK
378
+ )
379
+
380
+
381
+ class MailTemplateModelViewSet(viewsets.ModelViewSet):
382
+ IDENTIFIER = "wbmailing:mailtemplate"
383
+
384
+ queryset = models.MailTemplate.objects.all()
385
+ serializer_class = serializers.MailTemplateModelSerializer
386
+
387
+ display_config_class = MailTemplateDisplayConfig
388
+ title_config_class = MailTemplateTitleConfig
389
+
390
+
391
+ class MailEventModelViewSet(viewsets.ModelViewSet):
392
+ serializer_class = serializers.MailEventModelSerializer
393
+ filter_backends = (DjangoFilterBackend, filters.OrderingFilter)
394
+ queryset = MailEvent.objects.select_related("mail")
395
+
396
+ filterset_fields = {
397
+ "timestamp": ["gte", "exact", "lte"],
398
+ "event_type": ["exact"],
399
+ "reject_reason": ["exact"],
400
+ "recipient": ["exact"],
401
+ "click_url": ["exact", "icontains"],
402
+ "description": ["exact", "icontains"],
403
+ }
404
+
405
+ ordering_fields = ("timestamp",)
406
+ ordering = ("-timestamp",)
407
+ search_fields = ("description",)
408
+
409
+ display_config_class = MailEventDisplayConfig
410
+
411
+
412
+ class MailEventMailModelViewSet(MailEventModelViewSet):
413
+ endpoint_config_class = MailEventMailEndpointConfig
414
+ title_config_class = MailEventMailTitleConfig
415
+
416
+ def get_queryset(self):
417
+ return models.MailEvent.objects.filter(mail_id=self.kwargs["mail_id"])
418
+
419
+
420
+ class MailEventMassMailMailModelViewSet(MailEventModelViewSet):
421
+ title_config_class = MailEventMassMailTitleConfig
422
+ endpoint_config_class = MailEventMassMailEndpointConfig
423
+
424
+ def get_queryset(self):
425
+ return models.MailEvent.objects.filter(mail__mass_mail=self.kwargs["mass_mail_id"])
@@ -0,0 +1,5 @@
1
+ from .mailing_lists import (
2
+ MAILINGLIST_MENUITEM,
3
+ MAILINGLISTSUBSCRIPTIONCHANGEREQUEST_MENUITEM,
4
+ )
5
+ from .mails import MAIL_MENUITEM, MASSMAIL_MENUITEM
@@ -0,0 +1,37 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.menus import ItemPermission, MenuItem
3
+ from wbcore.permissions.shortcuts import is_internal_user
4
+ from wbmailing.models.mailing_lists import MailingListSubscriberChangeRequest
5
+
6
+ MAILINGLIST_MENUITEM = MenuItem(
7
+ label=_("Mailing Lists"),
8
+ endpoint="wbmailing:mailinglist-list",
9
+ permission=ItemPermission(
10
+ method=lambda request: is_internal_user(request.user), permissions=["wbmailing.view_mailinglist"]
11
+ ),
12
+ add=MenuItem(
13
+ label=_("Create Mailing List"),
14
+ endpoint="wbmailing:mailinglist-list",
15
+ permission=ItemPermission(
16
+ method=lambda request: is_internal_user(request.user), permissions=["wbmailing.add_mailinglist"]
17
+ ),
18
+ ),
19
+ )
20
+
21
+ MAILINGLISTSUBSCRIPTIONCHANGEREQUEST_MENUITEM = MenuItem(
22
+ label=_("Subscription Requests"),
23
+ endpoint="wbmailing:mailinglistsubscriberchangerequest-list",
24
+ endpoint_get_parameters={"status": MailingListSubscriberChangeRequest.Status.PENDING.value},
25
+ permission=ItemPermission(
26
+ method=lambda request: is_internal_user(request.user),
27
+ permissions=["wbmailing.view_mailinglistsubscriberchangerequest"],
28
+ ),
29
+ add=MenuItem(
30
+ label=_("Create Subscription Request"),
31
+ endpoint="wbmailing:mailinglistsubscriberchangerequest-list",
32
+ permission=ItemPermission(
33
+ method=lambda request: is_internal_user(request.user),
34
+ permissions=["wbmailing.add_mailinglistsubscriberchangerequest"],
35
+ ),
36
+ ),
37
+ )
@@ -0,0 +1,25 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.menus import ItemPermission, MenuItem
3
+ from wbcore.permissions.shortcuts import is_internal_user
4
+
5
+ MASSMAIL_MENUITEM = MenuItem(
6
+ label=_("Mass Mail"),
7
+ endpoint="wbmailing:massmail-list",
8
+ permission=ItemPermission(
9
+ method=lambda request: is_internal_user(request.user), permissions=["wbmailing.view_massmail"]
10
+ ),
11
+ add=MenuItem(
12
+ label=_("Create Mass Mail"),
13
+ endpoint="wbmailing:massmail-list",
14
+ permission=ItemPermission(
15
+ method=lambda request: is_internal_user(request.user), permissions=["wbmailing.add_massmail"]
16
+ ),
17
+ ),
18
+ )
19
+ MAIL_MENUITEM = MenuItem(
20
+ label=_("Mails"),
21
+ endpoint="wbmailing:mail-list",
22
+ permission=ItemPermission(
23
+ method=lambda request: is_internal_user(request.user), permissions=["wbmailing.view_mail"]
24
+ ),
25
+ )
@@ -0,0 +1,17 @@
1
+ from .mailing_lists import (
2
+ EmailContactMailingListTitleConfig,
3
+ MailingListEntryTitleConfig,
4
+ MailingListSubscriberChangeRequestTitleConfig,
5
+ MailingListSubscriberRequestEntryTitleConfig,
6
+ MailingListTitleConfig,
7
+ MailMailingListChartTitleConfig,
8
+ UnsubscribedEmailContactMailingListTitleConfig,
9
+ )
10
+ from .mails import (
11
+ MailEventMailTitleConfig,
12
+ MailEventMassMailTitleConfig,
13
+ MailStatusMassMailTitleConfig,
14
+ MailTemplateTitleConfig,
15
+ MailTitleConfig,
16
+ MassMailTitleConfig,
17
+ )
@@ -0,0 +1,63 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.contrib.directory.models import Entry
3
+ from wbcore.metadata.configs.titles import TitleViewConfig
4
+ from wbmailing import models
5
+
6
+
7
+ class MailingListTitleConfig(TitleViewConfig):
8
+ def get_instance_title(self):
9
+ return _("Mailing List: {{title}}")
10
+
11
+ def get_list_title(self):
12
+ return _("Mailing Lists")
13
+
14
+ def get_create_title(self):
15
+ return _("New Mailing List")
16
+
17
+
18
+ class MailingListSubscriberChangeRequestTitleConfig(TitleViewConfig):
19
+ def get_instance_title(self):
20
+ return _("Mailing List Subscriber Change Request")
21
+
22
+ def get_list_title(self):
23
+ return _("Mailing List Subscriber Change Requests")
24
+
25
+ def get_create_title(self):
26
+ return _("New Mailing List Subscriber Change Request")
27
+
28
+
29
+ class EmailContactMailingListTitleConfig(TitleViewConfig):
30
+ def get_instance_title(self):
31
+ return _("Email Contact: {{address}}")
32
+
33
+ def get_list_title(self):
34
+ mailinglist = models.MailingList.objects.get(id=self.view.kwargs["mailing_list_id"])
35
+ return _("Subscribed Emails for {}").format(mailinglist.title)
36
+
37
+
38
+ class MailMailingListChartTitleConfig(TitleViewConfig):
39
+ def get_list_title(self):
40
+ mailinglist = models.MailingList.objects.get(id=self.view.kwargs["mailing_list_id"])
41
+ return _("Mail Penetration for {}").format(mailinglist.title)
42
+
43
+
44
+ class UnsubscribedEmailContactMailingListTitleConfig(EmailContactMailingListTitleConfig):
45
+ def get_list_title(self):
46
+ mailinglist = models.MailingList.objects.get(id=self.view.kwargs["mailing_list_id"])
47
+ return _("Unsubscribed Emails for {}").format(mailinglist.title)
48
+
49
+
50
+ class MailingListEntryTitleConfig(MailingListTitleConfig):
51
+ def get_list_title(self):
52
+ entry = Entry.objects.get(id=self.view.kwargs["entry_id"])
53
+ return _("Subscribed Mailing Lists of {}").format(entry.computed_str)
54
+
55
+
56
+ class MailingListSubscriberRequestEntryTitleConfig(MailingListSubscriberChangeRequestTitleConfig):
57
+ def get_list_title(self):
58
+ entry = Entry.objects.get(id=self.view.kwargs["entry_id"])
59
+ return _("Mailing Subscription Requests for {}").format(entry.computed_str)
60
+
61
+ def get_create_title(self):
62
+ entry = Entry.objects.get(id=self.view.kwargs["entry_id"])
63
+ return _("New Mailing Subscription Request for {}").format(entry.computed_str)
@@ -0,0 +1,55 @@
1
+ from django.utils.translation import gettext as _
2
+ from wbcore.metadata.configs.titles import TitleViewConfig
3
+ from wbmailing import models
4
+
5
+
6
+ class MassMailTitleConfig(TitleViewConfig):
7
+ def get_instance_title(self):
8
+ return _("Mass Mail: {{subject}}")
9
+
10
+ def get_list_title(self):
11
+ return _("Mass Mails")
12
+
13
+ def get_create_title(self):
14
+ return _("New Mass Mail")
15
+
16
+
17
+ class MailTitleConfig(TitleViewConfig):
18
+ def get_instance_title(self):
19
+ return _("Mail: {{subject}}")
20
+
21
+ def get_list_title(self):
22
+ return _("Mails")
23
+
24
+ def get_create_title(self):
25
+ return _("Write E-Mail")
26
+
27
+
28
+ class MailStatusMassMailTitleConfig(TitleViewConfig):
29
+ def get_instance_title(self):
30
+ return _("Mail: {{subject}}")
31
+
32
+ def get_list_title(self):
33
+ massmail = models.MassMail.objects.get(id=self.view.kwargs["mass_mail_id"])
34
+ return _("Mails' Status for {}").format(massmail.subject)
35
+
36
+
37
+ class MailTemplateTitleConfig(TitleViewConfig):
38
+ def get_instance_title(self):
39
+ return _("Mail Template: {{title}}")
40
+
41
+ def get_list_title(self):
42
+ return _("Mail Templates")
43
+
44
+
45
+ class MailEventMailTitleConfig(TitleViewConfig):
46
+ def get_list_title(self):
47
+ mail = models.Mail.objects.get(id=self.view.kwargs["mail_id"])
48
+ emails = ", ".join([email.address for email in mail.to_email.all()])
49
+ return _("Event for Mail {} to {} ({})").format(mail.subject, emails, mail.created)
50
+
51
+
52
+ class MailEventMassMailTitleConfig(TitleViewConfig):
53
+ def get_list_title(self):
54
+ massmail = models.MassMail.objects.get(id=self.view.kwargs["mass_mail_id"])
55
+ return _("Event for Mass Mail {}").format(str(massmail))
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.3
2
+ Name: wbmailing
3
+ Version: 2.2.1
4
+ Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
+ Requires-Dist: wbcore