django-codenerix-email 4.0.4__tar.gz → 4.0.6__tar.gz
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.
- {django-codenerix-email-4.0.4/django_codenerix_email.egg-info → django-codenerix-email-4.0.6}/PKG-INFO +1 -1
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/__init__.py +1 -1
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/forms.py +61 -33
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/commands/send_emails.py +83 -37
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/commands/test_email.py +8 -6
- django-codenerix-email-4.0.6/codenerix_email/migrations/0009_emailmessage_opened_emailmessage_uuid.py +44 -0
- django-codenerix-email-4.0.6/codenerix_email/migrations/__pycache__/0009_delete_emailtemplatetexten.cpython-311.pyc +0 -0
- django-codenerix-email-4.0.6/codenerix_email/migrations/__pycache__/0009_emailmessage_opened_emailmessage_uuid.cpython-311.pyc +0 -0
- django-codenerix-email-4.0.6/codenerix_email/migrations/__pycache__/0010_emailmessage_opened_emailmessage_uuid_and_more.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/models.py +25 -3
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/static/codenerix_email/partials/emailmessages_rows.html +2 -0
- django-codenerix-email-4.0.6/codenerix_email/urls_frontend.py +31 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/views.py +41 -4
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6/django_codenerix_email.egg-info}/PKG-INFO +1 -1
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/django_codenerix_email.egg-info/SOURCES.txt +5 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/LICENSE +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/MANIFEST.in +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/README.rst +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/admin.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/apps.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/__init__.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/__pycache__/__init__.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/__pycache__/__init__.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/__pycache__/__init__.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/__pycache__/__init__.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/commands/__init__.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0001_initial.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0002_auto_20170502_1043.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0003_auto_20170921_1206.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0004_auto_20171108_1628.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0005_emailmessage_retries.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0006_emailmessage_error.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0007_emailmessage_next_retry.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/0008_auto_20171201_0928.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__init__.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0001_initial.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0001_initial.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0001_initial.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0001_initial.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/__init__.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/__init__.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__pycache__/__init__.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/urls.py +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/django_codenerix_email.egg-info/dependency_links.txt +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/django_codenerix_email.egg-info/not-zip-safe +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/django_codenerix_email.egg-info/requires.txt +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/django_codenerix_email.egg-info/top_level.txt +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/setup.cfg +0 -0
- {django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: django-codenerix-email
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.6
|
|
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>
|
|
@@ -32,53 +32,71 @@ class EmailTemplateForm(GenModelForm):
|
|
|
32
32
|
exclude = []
|
|
33
33
|
|
|
34
34
|
def __groups__(self):
|
|
35
|
-
return [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
return [
|
|
36
|
+
(
|
|
37
|
+
_("Details"),
|
|
38
|
+
12,
|
|
39
|
+
["cid", 3],
|
|
40
|
+
["efrom", 9],
|
|
41
|
+
)
|
|
39
42
|
]
|
|
40
43
|
|
|
41
44
|
@staticmethod
|
|
42
45
|
def __groups_details__():
|
|
43
|
-
return [
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
return [
|
|
47
|
+
(
|
|
48
|
+
_("Details"),
|
|
49
|
+
12,
|
|
50
|
+
["cid", 3],
|
|
51
|
+
["efrom", 9],
|
|
52
|
+
)
|
|
46
53
|
]
|
|
47
54
|
|
|
48
55
|
|
|
49
56
|
class EmailMessageForm(GenModelForm):
|
|
50
57
|
class Meta:
|
|
51
58
|
model = EmailMessage
|
|
52
|
-
exclude = [
|
|
59
|
+
exclude = ["sending", "log"]
|
|
53
60
|
|
|
54
61
|
def __groups__(self):
|
|
55
|
-
return [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
return [
|
|
63
|
+
(
|
|
64
|
+
_("Details"),
|
|
65
|
+
12,
|
|
66
|
+
["efrom", 2],
|
|
67
|
+
["eto", 2],
|
|
68
|
+
["subject", 4],
|
|
69
|
+
["priority", 1],
|
|
70
|
+
["sent", 1],
|
|
71
|
+
["error", 1],
|
|
72
|
+
["retries", 1],
|
|
73
|
+
["body", 12],
|
|
74
|
+
)
|
|
65
75
|
]
|
|
66
76
|
|
|
67
77
|
@staticmethod
|
|
68
78
|
def __groups_details__():
|
|
69
|
-
return [
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
return [
|
|
80
|
+
(
|
|
81
|
+
_("Details"),
|
|
82
|
+
6,
|
|
83
|
+
["uuid", 3],
|
|
84
|
+
["efrom", 3],
|
|
85
|
+
["eto", 3],
|
|
86
|
+
["subject", 3],
|
|
87
|
+
["priority", 3],
|
|
88
|
+
["sending", 3],
|
|
89
|
+
["sent", 3],
|
|
90
|
+
["error", 3],
|
|
91
|
+
["retries", 3],
|
|
92
|
+
["opened", 3],
|
|
93
|
+
["log", 3],
|
|
94
|
+
),
|
|
95
|
+
(
|
|
96
|
+
_("Body"),
|
|
97
|
+
6,
|
|
98
|
+
["body", 3],
|
|
99
|
+
),
|
|
82
100
|
]
|
|
83
101
|
|
|
84
102
|
|
|
@@ -86,7 +104,9 @@ for info in MODELS:
|
|
|
86
104
|
field = info[0]
|
|
87
105
|
model = info[1]
|
|
88
106
|
for lang_code in settings.LANGUAGES_DATABASES:
|
|
89
|
-
query = "from codenerix_email.models import {}Text{}\n".format(
|
|
107
|
+
query = "from codenerix_email.models import {}Text{}\n".format(
|
|
108
|
+
model, lang_code
|
|
109
|
+
)
|
|
90
110
|
exec(query)
|
|
91
111
|
query = """
|
|
92
112
|
class {model}TextForm{lang}(GenModelForm):\n
|
|
@@ -106,4 +126,12 @@ class {model}TextForm{lang}(GenModelForm):\n
|
|
|
106
126
|
['subject', 12],
|
|
107
127
|
['body', 12],
|
|
108
128
|
)]\n"""
|
|
109
|
-
exec(
|
|
129
|
+
exec(
|
|
130
|
+
query.format(
|
|
131
|
+
model=model,
|
|
132
|
+
lang=lang_code,
|
|
133
|
+
languages="'{}'".format(
|
|
134
|
+
"','".join(settings.LANGUAGES_DATABASES)
|
|
135
|
+
),
|
|
136
|
+
)
|
|
137
|
+
)
|
|
@@ -24,7 +24,7 @@ from django.core.management.base import BaseCommand
|
|
|
24
24
|
from django.conf import settings
|
|
25
25
|
from django.utils import timezone
|
|
26
26
|
|
|
27
|
-
from
|
|
27
|
+
from codenerix_lib.debugger import Debugger
|
|
28
28
|
from codenerix_email.models import EmailMessage
|
|
29
29
|
|
|
30
30
|
|
|
@@ -36,32 +36,40 @@ class Command(BaseCommand, Debugger):
|
|
|
36
36
|
def add_arguments(self, parser):
|
|
37
37
|
|
|
38
38
|
# Named (optional) arguments
|
|
39
|
-
parser.add_argument(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"-d",
|
|
41
|
+
action="store_true",
|
|
42
|
+
dest="d",
|
|
43
|
+
default=False,
|
|
44
|
+
help="Keep the command working forever as a daemon",
|
|
45
|
+
)
|
|
44
46
|
|
|
45
47
|
# Named (optional) arguments
|
|
46
|
-
parser.add_argument(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--daemon",
|
|
50
|
+
action="store_true",
|
|
51
|
+
dest="daemon",
|
|
52
|
+
default=False,
|
|
53
|
+
help="Keep the command working forever as a daemon",
|
|
54
|
+
)
|
|
51
55
|
|
|
52
56
|
# Named (optional) arguments
|
|
53
|
-
parser.add_argument(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"-c",
|
|
59
|
+
action="store_true",
|
|
60
|
+
dest="c",
|
|
61
|
+
default=False,
|
|
62
|
+
help="Clear the sending status to all the Queue",
|
|
63
|
+
)
|
|
58
64
|
|
|
59
65
|
# Named (optional) arguments
|
|
60
|
-
parser.add_argument(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"--clear",
|
|
68
|
+
action="store_true",
|
|
69
|
+
dest="clear",
|
|
70
|
+
default=False,
|
|
71
|
+
help="Clear the sending status to all the Queue",
|
|
72
|
+
)
|
|
65
73
|
|
|
66
74
|
def handle(self, *args, **options):
|
|
67
75
|
|
|
@@ -70,13 +78,21 @@ class Command(BaseCommand, Debugger):
|
|
|
70
78
|
self.set_debug()
|
|
71
79
|
|
|
72
80
|
# Get user configuration
|
|
73
|
-
daemon = bool(options[
|
|
74
|
-
clear = bool(options[
|
|
75
|
-
BUCKET_SIZE = getattr(settings,
|
|
81
|
+
daemon = bool(options["daemon"] or options["d"])
|
|
82
|
+
clear = bool(options["clear"] or options["c"])
|
|
83
|
+
BUCKET_SIZE = getattr(settings, "CLIENT_EMAIL_BUCKETS", 10)
|
|
76
84
|
if daemon:
|
|
77
|
-
self.debug(
|
|
85
|
+
self.debug(
|
|
86
|
+
"Starting command in DAEMON mode with a queue of {} emails".format(
|
|
87
|
+
BUCKET_SIZE
|
|
88
|
+
),
|
|
89
|
+
color="cyan",
|
|
90
|
+
)
|
|
78
91
|
else:
|
|
79
|
-
self.debug(
|
|
92
|
+
self.debug(
|
|
93
|
+
"Starting a queue of {} emails".format(BUCKET_SIZE),
|
|
94
|
+
color="blue",
|
|
95
|
+
)
|
|
80
96
|
|
|
81
97
|
# In if requested set sending status for all the list to False
|
|
82
98
|
if clear:
|
|
@@ -90,7 +106,12 @@ class Command(BaseCommand, Debugger):
|
|
|
90
106
|
while first or daemon:
|
|
91
107
|
|
|
92
108
|
# Get a bucket of emails
|
|
93
|
-
emails = EmailMessage.objects.filter(
|
|
109
|
+
emails = EmailMessage.objects.filter(
|
|
110
|
+
sent=False,
|
|
111
|
+
sending=False,
|
|
112
|
+
error=False,
|
|
113
|
+
next_retry__lte=timezone.now(),
|
|
114
|
+
).order_by("priority", "next_retry")[0 : BUCKET_SIZE + 1]
|
|
94
115
|
|
|
95
116
|
# Check if there are emails to process
|
|
96
117
|
if emails:
|
|
@@ -99,15 +120,26 @@ class Command(BaseCommand, Debugger):
|
|
|
99
120
|
list_emails = [x.pk for x in emails]
|
|
100
121
|
|
|
101
122
|
# Set sending status for all the list
|
|
102
|
-
EmailMessage.objects.filter(pk__in=list_emails).update(
|
|
123
|
+
EmailMessage.objects.filter(pk__in=list_emails).update(
|
|
124
|
+
sending=True
|
|
125
|
+
)
|
|
103
126
|
|
|
104
127
|
# For each email
|
|
105
128
|
for email in emails:
|
|
106
|
-
self.debug(
|
|
129
|
+
self.debug(
|
|
130
|
+
"Sending to {}".format(email.eto),
|
|
131
|
+
color="white",
|
|
132
|
+
tail=False,
|
|
133
|
+
)
|
|
107
134
|
|
|
108
135
|
# Check if we have connection
|
|
109
136
|
if not connection:
|
|
110
|
-
self.debug(
|
|
137
|
+
self.debug(
|
|
138
|
+
" - Connecting",
|
|
139
|
+
color="yellow",
|
|
140
|
+
head=False,
|
|
141
|
+
tail=False,
|
|
142
|
+
)
|
|
111
143
|
connection = email.connect()
|
|
112
144
|
|
|
113
145
|
# Send the email
|
|
@@ -123,14 +155,25 @@ class Command(BaseCommand, Debugger):
|
|
|
123
155
|
email.save()
|
|
124
156
|
self.error(error)
|
|
125
157
|
if email.sent:
|
|
126
|
-
self.debug(" -> SENT", color=
|
|
158
|
+
self.debug(" -> SENT", color="green", head=False)
|
|
127
159
|
else:
|
|
128
|
-
self.debug(
|
|
129
|
-
|
|
160
|
+
self.debug(
|
|
161
|
+
" -> ERROR", color="red", head=False, tail=False
|
|
162
|
+
)
|
|
163
|
+
self.debug(
|
|
164
|
+
" ({} retries left)".format(
|
|
165
|
+
getattr(settings, "CLIENT_EMAIL_RETRIES", 10)
|
|
166
|
+
- email.retries
|
|
167
|
+
),
|
|
168
|
+
color="cyan",
|
|
169
|
+
head=False,
|
|
170
|
+
)
|
|
130
171
|
|
|
131
172
|
# Delete all that have been sent
|
|
132
|
-
if not getattr(settings,
|
|
133
|
-
EmailMessage.objects.filter(
|
|
173
|
+
if not getattr(settings, "CLIENT_EMAIL_HISTORY", True):
|
|
174
|
+
EmailMessage.objects.filter(
|
|
175
|
+
pk__in=list_emails, sent=True
|
|
176
|
+
).delete()
|
|
134
177
|
|
|
135
178
|
elif daemon:
|
|
136
179
|
|
|
@@ -138,12 +181,15 @@ class Command(BaseCommand, Debugger):
|
|
|
138
181
|
try:
|
|
139
182
|
time.sleep(10)
|
|
140
183
|
except KeyboardInterrupt:
|
|
141
|
-
self.debug("Exited by user request!", color=
|
|
184
|
+
self.debug("Exited by user request!", color="green")
|
|
142
185
|
break
|
|
143
186
|
|
|
144
187
|
else:
|
|
145
188
|
# No emails to send
|
|
146
|
-
self.debug(
|
|
189
|
+
self.debug(
|
|
190
|
+
"No emails to be sent at this moment in the queue!",
|
|
191
|
+
color="green",
|
|
192
|
+
)
|
|
147
193
|
|
|
148
194
|
# This was the first time
|
|
149
195
|
first = False
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
from django.core.management.base import BaseCommand
|
|
23
23
|
from django.conf import settings
|
|
24
24
|
|
|
25
|
-
from
|
|
25
|
+
from codenerix_lib.debugger import Debugger
|
|
26
26
|
from codenerix_email.models import EmailMessage
|
|
27
27
|
from codenerix_email import __version__
|
|
28
28
|
|
|
@@ -31,26 +31,28 @@ class Command(BaseCommand, Debugger):
|
|
|
31
31
|
|
|
32
32
|
# Show this when the user types help
|
|
33
33
|
help = "Test"
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
def handle(self, *args, **options):
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
# Autoconfigure Debugger
|
|
38
38
|
self.set_name("CODENERIX-EMAIL")
|
|
39
39
|
self.set_debug()
|
|
40
40
|
|
|
41
|
-
message =
|
|
41
|
+
message = """Hello,
|
|
42
42
|
|
|
43
43
|
this email has been sent using Django Codenerix Email.
|
|
44
44
|
|
|
45
45
|
Best regards, Codenerix Team
|
|
46
46
|
|
|
47
47
|
--
|
|
48
|
-
Django Codenerix Email v{}
|
|
48
|
+
Django Codenerix Email v{}""".format(
|
|
49
|
+
__version__
|
|
50
|
+
)
|
|
49
51
|
|
|
50
52
|
for name, email in settings.ADMINS:
|
|
51
53
|
email_message = EmailMessage()
|
|
52
54
|
email_message.efrom = settings.DEFAULT_FROM_EMAIL
|
|
53
55
|
email_message.eto = email
|
|
54
|
-
email_message.subject =
|
|
56
|
+
email_message.subject = "[Codenerix Email] Test"
|
|
55
57
|
email_message.body = message
|
|
56
58
|
email_message.send(legacy=False, silent=False)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Generated by Django 5.0.4 on 2024-05-22 11:41
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def create_uuid(apps, schema_editor):
|
|
8
|
+
EmailMessage = apps.get_model("codenerix_email", "EmailMessage")
|
|
9
|
+
for email_message in EmailMessage.objects.all():
|
|
10
|
+
email_message.uuid = uuid.uuid4()
|
|
11
|
+
email_message.save()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Migration(migrations.Migration):
|
|
15
|
+
|
|
16
|
+
dependencies = [
|
|
17
|
+
("codenerix_email", "0008_auto_20171201_0928"),
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
operations = [
|
|
21
|
+
migrations.AddField(
|
|
22
|
+
model_name="emailmessage",
|
|
23
|
+
name="opened",
|
|
24
|
+
field=models.DateTimeField(
|
|
25
|
+
blank=True, default=None, null=True, verbose_name="Opened"
|
|
26
|
+
),
|
|
27
|
+
),
|
|
28
|
+
migrations.AddField(
|
|
29
|
+
model_name="emailmessage",
|
|
30
|
+
name="uuid",
|
|
31
|
+
field=models.UUIDField(blank=True, null=True),
|
|
32
|
+
),
|
|
33
|
+
migrations.RunPython(create_uuid),
|
|
34
|
+
migrations.AlterField(
|
|
35
|
+
model_name="emailmessage",
|
|
36
|
+
name="uuid",
|
|
37
|
+
field=models.UUIDField(
|
|
38
|
+
default=uuid.uuid4,
|
|
39
|
+
editable=False,
|
|
40
|
+
unique=True,
|
|
41
|
+
verbose_name="UUID",
|
|
42
|
+
),
|
|
43
|
+
),
|
|
44
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import re
|
|
22
22
|
import ssl
|
|
23
23
|
import smtplib
|
|
24
|
+
from uuid import uuid4
|
|
24
25
|
|
|
25
26
|
from django.utils import timezone
|
|
26
27
|
from django.utils.translation import gettext_lazy as _
|
|
@@ -29,13 +30,24 @@ from django.template import Context, Template
|
|
|
29
30
|
from django.core.exceptions import ValidationError
|
|
30
31
|
from django.conf import settings
|
|
31
32
|
|
|
32
|
-
from codenerix.models import CodenerixModel
|
|
33
|
+
from codenerix.models import CodenerixModel # type: ignore
|
|
33
34
|
from codenerix_lib.debugger import Debugger
|
|
34
|
-
from codenerix.lib.genmail import
|
|
35
|
-
|
|
35
|
+
from codenerix.lib.genmail import ( # type: ignore # noqa: N817
|
|
36
|
+
EmailMessage as EM,
|
|
37
|
+
get_connection,
|
|
38
|
+
)
|
|
39
|
+
from codenerix.fields import WysiwygAngularField # type: ignore
|
|
36
40
|
|
|
37
41
|
|
|
38
42
|
class EmailMessage(CodenerixModel, Debugger):
|
|
43
|
+
uuid = models.UUIDField(
|
|
44
|
+
_("UUID"),
|
|
45
|
+
unique=True,
|
|
46
|
+
default=uuid4,
|
|
47
|
+
editable=False,
|
|
48
|
+
null=False,
|
|
49
|
+
blank=False,
|
|
50
|
+
)
|
|
39
51
|
efrom = models.EmailField(_("From"), blank=False, null=False)
|
|
40
52
|
eto = models.EmailField(_("To"), blank=False, null=False)
|
|
41
53
|
subject = models.CharField(
|
|
@@ -59,6 +71,9 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
59
71
|
)
|
|
60
72
|
next_retry = models.DateTimeField(_("Next retry"), auto_now_add=True)
|
|
61
73
|
log = models.TextField(_("Log"), blank=True, null=True)
|
|
74
|
+
opened = models.DateTimeField(
|
|
75
|
+
_("Opened"), null=True, blank=True, default=None
|
|
76
|
+
)
|
|
62
77
|
|
|
63
78
|
def __fields__(self, info):
|
|
64
79
|
fields = []
|
|
@@ -66,7 +81,9 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
66
81
|
fields.append(("error", None, 100))
|
|
67
82
|
fields.append(("sent", _("Send"), 100))
|
|
68
83
|
fields.append(("priority", _("Priority"), 100))
|
|
84
|
+
fields.append(("uuid", _("UUID"), 100))
|
|
69
85
|
fields.append(("created", _("Created"), 100))
|
|
86
|
+
fields.append(("opened", _("Opened"), 100))
|
|
70
87
|
fields.append(("efrom", _("From"), 100))
|
|
71
88
|
fields.append(("eto", _("To"), 100))
|
|
72
89
|
fields.append(("subject", _("Subject"), 100))
|
|
@@ -78,6 +95,10 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
78
95
|
def __unicode__(self):
|
|
79
96
|
return "{} ({})".format(self.eto, self.pk)
|
|
80
97
|
|
|
98
|
+
def set_opened(self):
|
|
99
|
+
self.opened = timezone.now()
|
|
100
|
+
self.save()
|
|
101
|
+
|
|
81
102
|
def connect(self, legacy=False):
|
|
82
103
|
"""
|
|
83
104
|
This class will return a connection instance, you can disconnect it with connection.close()
|
|
@@ -309,6 +330,7 @@ class EmailTemplate(CodenerixModel):
|
|
|
309
330
|
lang = settings.LANGUAGES_DATABASES[0].lower()
|
|
310
331
|
|
|
311
332
|
e = EmailMessage()
|
|
333
|
+
context["__emsg__uuid__"] = e.uuid
|
|
312
334
|
e.subject = Template(getattr(self, lang).subject).render(
|
|
313
335
|
Context(context)
|
|
314
336
|
)
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
<span ng-if='row.error' alt='{{data.meta.gentranslate.notsent}}' title='{{data.meta.gentranslate.notsent}}' codenerix-html-compile="false|codenerix"></span>
|
|
6
6
|
</td>
|
|
7
7
|
<td>{{row.priority|codenerix}}</td>
|
|
8
|
+
<td>{{row.uuid|codenerix}}</td>
|
|
8
9
|
<td>{{row.created|codenerix}}</td>
|
|
10
|
+
<td>{{row.opened|codenerix}}</td>
|
|
9
11
|
<td>{{row.efrom|codenerix}}</td>
|
|
10
12
|
<td>{{row.eto|codenerix}}</td>
|
|
11
13
|
<td>{{row.subject|codenerix}}</td>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# django-codenerix-email
|
|
4
|
+
#
|
|
5
|
+
# Codenerix GNU
|
|
6
|
+
#
|
|
7
|
+
# Project URL : http://www.codenerix.com
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
|
|
21
|
+
from django.urls import re_path
|
|
22
|
+
from codenerix_email.views import EmailFollow
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
urlpatterns = [
|
|
26
|
+
re_path(
|
|
27
|
+
r"^flw/(?P<uuid_ext>.*)$",
|
|
28
|
+
EmailFollow.as_view(),
|
|
29
|
+
name="CDNX_email_follow",
|
|
30
|
+
),
|
|
31
|
+
]
|
|
@@ -18,14 +18,19 @@
|
|
|
18
18
|
# See the License for the specific language governing permissions and
|
|
19
19
|
# limitations under the License.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
import base64
|
|
22
22
|
|
|
23
|
+
from typing import Optional, Tuple, List, Dict
|
|
24
|
+
from django.http import HttpResponse
|
|
25
|
+
from django.views.generic import View
|
|
26
|
+
|
|
27
|
+
from django.shortcuts import get_object_or_404
|
|
23
28
|
from django.utils.translation import gettext as _
|
|
24
29
|
from django.conf import settings
|
|
25
|
-
from django.http import HttpRequest
|
|
30
|
+
from django.http import HttpRequest, Http404
|
|
26
31
|
|
|
27
|
-
from codenerix.multiforms import MultiForm
|
|
28
|
-
from codenerix.views import (
|
|
32
|
+
from codenerix.multiforms import MultiForm # type: ignore
|
|
33
|
+
from codenerix.views import ( # type: ignore
|
|
29
34
|
GenList,
|
|
30
35
|
GenCreate,
|
|
31
36
|
GenCreateModal,
|
|
@@ -70,6 +75,38 @@ for info in MODELS:
|
|
|
70
75
|
)
|
|
71
76
|
|
|
72
77
|
|
|
78
|
+
# ############################################
|
|
79
|
+
# EmailFollow
|
|
80
|
+
class EmailFollow(View):
|
|
81
|
+
def get(self, request, *args, **kwargs):
|
|
82
|
+
|
|
83
|
+
# Get uuid from email
|
|
84
|
+
uid = kwargs.get("uuid_ext", None)
|
|
85
|
+
|
|
86
|
+
if uid:
|
|
87
|
+
|
|
88
|
+
# Get email message or return 404
|
|
89
|
+
email_message = get_object_or_404(EmailMessage, uuid=uid)
|
|
90
|
+
|
|
91
|
+
# Set email message as opened
|
|
92
|
+
if not email_message.opened:
|
|
93
|
+
email_message.set_opened()
|
|
94
|
+
email_message.set_opened()
|
|
95
|
+
|
|
96
|
+
# Return an image of 1x1 pixel
|
|
97
|
+
return HttpResponse(
|
|
98
|
+
base64.b64decode(
|
|
99
|
+
"R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="
|
|
100
|
+
),
|
|
101
|
+
content_type="image/gif",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
else:
|
|
105
|
+
|
|
106
|
+
# Return 404
|
|
107
|
+
raise Http404
|
|
108
|
+
|
|
109
|
+
|
|
73
110
|
# ############################################
|
|
74
111
|
# EmailTemplate
|
|
75
112
|
class EmailTemplateList(GenList):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: django-codenerix-email
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.6
|
|
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>
|
|
@@ -8,6 +8,7 @@ codenerix_email/apps.py
|
|
|
8
8
|
codenerix_email/forms.py
|
|
9
9
|
codenerix_email/models.py
|
|
10
10
|
codenerix_email/urls.py
|
|
11
|
+
codenerix_email/urls_frontend.py
|
|
11
12
|
codenerix_email/views.py
|
|
12
13
|
codenerix_email/management/__init__.py
|
|
13
14
|
codenerix_email/management/__pycache__/__init__.cpython-310.pyc
|
|
@@ -25,6 +26,7 @@ codenerix_email/migrations/0005_emailmessage_retries.py
|
|
|
25
26
|
codenerix_email/migrations/0006_emailmessage_error.py
|
|
26
27
|
codenerix_email/migrations/0007_emailmessage_next_retry.py
|
|
27
28
|
codenerix_email/migrations/0008_auto_20171201_0928.py
|
|
29
|
+
codenerix_email/migrations/0009_emailmessage_opened_emailmessage_uuid.py
|
|
28
30
|
codenerix_email/migrations/__init__.py
|
|
29
31
|
codenerix_email/migrations/__pycache__/0001_initial.cpython-310.pyc
|
|
30
32
|
codenerix_email/migrations/__pycache__/0001_initial.cpython-311.pyc
|
|
@@ -58,6 +60,9 @@ codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-310.pyc
|
|
|
58
60
|
codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-311.pyc
|
|
59
61
|
codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-35.pyc
|
|
60
62
|
codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-39.pyc
|
|
63
|
+
codenerix_email/migrations/__pycache__/0009_delete_emailtemplatetexten.cpython-311.pyc
|
|
64
|
+
codenerix_email/migrations/__pycache__/0009_emailmessage_opened_emailmessage_uuid.cpython-311.pyc
|
|
65
|
+
codenerix_email/migrations/__pycache__/0010_emailmessage_opened_emailmessage_uuid_and_more.cpython-311.pyc
|
|
61
66
|
codenerix_email/migrations/__pycache__/__init__.cpython-310.pyc
|
|
62
67
|
codenerix_email/migrations/__pycache__/__init__.cpython-311.pyc
|
|
63
68
|
codenerix_email/migrations/__pycache__/__init__.cpython-35.pyc
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/management/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django-codenerix-email-4.0.4 → django-codenerix-email-4.0.6}/codenerix_email/migrations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|