django-codenerix-email 4.0.39__py2.py3-none-any.whl → 4.0.41__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.
- codenerix_email/__init__.py +1 -1
- codenerix_email/__pycache__/__init__.cpython-310.pyc +0 -0
- codenerix_email/__pycache__/__init__.cpython-311.pyc +0 -0
- codenerix_email/__pycache__/forms.cpython-311.pyc +0 -0
- codenerix_email/__pycache__/models.cpython-310.pyc +0 -0
- codenerix_email/__pycache__/models.cpython-311.pyc +0 -0
- codenerix_email/__pycache__/views.cpython-311.pyc +0 -0
- codenerix_email/forms.py +12 -5
- codenerix_email/management/commands/emails_recv.py +56 -11
- codenerix_email/migrations/0015_emailmessage_bounces_hard_emailmessage_bounces_soft_and_more.py +28 -0
- codenerix_email/migrations/__pycache__/0015_emailmessage_bounces_hard_emailmessage_bounces_soft_and_more.cpython-311.pyc +0 -0
- codenerix_email/models.py +29 -14
- codenerix_email/static/codenerix_email/emailmessages_rows.html +1 -1
- codenerix_email/views.py +2 -89
- {django_codenerix_email-4.0.39.dist-info → django_codenerix_email-4.0.41.dist-info}/METADATA +1 -1
- {django_codenerix_email-4.0.39.dist-info → django_codenerix_email-4.0.41.dist-info}/RECORD +19 -17
- {django_codenerix_email-4.0.39.dist-info → django_codenerix_email-4.0.41.dist-info}/LICENSE +0 -0
- {django_codenerix_email-4.0.39.dist-info → django_codenerix_email-4.0.41.dist-info}/WHEEL +0 -0
- {django_codenerix_email-4.0.39.dist-info → django_codenerix_email-4.0.41.dist-info}/top_level.txt +0 -0
codenerix_email/__init__.py
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
codenerix_email/forms.py
CHANGED
|
@@ -94,7 +94,7 @@ class EmailMessageForm(GenModelForm):
|
|
|
94
94
|
return [
|
|
95
95
|
(
|
|
96
96
|
_("Details"),
|
|
97
|
-
|
|
97
|
+
4,
|
|
98
98
|
["uuid", 3],
|
|
99
99
|
["created", 3],
|
|
100
100
|
["updated", 3],
|
|
@@ -102,20 +102,27 @@ class EmailMessageForm(GenModelForm):
|
|
|
102
102
|
["eto", 3],
|
|
103
103
|
["subject", 3],
|
|
104
104
|
["opened", 3],
|
|
105
|
-
["content_subtype", 3],
|
|
106
105
|
),
|
|
107
106
|
(
|
|
108
107
|
_("System"),
|
|
109
|
-
|
|
108
|
+
4,
|
|
110
109
|
["sending", 3],
|
|
111
110
|
["sent", 3],
|
|
112
111
|
["error", 3],
|
|
113
|
-
["retries", 3],
|
|
114
|
-
["priority", 3],
|
|
115
112
|
["log", 3],
|
|
113
|
+
["content_subtype", 3],
|
|
116
114
|
["unsubscribe_url", 3],
|
|
117
115
|
["headers", 3],
|
|
118
116
|
),
|
|
117
|
+
(
|
|
118
|
+
_("Status"),
|
|
119
|
+
4,
|
|
120
|
+
["retries", 3],
|
|
121
|
+
["priority", 3],
|
|
122
|
+
["bounces_total", 3],
|
|
123
|
+
["bounces_soft", 3],
|
|
124
|
+
["bounces_hard", 3],
|
|
125
|
+
),
|
|
119
126
|
(
|
|
120
127
|
_("Body"),
|
|
121
128
|
12,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
+
import codecs
|
|
2
3
|
from textwrap import dedent
|
|
3
4
|
from argparse import RawTextHelpFormatter
|
|
4
5
|
|
|
@@ -144,6 +145,24 @@ class Command(BaseCommand):
|
|
|
144
145
|
"--rewrite", action="store_true", help="Rewrite existing"
|
|
145
146
|
)
|
|
146
147
|
|
|
148
|
+
def validate_encoding(self, encoding: str | None) -> str:
|
|
149
|
+
"""
|
|
150
|
+
Validates and returns a safe encoding name.
|
|
151
|
+
"""
|
|
152
|
+
# If an encoding is specified, verify it's valid
|
|
153
|
+
if encoding:
|
|
154
|
+
try:
|
|
155
|
+
# Attempt to look up the encoding to see if it's known
|
|
156
|
+
codecs.lookup(encoding)
|
|
157
|
+
except LookupError:
|
|
158
|
+
# If the lookup fails, the encoding is unknown
|
|
159
|
+
# Fall back to a safe default like 'latin-1'
|
|
160
|
+
encoding = "latin-1"
|
|
161
|
+
else:
|
|
162
|
+
# If no encoding is specified, use a default
|
|
163
|
+
encoding = "utf-8"
|
|
164
|
+
return encoding
|
|
165
|
+
|
|
147
166
|
def handle(self, *args, **options):
|
|
148
167
|
# Get configuration
|
|
149
168
|
self.silent = options["silent"]
|
|
@@ -328,10 +347,15 @@ class Command(BaseCommand):
|
|
|
328
347
|
# Parse the email
|
|
329
348
|
msg = message_from_bytes(raw_email)
|
|
330
349
|
|
|
331
|
-
# Extract subject
|
|
350
|
+
# Extract subject
|
|
332
351
|
subject, encoding = decode_header(msg["Subject"])[0]
|
|
352
|
+
|
|
353
|
+
# Decode subject if it's bytes
|
|
333
354
|
if isinstance(subject, bytes):
|
|
334
|
-
|
|
355
|
+
charset = self.validate_encoding(encoding)
|
|
356
|
+
subject = subject.decode(charset, "ignore")
|
|
357
|
+
|
|
358
|
+
# Extract other headers
|
|
335
359
|
efrom = msg.get("From")
|
|
336
360
|
eto = msg.get("To")
|
|
337
361
|
eid = msg.get("Message-ID")
|
|
@@ -353,22 +377,31 @@ class Command(BaseCommand):
|
|
|
353
377
|
for part in msg.walk():
|
|
354
378
|
content_type = part.get_content_type()
|
|
355
379
|
if content_type == "text/plain" and not body_plain:
|
|
380
|
+
charset = self.validate_encoding(
|
|
381
|
+
part.get_content_charset()
|
|
382
|
+
)
|
|
356
383
|
body_plain = part.get_payload(
|
|
357
384
|
decode=True
|
|
358
385
|
).decode(
|
|
359
|
-
|
|
386
|
+
charset,
|
|
360
387
|
"ignore",
|
|
361
388
|
)
|
|
362
389
|
elif content_type == "text/html" and not body_html:
|
|
390
|
+
charset = self.validate_encoding(
|
|
391
|
+
part.get_content_charset()
|
|
392
|
+
)
|
|
363
393
|
body_html = part.get_payload(
|
|
364
394
|
decode=True
|
|
365
395
|
).decode(
|
|
366
|
-
|
|
396
|
+
charset,
|
|
367
397
|
"ignore",
|
|
368
398
|
)
|
|
369
399
|
else:
|
|
400
|
+
charset = self.validate_encoding(
|
|
401
|
+
msg.get_content_charset()
|
|
402
|
+
)
|
|
370
403
|
body_plain = msg.get_payload(decode=True).decode(
|
|
371
|
-
|
|
404
|
+
charset,
|
|
372
405
|
"ignore",
|
|
373
406
|
)
|
|
374
407
|
|
|
@@ -416,9 +449,10 @@ class Command(BaseCommand):
|
|
|
416
449
|
headers = {}
|
|
417
450
|
for header, value in msg.items():
|
|
418
451
|
decoded_value, encoding = decode_header(value)[0]
|
|
452
|
+
charset = self.validate_encoding(encoding)
|
|
419
453
|
if isinstance(decoded_value, bytes):
|
|
420
454
|
decoded_value = decoded_value.decode(
|
|
421
|
-
|
|
455
|
+
charset, "ignore"
|
|
422
456
|
)
|
|
423
457
|
headers[header] = decoded_value
|
|
424
458
|
|
|
@@ -453,7 +487,8 @@ class Command(BaseCommand):
|
|
|
453
487
|
if self.verbose:
|
|
454
488
|
self.stdout.write(
|
|
455
489
|
self.style.SUCCESS(
|
|
456
|
-
|
|
490
|
+
"Deleted email with "
|
|
491
|
+
f"IMAP ID: {imap_id}"
|
|
457
492
|
)
|
|
458
493
|
)
|
|
459
494
|
|
|
@@ -487,6 +522,10 @@ class Command(BaseCommand):
|
|
|
487
522
|
# Save the received email
|
|
488
523
|
email_received.save()
|
|
489
524
|
|
|
525
|
+
# Recalculate the email status if linked to a sent email
|
|
526
|
+
if email_message:
|
|
527
|
+
email_message.recalculate_bounces()
|
|
528
|
+
|
|
490
529
|
# Count created or overwritten
|
|
491
530
|
if overwriting:
|
|
492
531
|
overwrite_count += 1
|
|
@@ -543,7 +582,7 @@ class Command(BaseCommand):
|
|
|
543
582
|
)
|
|
544
583
|
)
|
|
545
584
|
elif getattr(settings, "IMAP_EMAIL_SEEN", True):
|
|
546
|
-
# Mark the message as read otherwise (
|
|
585
|
+
# Mark the message as read otherwise (avoids reprocessing)
|
|
547
586
|
server.add_flags(imap_id, [b"\\Seen"])
|
|
548
587
|
|
|
549
588
|
return (created_count, overwrite_count)
|
|
@@ -591,7 +630,9 @@ class Command(BaseCommand):
|
|
|
591
630
|
headers_payload = part.get_payload(decode=True)
|
|
592
631
|
if isinstance(headers_payload, bytes):
|
|
593
632
|
# Decode using the specified charset
|
|
594
|
-
charset =
|
|
633
|
+
charset = self.validate_encoding(
|
|
634
|
+
part.get_content_charset()
|
|
635
|
+
)
|
|
595
636
|
headers_text = headers_payload.decode(
|
|
596
637
|
charset, errors="ignore"
|
|
597
638
|
)
|
|
@@ -615,7 +656,9 @@ class Command(BaseCommand):
|
|
|
615
656
|
payload = part.get_payload(decode=True)
|
|
616
657
|
if isinstance(payload, bytes):
|
|
617
658
|
# Decode using the specified charset
|
|
618
|
-
charset =
|
|
659
|
+
charset = self.validate_encoding(
|
|
660
|
+
part.get_content_charset()
|
|
661
|
+
)
|
|
619
662
|
body_text += payload.decode(
|
|
620
663
|
charset, errors="ignore"
|
|
621
664
|
)
|
|
@@ -626,7 +669,9 @@ class Command(BaseCommand):
|
|
|
626
669
|
payload = msg.get_payload(decode=True)
|
|
627
670
|
if isinstance(payload, bytes):
|
|
628
671
|
# Decode using the specified charset
|
|
629
|
-
charset =
|
|
672
|
+
charset = self.validate_encoding(
|
|
673
|
+
msg.get_content_charset()
|
|
674
|
+
)
|
|
630
675
|
body_text = payload.decode(
|
|
631
676
|
charset, errors="ignore"
|
|
632
677
|
)
|
codenerix_email/migrations/0015_emailmessage_bounces_hard_emailmessage_bounces_soft_and_more.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Generated by Django 5.2.7 on 2025-10-14 05:10
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('codenerix_email', '0014_emailreceived'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='emailmessage',
|
|
15
|
+
name='bounces_hard',
|
|
16
|
+
field=models.PositiveIntegerField(default=0, verbose_name='Hard bounces'),
|
|
17
|
+
),
|
|
18
|
+
migrations.AddField(
|
|
19
|
+
model_name='emailmessage',
|
|
20
|
+
name='bounces_soft',
|
|
21
|
+
field=models.PositiveIntegerField(default=0, verbose_name='Soft bounces'),
|
|
22
|
+
),
|
|
23
|
+
migrations.AddField(
|
|
24
|
+
model_name='emailmessage',
|
|
25
|
+
name='bounces_total',
|
|
26
|
+
field=models.PositiveIntegerField(default=0, verbose_name='Total bounces'),
|
|
27
|
+
),
|
|
28
|
+
]
|
|
Binary file
|
codenerix_email/models.py
CHANGED
|
@@ -114,6 +114,34 @@ class EmailMessage(CodenerixModel):
|
|
|
114
114
|
_("Unsubscribe URL"), blank=True, null=True
|
|
115
115
|
)
|
|
116
116
|
headers = models.JSONField(_("Headers"), blank=True, null=True)
|
|
117
|
+
bounces_soft = models.PositiveIntegerField(
|
|
118
|
+
_("Soft bounces"), blank=False, null=False, default=0
|
|
119
|
+
)
|
|
120
|
+
bounces_hard = models.PositiveIntegerField(
|
|
121
|
+
_("Hard bounces"), blank=False, null=False, default=0
|
|
122
|
+
)
|
|
123
|
+
bounces_total = models.PositiveIntegerField(
|
|
124
|
+
_("Total bounces"), blank=False, null=False, default=0
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def recalculate_bounces(self):
|
|
128
|
+
bounces_soft = self.receiveds.filter(bounce_type=BOUNCE_SOFT).count()
|
|
129
|
+
bounces_hard = self.receiveds.filter(bounce_type=BOUNCE_HARD).count()
|
|
130
|
+
bounces_total = self.receiveds.filter(
|
|
131
|
+
bounce_type__isnull=False
|
|
132
|
+
).count()
|
|
133
|
+
changed = False
|
|
134
|
+
if self.bounces_soft != bounces_soft:
|
|
135
|
+
self.bounces_soft = bounces_soft
|
|
136
|
+
changed = True
|
|
137
|
+
if self.bounces_hard != bounces_hard:
|
|
138
|
+
self.bounces_hard = bounces_hard
|
|
139
|
+
changed = True
|
|
140
|
+
if self.bounces_total != bounces_total:
|
|
141
|
+
self.bounces_total = bounces_total
|
|
142
|
+
changed = True
|
|
143
|
+
if changed:
|
|
144
|
+
self.save()
|
|
117
145
|
|
|
118
146
|
def __fields__(self, info):
|
|
119
147
|
fields = []
|
|
@@ -127,6 +155,7 @@ class EmailMessage(CodenerixModel):
|
|
|
127
155
|
# fields.append(("efrom", _("From")))
|
|
128
156
|
fields.append(("eto", _("To")))
|
|
129
157
|
fields.append(("subject", _("Subject")))
|
|
158
|
+
fields.append(("bounces_total", _("Bounces")))
|
|
130
159
|
fields.append(("retries", _("Retries")))
|
|
131
160
|
fields.append(("next_retry", _("Next retry")))
|
|
132
161
|
fields.append(("pk", _("ID")))
|
|
@@ -169,7 +198,6 @@ class EmailMessage(CodenerixModel):
|
|
|
169
198
|
return {
|
|
170
199
|
"sent": (_("Sent"), lambda x: mailstatus(x), mailoptions),
|
|
171
200
|
"uuid": (_("UUID"), lambda x: Q(uuid__icontains=x), "input"),
|
|
172
|
-
"priority": (_("Priority"), lambda x: Q(priority=x), "input"),
|
|
173
201
|
"opened": (
|
|
174
202
|
_("Opened"),
|
|
175
203
|
lambda x: ~Q(opened__isnull=x),
|
|
@@ -177,25 +205,12 @@ class EmailMessage(CodenerixModel):
|
|
|
177
205
|
),
|
|
178
206
|
# "efrom": (_("From"), lambda x: Q(efrom__icontains=x), "input"),
|
|
179
207
|
"eto": (_("To"), lambda x: Q(eto__icontains=x), "input"),
|
|
180
|
-
"retries": (_("Retries"), lambda x: Q(retries=x), "input"),
|
|
181
208
|
"pk": (_("ID"), lambda x: Q(pk=x), "input"),
|
|
182
209
|
}
|
|
183
210
|
|
|
184
211
|
def __unicode__(self):
|
|
185
212
|
return "{} ({})".format(self.eto, self.pk)
|
|
186
213
|
|
|
187
|
-
@property
|
|
188
|
-
def bounces_soft(self):
|
|
189
|
-
return self.receiveds.filter(bounce_type=BOUNCE_SOFT).count()
|
|
190
|
-
|
|
191
|
-
@property
|
|
192
|
-
def bounces_hard(self):
|
|
193
|
-
return self.receiveds.filter(bounce_type=BOUNCE_HARD).count()
|
|
194
|
-
|
|
195
|
-
@property
|
|
196
|
-
def bounces_total(self):
|
|
197
|
-
return self.receiveds.filter(bounce_type__isnull=False).count()
|
|
198
|
-
|
|
199
214
|
def clean(self):
|
|
200
215
|
if not isinstance(self.headers, dict):
|
|
201
216
|
raise ValidationError(_("HEADERS must be a Dictionary"))
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
</td>
|
|
15
15
|
<td>{{row.eto|codenerix}}</td>
|
|
16
16
|
<td><nobr>{{row.subject|codenerix}}</nobr></td>
|
|
17
|
-
<td class="text-nowrap">{{row.
|
|
17
|
+
<td class="text-nowrap">{{row.bounces_total|codenerix}}</td>
|
|
18
18
|
<td><center>{{row.retries|codenerix}}</center></td>
|
|
19
19
|
<td class="text-nowrap">{{row.next_retry|codenerix}}</td>
|
|
20
20
|
<td><center>{{row.pk|codenerix}}</center></td>
|
codenerix_email/views.py
CHANGED
|
@@ -28,7 +28,7 @@ from django.shortcuts import get_object_or_404
|
|
|
28
28
|
from django.utils.translation import gettext as _
|
|
29
29
|
from django.conf import settings
|
|
30
30
|
from django.http import HttpRequest, Http404
|
|
31
|
-
from django.db.models import Q
|
|
31
|
+
from django.db.models import Q
|
|
32
32
|
|
|
33
33
|
from codenerix.multiforms import MultiForm # type: ignore
|
|
34
34
|
from codenerix.views import ( # type: ignore
|
|
@@ -40,15 +40,12 @@ from codenerix.views import ( # type: ignore
|
|
|
40
40
|
GenDelete,
|
|
41
41
|
GenDetail,
|
|
42
42
|
GenDetailModal,
|
|
43
|
-
SearchFilters,
|
|
44
43
|
)
|
|
45
44
|
from codenerix_email.models import (
|
|
46
45
|
EmailTemplate,
|
|
47
46
|
EmailMessage,
|
|
48
47
|
EmailReceived,
|
|
49
48
|
MODELS,
|
|
50
|
-
BOUNCE_SOFT,
|
|
51
|
-
BOUNCE_HARD,
|
|
52
49
|
)
|
|
53
50
|
from codenerix_email.forms import (
|
|
54
51
|
EmailTemplateForm,
|
|
@@ -106,7 +103,7 @@ class EmailFollow(View):
|
|
|
106
103
|
# Return an image of 1x1 pixel
|
|
107
104
|
return HttpResponse(
|
|
108
105
|
base64.b64decode(
|
|
109
|
-
"R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="
|
|
106
|
+
"R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" # noqa: E501
|
|
110
107
|
),
|
|
111
108
|
content_type="image/gif",
|
|
112
109
|
)
|
|
@@ -186,90 +183,6 @@ class EmailMessageList(GenList):
|
|
|
186
183
|
"menu": ["codenerix_email", "emailmessages"],
|
|
187
184
|
"bread": [_("Emails"), _("Email Messages")],
|
|
188
185
|
}
|
|
189
|
-
annotations = {
|
|
190
|
-
# "bounces_soft_count": Count(
|
|
191
|
-
# "receiveds__pk", filter=Q(receiveds__bounce_type=BOUNCE_SOFT)
|
|
192
|
-
# ),
|
|
193
|
-
# "bounces_hard_count": Count(
|
|
194
|
-
# "receiveds__pk", filter=Q(receiveds__bounce_type=BOUNCE_HARD)
|
|
195
|
-
# ),
|
|
196
|
-
"bounces_total_count": Count(
|
|
197
|
-
"receiveds__pk", filter=Q(receiveds__bounce_type__isnull=False)
|
|
198
|
-
),
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
def __fields__(self, info):
|
|
202
|
-
fields = []
|
|
203
|
-
fields.append(("sending", None))
|
|
204
|
-
fields.append(("error", None))
|
|
205
|
-
fields.append(("sent", _("Send")))
|
|
206
|
-
fields.append(("priority", _("Priority")))
|
|
207
|
-
fields.append(("created", _("Created")))
|
|
208
|
-
fields.append(("updated", _("Updated")))
|
|
209
|
-
fields.append(("opened", _("Opened")))
|
|
210
|
-
# fields.append(("efrom", _("From")))
|
|
211
|
-
fields.append(("eto", _("To")))
|
|
212
|
-
fields.append(("subject", _("Subject")))
|
|
213
|
-
fields.append(("bounces_total_count", _("Bounces")))
|
|
214
|
-
# fields.append(("bounces_soft_count", _("Soft bounces")))
|
|
215
|
-
# fields.append(("bounces_hard_count", _("Hard bounces")))
|
|
216
|
-
fields.append(("retries", _("Retries")))
|
|
217
|
-
fields.append(("next_retry", _("Next retry")))
|
|
218
|
-
fields.append(("pk", _("ID")))
|
|
219
|
-
fields.append(("uuid", _("UUID")))
|
|
220
|
-
fields.append(("unsubscribe_url", _("Unsubscribe")))
|
|
221
|
-
fields.append(("content_subtype", _("Content Subtype")))
|
|
222
|
-
return fields
|
|
223
|
-
|
|
224
|
-
def __searchF__(self, info): # noqa: N802
|
|
225
|
-
def mailstatus(x):
|
|
226
|
-
if x == "D":
|
|
227
|
-
return Q(error=False, sent=True)
|
|
228
|
-
elif x == "P":
|
|
229
|
-
return Q(error=False, sent=False, sending=False)
|
|
230
|
-
elif x == "S":
|
|
231
|
-
return Q(error=False, sent=False, sending=True)
|
|
232
|
-
elif x == "E":
|
|
233
|
-
return Q(error=True)
|
|
234
|
-
else:
|
|
235
|
-
return Q()
|
|
236
|
-
|
|
237
|
-
mailoptions = [
|
|
238
|
-
("D", _("Sent")), # Sent - Done
|
|
239
|
-
("P", _("Pending")), # Pending - Pending
|
|
240
|
-
("S", _("Sending")), # Sending - Sending
|
|
241
|
-
("E", _("Error")), # Error - Error
|
|
242
|
-
]
|
|
243
|
-
|
|
244
|
-
return {
|
|
245
|
-
"sent": (_("Sent"), lambda x: mailstatus(x), mailoptions),
|
|
246
|
-
"uuid": (_("UUID"), lambda x: Q(uuid__icontains=x), "input"),
|
|
247
|
-
"priority": (_("Priority"), lambda x: Q(priority=x), "input"),
|
|
248
|
-
"opened": (
|
|
249
|
-
_("Opened"),
|
|
250
|
-
lambda x: ~Q(opened__isnull=x),
|
|
251
|
-
[(True, _("Yes")), (False, _("No"))],
|
|
252
|
-
),
|
|
253
|
-
# "efrom": (_("From"), lambda x: Q(efrom__icontains=x), "input"),
|
|
254
|
-
"eto": (_("To"), lambda x: Q(eto__icontains=x), "input"),
|
|
255
|
-
"retries": (_("Retries"), lambda x: Q(retries=x), "input"),
|
|
256
|
-
"pk": (_("ID"), lambda x: Q(pk=x), "input"),
|
|
257
|
-
"bounces_total_count": (
|
|
258
|
-
_("Bounces"),
|
|
259
|
-
SearchFilters.number("bounces_total_count"),
|
|
260
|
-
"input",
|
|
261
|
-
),
|
|
262
|
-
"bounces_soft_count": (
|
|
263
|
-
_("Soft bounces"),
|
|
264
|
-
SearchFilters.number("bounces_soft_count"),
|
|
265
|
-
"input",
|
|
266
|
-
),
|
|
267
|
-
"bounces_hard_count": (
|
|
268
|
-
_("Hard bounces"),
|
|
269
|
-
SearchFilters.number("bounces_hard_count"),
|
|
270
|
-
"input",
|
|
271
|
-
),
|
|
272
|
-
}
|
|
273
186
|
|
|
274
187
|
|
|
275
188
|
class EmailMessageCreate(GenCreate):
|
{django_codenerix_email-4.0.39.dist-info → django_codenerix_email-4.0.41.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: django-codenerix-email
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.41
|
|
4
4
|
Summary: Codenerix Email is a module that enables CODENERIX to set send emails in a general manner.
|
|
5
5
|
Home-page: https://github.com/codenerix/django-codenerix-email
|
|
6
6
|
Author: Juan Miguel Taboada Godoy <juanmi@juanmitaboada.com>, Juan Soler Ruiz <soleronline@gmail.com>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
codenerix_email/__init__.py,sha256=
|
|
1
|
+
codenerix_email/__init__.py,sha256=fvnPvF-O5l4qg-_eeRjKHdMZDzfLHFHFDi1l8fzeLQ4,149
|
|
2
2
|
codenerix_email/admin.py,sha256=w259UKFk_opGEl6PJjYHXWAHQ_8emgqmiixKT5Rid4A,1180
|
|
3
3
|
codenerix_email/apps.py,sha256=WXqu1XQibDDyCvvQYt2JbTK4GIpW8BNv5DCbRJS2mmk,149
|
|
4
|
-
codenerix_email/forms.py,sha256=
|
|
5
|
-
codenerix_email/models.py,sha256=
|
|
4
|
+
codenerix_email/forms.py,sha256=P5w-ebxLR1V10RFDqO_R5vvZV-vY6SLTzVb1OLdFZE0,5710
|
|
5
|
+
codenerix_email/models.py,sha256=z0tcaOy1LCs8QBelJmn5O9Fn3GAS3_bQT59RBi-Otm4,25948
|
|
6
6
|
codenerix_email/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
codenerix_email/test_settings.py,sha256=A9WT-2MMuqvW5Mrd3lkmjrf0xJZmJl3McOEeyJug1Xc,633
|
|
8
8
|
codenerix_email/urls.py,sha256=M760qDSVV3EoY9aIPdnk8DtUv5tyWO-FQWdody4KTeM,3996
|
|
9
9
|
codenerix_email/urls_frontend.py,sha256=DG5WS_fGQJC9sezNebPwG-E_WtUWy3Kwz4VUxh82xuc,873
|
|
10
|
-
codenerix_email/views.py,sha256=
|
|
10
|
+
codenerix_email/views.py,sha256=7j9lIUJ8TMZlFx6GzDZ_R9QC6Krt__z3Dfr0ZO_IcKE,6707
|
|
11
11
|
codenerix_email/.mypy_cache/.gitignore,sha256=amnaZw0RUw038PDP3HvtMLeOpkNOJPenMgi5guKdMiw,34
|
|
12
12
|
codenerix_email/.mypy_cache/CACHEDIR.TAG,sha256=8cE6_FVTWMkDOw8fMKqhd_6IvaQPS4okWYQA1UeHatw,190
|
|
13
13
|
codenerix_email/.mypy_cache/3.10/@plugins_snapshot.json,sha256=RBNvo1WzZ4oRRq0W9-hknpT7T8If536DEMBg9hyq_4o,2
|
|
@@ -827,8 +827,8 @@ codenerix_email/.mypy_cache/3.10/zoneinfo/_common.data.json,sha256=e4xbNKL_yQ5h5
|
|
|
827
827
|
codenerix_email/.mypy_cache/3.10/zoneinfo/_common.meta.json,sha256=5K19XWobpSjKwiv7bZFZRcxsEfoh7b-FhYcmqB-2Iic,1737
|
|
828
828
|
codenerix_email/.mypy_cache/3.10/zoneinfo/_tzpath.data.json,sha256=CFx7Q1XfUhhuNX69prkxyirG8rfvEDCNgEHWQigKC_A,5632
|
|
829
829
|
codenerix_email/.mypy_cache/3.10/zoneinfo/_tzpath.meta.json,sha256=d1HJ_xFBI1orlZSVhH0gHWLI-dJG3zY-ZOlctOl62yU,1765
|
|
830
|
-
codenerix_email/__pycache__/__init__.cpython-310.pyc,sha256=
|
|
831
|
-
codenerix_email/__pycache__/__init__.cpython-311.pyc,sha256=
|
|
830
|
+
codenerix_email/__pycache__/__init__.cpython-310.pyc,sha256=15V6lHDQ0IWV_UqdkRd4uPnweplUuyHbpl8lpW1wUTI,313
|
|
831
|
+
codenerix_email/__pycache__/__init__.cpython-311.pyc,sha256=UWUl2oUBod7dR46Nr9F955JjBzb5Hw5FLg0DZAJ3XNk,337
|
|
832
832
|
codenerix_email/__pycache__/__init__.cpython-35.pyc,sha256=dl9lYAgrokJptUj3JAhiqTlX7d_CbncOxZeTc1USc88,308
|
|
833
833
|
codenerix_email/__pycache__/__init__.cpython-37.pyc,sha256=5d1CeFU5DrfnwrRpvSw1bHvLN9hoHXjUA3ln3rXCDo8,306
|
|
834
834
|
codenerix_email/__pycache__/__init__.cpython-39.pyc,sha256=0c6KWU_eOTlF5l9fNWv8l41b0LcfVQNUsqDvJTv2YyU,300
|
|
@@ -840,11 +840,11 @@ codenerix_email/__pycache__/apps.cpython-310.pyc,sha256=PzDChfGmY_KnNkDrqSdEAQbl
|
|
|
840
840
|
codenerix_email/__pycache__/apps.cpython-311.pyc,sha256=U51a_9uWzb1nkGnGLqZL5X4d-LBMi83MiPMlUtBYobo,560
|
|
841
841
|
codenerix_email/__pycache__/apps.cpython-39.pyc,sha256=d5Hd-YMSDmSzyxDmQ_nwXjcEcHASDm6MxFblb1TATf4,439
|
|
842
842
|
codenerix_email/__pycache__/forms.cpython-310.pyc,sha256=-oq5NlQGH7VkMUUMB4lXmBoUhkTVO14AOIZetrpgqck,4004
|
|
843
|
-
codenerix_email/__pycache__/forms.cpython-311.pyc,sha256=
|
|
843
|
+
codenerix_email/__pycache__/forms.cpython-311.pyc,sha256=jUjgCTZFkAE2iTueIoG0mZ7CunsFX4EH2zh2OhLA_-c,5999
|
|
844
844
|
codenerix_email/__pycache__/forms.cpython-35.pyc,sha256=z1aCJ2d8yyKJMuf5aVz0mGE6Nqi9bjU7HyDZPKxpUWc,3233
|
|
845
845
|
codenerix_email/__pycache__/forms.cpython-39.pyc,sha256=NORLA0i3bmWx-mUn3wh3JtObuR7UYKZemSU6Cl5gHM8,2988
|
|
846
|
-
codenerix_email/__pycache__/models.cpython-310.pyc,sha256=
|
|
847
|
-
codenerix_email/__pycache__/models.cpython-311.pyc,sha256=
|
|
846
|
+
codenerix_email/__pycache__/models.cpython-310.pyc,sha256=glpYvUi4CpWxUfW8zUzo60woiHa_YdvIz5MS6SFnbns,17995
|
|
847
|
+
codenerix_email/__pycache__/models.cpython-311.pyc,sha256=p5V6pZ7oTWjBFJNlexW7mM29QnJVMnc3wCn5fk4A7Lo,36820
|
|
848
848
|
codenerix_email/__pycache__/models.cpython-35.pyc,sha256=oGheSKlh8Ttc6bB-qZ1JY5_6RySM9M6GY5-GCATxfes,9481
|
|
849
849
|
codenerix_email/__pycache__/models.cpython-39.pyc,sha256=ugyNNDG3k6rqsunwlcUIWADaLNvJ8snCgQwMZu9Ahac,8849
|
|
850
850
|
codenerix_email/__pycache__/test_settings.cpython-310.pyc,sha256=HH5CsPxLlq7_jW4ZCGBc1KzcV4HNQcI6YTh0wcz_F0w,715
|
|
@@ -855,7 +855,7 @@ codenerix_email/__pycache__/urls.cpython-39.pyc,sha256=EZTAIjMTQLfB4lVdxaQrspy93
|
|
|
855
855
|
codenerix_email/__pycache__/urls_frontend.cpython-310.pyc,sha256=byQ8k-Hcfft-DzwWVvO5CEt_DBazuNPK_lNXkDV8HhY,381
|
|
856
856
|
codenerix_email/__pycache__/urls_frontend.cpython-311.pyc,sha256=GmCqHFwOVkzllal3pnLe5BYg1Rj5SAm5WTGKQrfzVGk,498
|
|
857
857
|
codenerix_email/__pycache__/views.cpython-310.pyc,sha256=vB2BqnTPYMYxiihKQAr6DZZ1-7SoGfC7dE41JHp-jPI,8707
|
|
858
|
-
codenerix_email/__pycache__/views.cpython-311.pyc,sha256=
|
|
858
|
+
codenerix_email/__pycache__/views.cpython-311.pyc,sha256=urp3a_ATSfAza2O4A-D_Vnf_zfTMzRO6jG9BxwR8MZA,10251
|
|
859
859
|
codenerix_email/__pycache__/views.cpython-35.pyc,sha256=ZiDircDZ5B_MEFZu2H4ca7OZop10EyZF2PRR6JRgUGc,3988
|
|
860
860
|
codenerix_email/__pycache__/views.cpython-39.pyc,sha256=SV_-RTnh7w_7oMUkD0mUWhSs5lqMuw-HUGU40hV56YY,3657
|
|
861
861
|
codenerix_email/locale/en/LC_MESSAGES/django.po,sha256=NzL-kG6Z7lVnp_YDsUOMz-HAKqC37J-2elkU_Ce1zL8,7198
|
|
@@ -868,7 +868,7 @@ codenerix_email/management/__pycache__/__init__.cpython-35.pyc,sha256=sBoEWs6zdI
|
|
|
868
868
|
codenerix_email/management/__pycache__/__init__.cpython-39.pyc,sha256=uPXklfliVd3b8pLOJQT9ZeKcqmJMrGychvt68BsPulY,168
|
|
869
869
|
codenerix_email/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
870
870
|
codenerix_email/management/commands/email_test.py,sha256=SPsiq0s48sEX_G3piNHq-c1gDOH800H2zTvM19ei2LY,5605
|
|
871
|
-
codenerix_email/management/commands/emails_recv.py,sha256=
|
|
871
|
+
codenerix_email/management/commands/emails_recv.py,sha256=6MRABJzVSvOcGzz7qH-1_q9U3o8yNGBVlPB6lkvYlfU,37562
|
|
872
872
|
codenerix_email/management/commands/emails_send.py,sha256=scCFklro4WVMYm-1ataSjUMsPT-Ie5u_DdA55CQcTCQ,7944
|
|
873
873
|
codenerix_email/management/commands/recv_emails.py,sha256=aXmhdXlamiNxRpMIDSKBXUBhkOcwi5l_Pme7jSQUCME,273
|
|
874
874
|
codenerix_email/management/commands/send_emails.py,sha256=a1MnpvZKAEFdXNfmI5oFUkVxy4PZ1AjaJS6GH90zeD0,273
|
|
@@ -1634,6 +1634,7 @@ codenerix_email/migrations/0011_alter_emailmessage_content_subtype_and_more.py,s
|
|
|
1634
1634
|
codenerix_email/migrations/0012_emailmessage_unsubscribe_url.py,sha256=tPQt1W2LJcXMvt_ecB-2npu7wQ-Og29M99ZJjukYnWA,501
|
|
1635
1635
|
codenerix_email/migrations/0013_emailmessage_headers.py,sha256=1T0lryajjfXhnMgU-aqJUW-CKDvVe6zLrYu_FygcFE4,441
|
|
1636
1636
|
codenerix_email/migrations/0014_emailreceived.py,sha256=U--Zhb9JkihuL3w-lNnhCfWT1dkVbgEWBHE3RHXtAnA,3406
|
|
1637
|
+
codenerix_email/migrations/0015_emailmessage_bounces_hard_emailmessage_bounces_soft_and_more.py,sha256=68A8DtX_77s0KwhocOuyUyExkx3AMndAEnYahdok3rE,835
|
|
1637
1638
|
codenerix_email/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1638
1639
|
codenerix_email/migrations/__pycache__/0001_initial.cpython-310.pyc,sha256=Sm54OKfGHUMvSVgbXiFAe9E2d85HqlLoMEaBEBP53mE,2005
|
|
1639
1640
|
codenerix_email/migrations/__pycache__/0001_initial.cpython-311.pyc,sha256=KsQcRgyLOFbYfAHj9C5i7uQNWt9_wMJg2MOwpOa1B10,3852
|
|
@@ -1681,14 +1682,15 @@ codenerix_email/migrations/__pycache__/0013_emailmessage_headers.cpython-310.pyc
|
|
|
1681
1682
|
codenerix_email/migrations/__pycache__/0013_emailmessage_headers.cpython-311.pyc,sha256=-fFwK7UWVLCbaVh3ej4EQbee44wVC3hBezdgW875ncg,891
|
|
1682
1683
|
codenerix_email/migrations/__pycache__/0014_emailreceived.cpython-310.pyc,sha256=cN48X4p05m2tZafTP1pHgQOcoz9qrROwGqII6G1FjsQ,1923
|
|
1683
1684
|
codenerix_email/migrations/__pycache__/0014_emailreceived.cpython-311.pyc,sha256=0FC9aa_p8Ojxq0IISCbJbmNlySYNr-UkI1W1Y6b6jIU,2924
|
|
1685
|
+
codenerix_email/migrations/__pycache__/0015_emailmessage_bounces_hard_emailmessage_bounces_soft_and_more.cpython-311.pyc,sha256=-4y6CXG8s9cn_rpvQcWvxi1-farfomE6yIf6Dy1kBos,1231
|
|
1684
1686
|
codenerix_email/migrations/__pycache__/__init__.cpython-310.pyc,sha256=PdaaABMdLCzCMnJmxaylT_jnLb8l7rr6n5C4CGDX37A,151
|
|
1685
1687
|
codenerix_email/migrations/__pycache__/__init__.cpython-311.pyc,sha256=RbbUUEhcJ_eAVNFAdNbkjv60hyF7BsnNOlti5xplQsY,195
|
|
1686
1688
|
codenerix_email/migrations/__pycache__/__init__.cpython-35.pyc,sha256=2g70xiMW6oJNkIpRM-0Dr5h7AUac-3xyCXPONxp9BBw,147
|
|
1687
1689
|
codenerix_email/migrations/__pycache__/__init__.cpython-39.pyc,sha256=qNj2NH0YvoWPnCKxkVZPsEFsbM05y7t1njMskNISdVQ,168
|
|
1688
|
-
codenerix_email/static/codenerix_email/emailmessages_rows.html,sha256=
|
|
1690
|
+
codenerix_email/static/codenerix_email/emailmessages_rows.html,sha256=cA2ru5ti9WnPhhvFNEpI2tTR7gZzUYXWdzngRKU6a7k,2196
|
|
1689
1691
|
codenerix_email/static/codenerix_email/emailreceiveds_rows.html,sha256=u9DXVdzKhx9WlJgcK_cT2DfGp9bGIKTBn3LDQplB4g4,2032
|
|
1690
|
-
django_codenerix_email-4.0.
|
|
1691
|
-
django_codenerix_email-4.0.
|
|
1692
|
-
django_codenerix_email-4.0.
|
|
1693
|
-
django_codenerix_email-4.0.
|
|
1694
|
-
django_codenerix_email-4.0.
|
|
1692
|
+
django_codenerix_email-4.0.41.dist-info/LICENSE,sha256=IXMIpi75XsrJt1Sznt4EftT9c_4X0C9eqK4tHhH8H48,11339
|
|
1693
|
+
django_codenerix_email-4.0.41.dist-info/METADATA,sha256=EZuTjqR4JMJ9UnNCudgk6mNmFnIlBjZng24g08-k_JA,2676
|
|
1694
|
+
django_codenerix_email-4.0.41.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
|
|
1695
|
+
django_codenerix_email-4.0.41.dist-info/top_level.txt,sha256=lljSA0iKE_UBEM5gIrGQwioC_i8Jjnp-aR1LFElENgw,16
|
|
1696
|
+
django_codenerix_email-4.0.41.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{django_codenerix_email-4.0.39.dist-info → django_codenerix_email-4.0.41.dist-info}/top_level.txt
RENAMED
|
File without changes
|