django-codenerix-email 4.0.10__tar.gz → 4.0.11__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.10/django_codenerix_email.egg-info → django-codenerix-email-4.0.11}/PKG-INFO +1 -1
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/__init__.py +1 -1
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/forms.py +21 -6
- django-codenerix-email-4.0.11/codenerix_email/management/commands/__pycache__/__init__.cpython-311.pyc +0 -0
- django-codenerix-email-4.0.11/codenerix_email/management/commands/__pycache__/send_emails.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/commands/send_emails.py +93 -44
- django-codenerix-email-4.0.11/codenerix_email/migrations/0010_emailmessage_content_subtype_and_more.py +35 -0
- django-codenerix-email-4.0.11/codenerix_email/migrations/0011_alter_emailmessage_content_subtype_and_more.py +33 -0
- django-codenerix-email-4.0.11/codenerix_email/migrations/__pycache__/0010_emailmessage_content_subtype_and_more.cpython-311.pyc +0 -0
- django-codenerix-email-4.0.11/codenerix_email/migrations/__pycache__/0011_alter_emailmessage_content_subtype_and_more.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/models.py +204 -45
- django-codenerix-email-4.0.11/codenerix_email/static/codenerix_email/partials/emailmessages_rows.html +29 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/views.py +2 -1
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11/django_codenerix_email.egg-info}/PKG-INFO +1 -1
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/django_codenerix_email.egg-info/SOURCES.txt +6 -0
- django-codenerix-email-4.0.10/codenerix_email/static/codenerix_email/partials/emailmessages_rows.html +0 -18
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/LICENSE +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/MANIFEST.in +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/README.rst +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/admin.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/apps.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/__init__.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/__pycache__/__init__.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/__pycache__/__init__.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/__pycache__/__init__.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/__pycache__/__init__.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/commands/__init__.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/management/commands/test_email.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0001_initial.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0002_auto_20170502_1043.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0003_auto_20170921_1206.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0004_auto_20171108_1628.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0005_emailmessage_retries.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0006_emailmessage_error.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0007_emailmessage_next_retry.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0008_auto_20171201_0928.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/0009_emailmessage_opened_emailmessage_uuid.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__init__.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0001_initial.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0001_initial.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0001_initial.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0001_initial.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0002_auto_20170502_1043.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0003_auto_20170921_1206.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0004_auto_20171108_1628.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0005_emailmessage_retries.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0006_emailmessage_error.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0007_emailmessage_next_retry.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0009_delete_emailtemplatetexten.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0009_emailmessage_opened_emailmessage_uuid.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/0010_emailmessage_opened_emailmessage_uuid_and_more.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/__init__.cpython-310.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/__init__.cpython-35.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/migrations/__pycache__/__init__.cpython-39.pyc +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/urls.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/urls_frontend.py +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/django_codenerix_email.egg-info/dependency_links.txt +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/django_codenerix_email.egg-info/not-zip-safe +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/django_codenerix_email.egg-info/requires.txt +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/django_codenerix_email.egg-info/top_level.txt +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/setup.cfg +0 -0
- {django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/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.11
|
|
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>
|
|
@@ -36,9 +36,18 @@ class EmailTemplateForm(GenModelForm):
|
|
|
36
36
|
(
|
|
37
37
|
_("Details"),
|
|
38
38
|
12,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
(
|
|
40
|
+
None,
|
|
41
|
+
3,
|
|
42
|
+
["cid", 12],
|
|
43
|
+
["content_subtype", 12],
|
|
44
|
+
),
|
|
45
|
+
(
|
|
46
|
+
None,
|
|
47
|
+
9,
|
|
48
|
+
["efrom", 9],
|
|
49
|
+
),
|
|
50
|
+
),
|
|
42
51
|
]
|
|
43
52
|
|
|
44
53
|
@staticmethod
|
|
@@ -81,20 +90,26 @@ class EmailMessageForm(GenModelForm):
|
|
|
81
90
|
_("Details"),
|
|
82
91
|
6,
|
|
83
92
|
["uuid", 3],
|
|
93
|
+
["created", 3],
|
|
94
|
+
["updated", 3],
|
|
84
95
|
["efrom", 3],
|
|
85
96
|
["eto", 3],
|
|
86
97
|
["subject", 3],
|
|
87
|
-
["
|
|
98
|
+
["opened", 3],
|
|
99
|
+
),
|
|
100
|
+
(
|
|
101
|
+
_("System"),
|
|
102
|
+
6,
|
|
88
103
|
["sending", 3],
|
|
89
104
|
["sent", 3],
|
|
90
105
|
["error", 3],
|
|
91
106
|
["retries", 3],
|
|
92
|
-
["
|
|
107
|
+
["priority", 3],
|
|
93
108
|
["log", 3],
|
|
94
109
|
),
|
|
95
110
|
(
|
|
96
111
|
_("Body"),
|
|
97
|
-
|
|
112
|
+
12,
|
|
98
113
|
["body", 3],
|
|
99
114
|
),
|
|
100
115
|
]
|
|
Binary file
|
|
Binary file
|
|
@@ -70,29 +70,58 @@ class Command(BaseCommand, Debugger):
|
|
|
70
70
|
default=False,
|
|
71
71
|
help="Clear the sending status to all the Queue",
|
|
72
72
|
)
|
|
73
|
+
# Named (optional) arguments
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"--verbose",
|
|
76
|
+
action="store_true",
|
|
77
|
+
dest="verbose",
|
|
78
|
+
default=False,
|
|
79
|
+
help="Enable verbose mode",
|
|
80
|
+
)
|
|
81
|
+
# Named (optional) arguments
|
|
82
|
+
parser.add_argument(
|
|
83
|
+
"--now",
|
|
84
|
+
action="store_true",
|
|
85
|
+
dest="now",
|
|
86
|
+
default=False,
|
|
87
|
+
help="Send now, do not wait the retry time",
|
|
88
|
+
)
|
|
89
|
+
# Named (optional) arguments
|
|
90
|
+
parser.add_argument(
|
|
91
|
+
"--all",
|
|
92
|
+
action="store_true",
|
|
93
|
+
dest="all",
|
|
94
|
+
default=False,
|
|
95
|
+
help="Send all, do not do on buckets",
|
|
96
|
+
)
|
|
73
97
|
|
|
74
98
|
def handle(self, *args, **options):
|
|
75
99
|
|
|
100
|
+
# Get user configuration
|
|
101
|
+
daemon = bool(options["daemon"] or options["d"])
|
|
102
|
+
clear = bool(options["clear"] or options["c"])
|
|
103
|
+
bucket_size = getattr(settings, "CLIENT_EMAIL_BUCKETS", 10)
|
|
104
|
+
verbose = bool(options.get("verbose", False))
|
|
105
|
+
sendnow = bool(options.get("now", False))
|
|
106
|
+
doall = bool(options.get("all", False))
|
|
107
|
+
|
|
76
108
|
# Autoconfigure Debugger
|
|
77
109
|
self.set_name("CODENERIX-EMAIL")
|
|
78
110
|
self.set_debug()
|
|
79
111
|
|
|
80
|
-
#
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"Starting a queue of {} emails".format(BUCKET_SIZE),
|
|
94
|
-
color="blue",
|
|
95
|
-
)
|
|
112
|
+
# Daemon
|
|
113
|
+
if verbose:
|
|
114
|
+
if daemon:
|
|
115
|
+
self.debug(
|
|
116
|
+
"Starting command in DAEMON mode with a "
|
|
117
|
+
f"queue of {bucket_size} emails",
|
|
118
|
+
color="cyan",
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
self.debug(
|
|
122
|
+
"Starting a queue of {} emails".format(bucket_size),
|
|
123
|
+
color="blue",
|
|
124
|
+
)
|
|
96
125
|
|
|
97
126
|
# In if requested set sending status for all the list to False
|
|
98
127
|
if clear:
|
|
@@ -110,8 +139,20 @@ class Command(BaseCommand, Debugger):
|
|
|
110
139
|
sent=False,
|
|
111
140
|
sending=False,
|
|
112
141
|
error=False,
|
|
113
|
-
|
|
114
|
-
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# If we do not have to send now we have to wait for the next retry
|
|
145
|
+
if not sendnow:
|
|
146
|
+
emails = emails.filter(
|
|
147
|
+
next_retry__lte=timezone.now(),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# Order emails by priority and next retry
|
|
151
|
+
emails = emails.order_by("priority", "next_retry")
|
|
152
|
+
|
|
153
|
+
# Send in buckets if we are not doing them all
|
|
154
|
+
if not doall:
|
|
155
|
+
emails = emails[0 : bucket_size + 1]
|
|
115
156
|
|
|
116
157
|
# Check if there are emails to process
|
|
117
158
|
if emails:
|
|
@@ -126,20 +167,22 @@ class Command(BaseCommand, Debugger):
|
|
|
126
167
|
|
|
127
168
|
# For each email
|
|
128
169
|
for email in emails:
|
|
129
|
-
|
|
130
|
-
"Sending to {}".format(email.eto),
|
|
131
|
-
color="white",
|
|
132
|
-
tail=False,
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
# Check if we have connection
|
|
136
|
-
if not connection:
|
|
170
|
+
if verbose:
|
|
137
171
|
self.debug(
|
|
138
|
-
"
|
|
139
|
-
color="
|
|
140
|
-
head=False,
|
|
172
|
+
"Sending to {}".format(email.eto),
|
|
173
|
+
color="white",
|
|
141
174
|
tail=False,
|
|
142
175
|
)
|
|
176
|
+
|
|
177
|
+
# Check if we have connection
|
|
178
|
+
if not connection:
|
|
179
|
+
if verbose:
|
|
180
|
+
self.debug(
|
|
181
|
+
" - Connecting",
|
|
182
|
+
color="yellow",
|
|
183
|
+
head=False,
|
|
184
|
+
tail=False,
|
|
185
|
+
)
|
|
143
186
|
connection = email.connect()
|
|
144
187
|
|
|
145
188
|
# Send the email
|
|
@@ -154,20 +197,26 @@ class Command(BaseCommand, Debugger):
|
|
|
154
197
|
email.log = error
|
|
155
198
|
email.save()
|
|
156
199
|
self.error(error)
|
|
157
|
-
if
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
200
|
+
if verbose:
|
|
201
|
+
if email.sent:
|
|
202
|
+
self.debug(" -> SENT", color="green", head=False)
|
|
203
|
+
else:
|
|
204
|
+
self.debug(
|
|
205
|
+
" -> ERROR",
|
|
206
|
+
color="red",
|
|
207
|
+
head=False,
|
|
208
|
+
tail=False,
|
|
209
|
+
)
|
|
210
|
+
self.debug(
|
|
211
|
+
" ({} retries left)".format(
|
|
212
|
+
getattr(
|
|
213
|
+
settings, "CLIENT_EMAIL_RETRIES", 10
|
|
214
|
+
)
|
|
215
|
+
- email.retries
|
|
216
|
+
),
|
|
217
|
+
color="cyan",
|
|
218
|
+
head=False,
|
|
219
|
+
)
|
|
171
220
|
|
|
172
221
|
# Delete all that have been sent
|
|
173
222
|
if not getattr(settings, "CLIENT_EMAIL_HISTORY", True):
|
|
@@ -184,7 +233,7 @@ class Command(BaseCommand, Debugger):
|
|
|
184
233
|
self.debug("Exited by user request!", color="green")
|
|
185
234
|
break
|
|
186
235
|
|
|
187
|
-
|
|
236
|
+
elif verbose:
|
|
188
237
|
# No emails to send
|
|
189
238
|
self.debug(
|
|
190
239
|
"No emails to be sent at this moment in the queue!",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generated by Django 5.0.6 on 2024-06-04 10:55
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("codenerix_email", "0009_emailmessage_opened_emailmessage_uuid"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name="emailmessage",
|
|
15
|
+
name="content_subtype",
|
|
16
|
+
field=models.CharField(
|
|
17
|
+
blank=True,
|
|
18
|
+
choices=[("plain", "Plain"), ("html", "HTML")],
|
|
19
|
+
default="html",
|
|
20
|
+
max_length=256,
|
|
21
|
+
verbose_name="Content Subtype",
|
|
22
|
+
),
|
|
23
|
+
),
|
|
24
|
+
migrations.AddField(
|
|
25
|
+
model_name="emailtemplate",
|
|
26
|
+
name="content_subtype",
|
|
27
|
+
field=models.CharField(
|
|
28
|
+
blank=True,
|
|
29
|
+
choices=[("plain", "Plain"), ("html", "HTML")],
|
|
30
|
+
default="html",
|
|
31
|
+
max_length=256,
|
|
32
|
+
verbose_name="Content Subtype",
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Generated by Django 5.0.6 on 2024-06-04 11:05
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("codenerix_email", "0010_emailmessage_content_subtype_and_more"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="emailmessage",
|
|
15
|
+
name="content_subtype",
|
|
16
|
+
field=models.CharField(
|
|
17
|
+
choices=[("plain", "Plain"), ("html", "HTML Web")],
|
|
18
|
+
default="html",
|
|
19
|
+
max_length=256,
|
|
20
|
+
verbose_name="Content Subtype",
|
|
21
|
+
),
|
|
22
|
+
),
|
|
23
|
+
migrations.AlterField(
|
|
24
|
+
model_name="emailtemplate",
|
|
25
|
+
name="content_subtype",
|
|
26
|
+
field=models.CharField(
|
|
27
|
+
choices=[("plain", "Plain"), ("html", "HTML Web")],
|
|
28
|
+
default="html",
|
|
29
|
+
max_length=256,
|
|
30
|
+
verbose_name="Content Subtype",
|
|
31
|
+
),
|
|
32
|
+
),
|
|
33
|
+
]
|
|
Binary file
|
|
Binary file
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
18
|
# See the License for the specific language governing permissions and
|
|
19
19
|
# limitations under the License.
|
|
20
|
+
#
|
|
21
|
+
# type: ignore
|
|
20
22
|
|
|
21
23
|
import re
|
|
22
24
|
import ssl
|
|
@@ -29,14 +31,22 @@ from django.db import models
|
|
|
29
31
|
from django.template import Context, Template
|
|
30
32
|
from django.core.exceptions import ValidationError
|
|
31
33
|
from django.conf import settings
|
|
34
|
+
from django.db.models import Q
|
|
32
35
|
|
|
33
|
-
from codenerix.models import CodenerixModel
|
|
36
|
+
from codenerix.models import CodenerixModel
|
|
34
37
|
from codenerix_lib.debugger import Debugger
|
|
35
|
-
from codenerix.lib.genmail import ( #
|
|
38
|
+
from codenerix.lib.genmail import ( # noqa: N817
|
|
36
39
|
EmailMessage as EM,
|
|
37
40
|
get_connection,
|
|
38
41
|
)
|
|
39
|
-
from codenerix.fields import WysiwygAngularField
|
|
42
|
+
from codenerix.fields import WysiwygAngularField
|
|
43
|
+
|
|
44
|
+
CONTENT_SUBTYPE_PLAIN = "plain"
|
|
45
|
+
CONTENT_SUBTYPE_HTML = "html"
|
|
46
|
+
CONTENT_SUBTYPES = (
|
|
47
|
+
(CONTENT_SUBTYPE_PLAIN, _("Plain")),
|
|
48
|
+
(CONTENT_SUBTYPE_HTML, _("HTML Web")),
|
|
49
|
+
)
|
|
40
50
|
|
|
41
51
|
|
|
42
52
|
class EmailMessage(CodenerixModel, Debugger):
|
|
@@ -74,24 +84,78 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
74
84
|
opened = models.DateTimeField(
|
|
75
85
|
_("Opened"), null=True, blank=True, default=None
|
|
76
86
|
)
|
|
87
|
+
content_subtype = models.CharField(
|
|
88
|
+
_("Content Subtype"),
|
|
89
|
+
max_length=256,
|
|
90
|
+
choices=CONTENT_SUBTYPES,
|
|
91
|
+
blank=False,
|
|
92
|
+
null=False,
|
|
93
|
+
default=CONTENT_SUBTYPE_HTML,
|
|
94
|
+
)
|
|
77
95
|
|
|
78
96
|
def __fields__(self, info):
|
|
79
97
|
fields = []
|
|
80
|
-
fields.append(("sending", None
|
|
81
|
-
fields.append(("error", None
|
|
82
|
-
fields.append(("sent", _("Send")
|
|
83
|
-
fields.append(("priority", _("Priority")
|
|
84
|
-
fields.append(("
|
|
85
|
-
fields.append(("
|
|
86
|
-
fields.append(("
|
|
87
|
-
fields.append(("
|
|
88
|
-
fields.append(("
|
|
89
|
-
fields.append(("
|
|
90
|
-
fields.append(("
|
|
91
|
-
fields.append(("
|
|
92
|
-
fields.append(("
|
|
98
|
+
fields.append(("sending", None))
|
|
99
|
+
fields.append(("error", None))
|
|
100
|
+
fields.append(("sent", _("Send")))
|
|
101
|
+
fields.append(("priority", _("Priority")))
|
|
102
|
+
fields.append(("updated", _("Updated")))
|
|
103
|
+
fields.append(("opened", _("Opened")))
|
|
104
|
+
fields.append(("efrom", _("From")))
|
|
105
|
+
fields.append(("eto", _("To")))
|
|
106
|
+
fields.append(("subject", _("Subject")))
|
|
107
|
+
fields.append(("retries", _("Retries")))
|
|
108
|
+
fields.append(("next_retry", _("Next retry")))
|
|
109
|
+
fields.append(("pk", _("ID")))
|
|
110
|
+
fields.append(("content_subtype", _("Content Subtype")))
|
|
111
|
+
fields.append(("uuid", _("UUID")))
|
|
93
112
|
return fields
|
|
94
113
|
|
|
114
|
+
def __searchQ__(self, info, search): # noqa: N802
|
|
115
|
+
answer = super().__searchQ__(info, search)
|
|
116
|
+
answer["uuid"] = Q(uuid__icontains=search)
|
|
117
|
+
answer["priority"] = Q(priority=search)
|
|
118
|
+
answer["efrom"] = Q(efrom__icontains=search)
|
|
119
|
+
answer["eto"] = Q(eto__icontains=search)
|
|
120
|
+
answer["retries"] = Q(retries=search)
|
|
121
|
+
answer["pk"] = Q(pk=search)
|
|
122
|
+
return answer
|
|
123
|
+
|
|
124
|
+
def __searchF__(self, info): # noqa: N802
|
|
125
|
+
def mailstatus(x):
|
|
126
|
+
if x == "D":
|
|
127
|
+
return Q(error=False, sent=True)
|
|
128
|
+
elif x == "P":
|
|
129
|
+
return Q(error=False, sent=False, sending=False)
|
|
130
|
+
elif x == "S":
|
|
131
|
+
return Q(error=False, sent=False, sending=True)
|
|
132
|
+
elif x == "E":
|
|
133
|
+
return Q(error=True)
|
|
134
|
+
else:
|
|
135
|
+
return Q()
|
|
136
|
+
|
|
137
|
+
mailoptions = [
|
|
138
|
+
("D", _("Sent")), # Sent - Done
|
|
139
|
+
("P", _("Pending")), # Pending - Pending
|
|
140
|
+
("S", _("Sending")), # Sending - Sending
|
|
141
|
+
("E", _("Error")), # Error - Error
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
"sent": (_("Sent"), lambda x: mailstatus(x), mailoptions),
|
|
146
|
+
"uuid": (_("UUID"), lambda x: Q(uuid__icontains=x), "input"),
|
|
147
|
+
"priority": (_("Priority"), lambda x: Q(priority=x), "input"),
|
|
148
|
+
"opened": (
|
|
149
|
+
_("Opened"),
|
|
150
|
+
lambda x: ~Q(opened__isnull=x),
|
|
151
|
+
[(True, _("Yes")), (False, _("No"))],
|
|
152
|
+
),
|
|
153
|
+
"efrom": (_("From"), lambda x: Q(efrom__icontains=x), "input"),
|
|
154
|
+
"eto": (_("To"), lambda x: Q(eto__icontains=x), "input"),
|
|
155
|
+
"retries": (_("Retries"), lambda x: Q(retries=x), "input"),
|
|
156
|
+
"pk": (_("ID"), lambda x: Q(pk=x), "input"),
|
|
157
|
+
}
|
|
158
|
+
|
|
95
159
|
def __unicode__(self):
|
|
96
160
|
return "{} ({})".format(self.eto, self.pk)
|
|
97
161
|
|
|
@@ -100,9 +164,63 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
100
164
|
self.opened = timezone.now()
|
|
101
165
|
self.save()
|
|
102
166
|
|
|
103
|
-
|
|
167
|
+
@classmethod
|
|
168
|
+
def process_queue(
|
|
169
|
+
cls, connection=None, legacy=False, silent=True, debug=False
|
|
170
|
+
):
|
|
104
171
|
"""
|
|
105
|
-
This
|
|
172
|
+
This method will process all the emails in the queue
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
# Process queue
|
|
176
|
+
emails = cls.objects.filter(
|
|
177
|
+
sent=False, error=False, next_retry__lte=timezone.now()
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Do we have to send emails
|
|
181
|
+
if emails.count():
|
|
182
|
+
|
|
183
|
+
# Get connection if not connected yet
|
|
184
|
+
if connection is None:
|
|
185
|
+
|
|
186
|
+
# Connect
|
|
187
|
+
connection = cls.internal_connect(legacy)
|
|
188
|
+
|
|
189
|
+
# Configure them as sending
|
|
190
|
+
emails.update(sending=True)
|
|
191
|
+
|
|
192
|
+
# Send them
|
|
193
|
+
for email in emails.order_by("priority"):
|
|
194
|
+
try:
|
|
195
|
+
email.send(
|
|
196
|
+
connection=connection,
|
|
197
|
+
legacy=legacy,
|
|
198
|
+
silent=silent,
|
|
199
|
+
debug=debug,
|
|
200
|
+
)
|
|
201
|
+
except Exception as e:
|
|
202
|
+
|
|
203
|
+
# Los the error into this email
|
|
204
|
+
if email.log is None:
|
|
205
|
+
email.log = ""
|
|
206
|
+
email.log += f"Error: {e}\n"
|
|
207
|
+
email.sending = False
|
|
208
|
+
email.save()
|
|
209
|
+
email.warning(f"Error at EmailMessage<{{email.pk}}>: {e}")
|
|
210
|
+
|
|
211
|
+
# Set all emails to not sending, since we are stopping now
|
|
212
|
+
emails.update(sending=False)
|
|
213
|
+
|
|
214
|
+
# Re-raise the exception
|
|
215
|
+
raise
|
|
216
|
+
|
|
217
|
+
emails.update(sending=False)
|
|
218
|
+
|
|
219
|
+
@classmethod
|
|
220
|
+
def internal_connect(cls, legacy=False):
|
|
221
|
+
"""
|
|
222
|
+
This class will return a connection instance, you can disconnect it
|
|
223
|
+
with connection.close()
|
|
106
224
|
"""
|
|
107
225
|
|
|
108
226
|
if not legacy:
|
|
@@ -119,15 +237,24 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
119
237
|
use_tls = settings.EMAIL_USE_TLS
|
|
120
238
|
|
|
121
239
|
# Remember last connection data
|
|
122
|
-
|
|
240
|
+
conect_info = {"host": host, "port": port, "use_tls": use_tls}
|
|
123
241
|
# Get connection
|
|
124
|
-
return
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
242
|
+
return (
|
|
243
|
+
get_connection(
|
|
244
|
+
host=host,
|
|
245
|
+
port=port,
|
|
246
|
+
username=username,
|
|
247
|
+
password=password,
|
|
248
|
+
use_tls=use_tls,
|
|
249
|
+
),
|
|
250
|
+
conect_info,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
def connect(self, legacy=False):
|
|
254
|
+
(connection, self.__connect_info) = EmailMessage.internal_connect(
|
|
255
|
+
legacy
|
|
130
256
|
)
|
|
257
|
+
return connection
|
|
131
258
|
|
|
132
259
|
def send(
|
|
133
260
|
self,
|
|
@@ -135,7 +262,7 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
135
262
|
legacy=False,
|
|
136
263
|
silent=True,
|
|
137
264
|
debug=False,
|
|
138
|
-
content_subtype=
|
|
265
|
+
content_subtype=None,
|
|
139
266
|
):
|
|
140
267
|
|
|
141
268
|
# Autoconfigure Debugger
|
|
@@ -143,6 +270,16 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
143
270
|
self.set_name("EmailMessage")
|
|
144
271
|
self.set_debug()
|
|
145
272
|
|
|
273
|
+
# Warn about subtype
|
|
274
|
+
if content_subtype:
|
|
275
|
+
self.warning(
|
|
276
|
+
_(
|
|
277
|
+
"Programming ERROR: You are using content_subtype, this "
|
|
278
|
+
"value has been DEPRECATED and will be remove in future "
|
|
279
|
+
"versions."
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
|
|
146
283
|
# Get connection if not connected yet
|
|
147
284
|
if connection is None:
|
|
148
285
|
# Connect
|
|
@@ -155,6 +292,7 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
155
292
|
self.set_name("EmailMessage->{}".format(self.eto))
|
|
156
293
|
|
|
157
294
|
# Manually open the connection
|
|
295
|
+
error = None
|
|
158
296
|
try:
|
|
159
297
|
connection.open()
|
|
160
298
|
except (
|
|
@@ -163,8 +301,6 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
163
301
|
TimeoutError,
|
|
164
302
|
) as e:
|
|
165
303
|
connection = None
|
|
166
|
-
if self.log is None:
|
|
167
|
-
self.log = ""
|
|
168
304
|
exceptiontxt = str(type(e)).split(".")[-1].split("'")[0]
|
|
169
305
|
ci = getattr(self, "__connect_info", {})
|
|
170
306
|
error = "{}: {} [HOST={}:{} TLS={}]\n".format(
|
|
@@ -175,12 +311,14 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
175
311
|
ci.get("use_tls", "-"),
|
|
176
312
|
)
|
|
177
313
|
self.warning(error)
|
|
178
|
-
self.log
|
|
179
|
-
|
|
314
|
+
if self.log is None:
|
|
315
|
+
self.log = ""
|
|
316
|
+
self.log += f"{error}\n"
|
|
317
|
+
# We will not retry anymore (for now)
|
|
180
318
|
self.sending = False
|
|
181
319
|
# We make lower this email's priority
|
|
182
320
|
self.priority += 1
|
|
183
|
-
# Set new retry
|
|
321
|
+
# Set we just made a new retry
|
|
184
322
|
self.retries += 1
|
|
185
323
|
self.next_retry = timezone.now() + timezone.timedelta(
|
|
186
324
|
seconds=getattr(
|
|
@@ -204,7 +342,7 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
204
342
|
[self.eto],
|
|
205
343
|
connection=connection,
|
|
206
344
|
)
|
|
207
|
-
email.content_subtype = content_subtype
|
|
345
|
+
email.content_subtype = self.content_subtype
|
|
208
346
|
for at in self.attachments.all():
|
|
209
347
|
with open(at.path) as f:
|
|
210
348
|
email.attach(at.filename, f.read(), at.mime)
|
|
@@ -212,6 +350,7 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
212
350
|
# send list emails
|
|
213
351
|
retries = 1
|
|
214
352
|
while retries + 1:
|
|
353
|
+
error = None
|
|
215
354
|
try:
|
|
216
355
|
if connection.send_messages([email]):
|
|
217
356
|
# We are done
|
|
@@ -219,27 +358,33 @@ class EmailMessage(CodenerixModel, Debugger):
|
|
|
219
358
|
self.sending = False
|
|
220
359
|
break
|
|
221
360
|
except ssl.SSLError as e:
|
|
222
|
-
error = "SSLError: {}\n"
|
|
361
|
+
error = f"SSLError: {e}\n"
|
|
223
362
|
self.warning(error)
|
|
224
|
-
self.log
|
|
363
|
+
if self.log is None:
|
|
364
|
+
self.log = ""
|
|
365
|
+
self.log += f"{error}\n"
|
|
225
366
|
except smtplib.SMTPServerDisconnected as e:
|
|
226
|
-
error = "SMTPServerDisconnected: {}\n"
|
|
367
|
+
error = f"SMTPServerDisconnected: {e}\n"
|
|
227
368
|
self.warning(error)
|
|
228
|
-
self.log
|
|
369
|
+
if self.log is None:
|
|
370
|
+
self.log = ""
|
|
371
|
+
self.log += f"{error}\n"
|
|
229
372
|
except smtplib.SMTPException as e:
|
|
230
|
-
error = "SMTPException: {}\n"
|
|
373
|
+
error = f"SMTPException: {e}\n"
|
|
231
374
|
self.warning(error)
|
|
232
|
-
self.log
|
|
375
|
+
if self.log is None:
|
|
376
|
+
self.log = ""
|
|
377
|
+
self.log += f"{error}\n"
|
|
233
378
|
finally:
|
|
234
379
|
# One chance less
|
|
235
380
|
retries -= 1
|
|
236
381
|
# Check if this is the last try
|
|
237
382
|
if not retries:
|
|
238
|
-
# We will not retry anymore
|
|
383
|
+
# We will not retry anymore (fow now)
|
|
239
384
|
self.sending = False
|
|
240
385
|
# We make lower this email's priority
|
|
241
386
|
self.priority += 1
|
|
242
|
-
# Set new retry
|
|
387
|
+
# Set we just made a new retry
|
|
243
388
|
self.retries += 1
|
|
244
389
|
self.next_retry = (
|
|
245
390
|
timezone.now()
|
|
@@ -293,12 +438,21 @@ class EmailTemplate(CodenerixModel):
|
|
|
293
438
|
_("CID"), unique=True, max_length=30, blank=False, null=False
|
|
294
439
|
)
|
|
295
440
|
efrom = models.TextField(_("From"), blank=True, null=False)
|
|
441
|
+
content_subtype = models.CharField(
|
|
442
|
+
_("Content Subtype"),
|
|
443
|
+
max_length=256,
|
|
444
|
+
choices=CONTENT_SUBTYPES,
|
|
445
|
+
blank=False,
|
|
446
|
+
null=False,
|
|
447
|
+
default=CONTENT_SUBTYPE_HTML,
|
|
448
|
+
)
|
|
296
449
|
|
|
297
450
|
def __fields__(self, info):
|
|
298
451
|
fields = []
|
|
299
452
|
fields.append(("pk", _("PK"), 100))
|
|
300
453
|
fields.append(("cid", _("CID"), 100))
|
|
301
454
|
fields.append(("efrom", _("From"), 100))
|
|
455
|
+
fields.append(("content_subtype", _("Content Subtype"), 100))
|
|
302
456
|
return fields
|
|
303
457
|
|
|
304
458
|
def __str__(self):
|
|
@@ -313,7 +467,8 @@ class EmailTemplate(CodenerixModel):
|
|
|
313
467
|
Usages:
|
|
314
468
|
EmailTemplate.get('PACO', ctx) => EmailMessage(): le falta el eto
|
|
315
469
|
> cid: PACO
|
|
316
|
-
EmailTemplate.get(pk='PACO', context=ctx) => EmailMessage(): le
|
|
470
|
+
EmailTemplate.get(pk='PACO', context=ctx) => EmailMessage(): le
|
|
471
|
+
falta el eto
|
|
317
472
|
> pk: PACO (we don't have CID)
|
|
318
473
|
"""
|
|
319
474
|
if cid:
|
|
@@ -337,6 +492,7 @@ class EmailTemplate(CodenerixModel):
|
|
|
337
492
|
)
|
|
338
493
|
e.body = Template(getattr(self, lang).body).render(Context(context))
|
|
339
494
|
e.efrom = Template(self.efrom).render(Context(context))
|
|
495
|
+
e.content_subtype = self.content_subtype
|
|
340
496
|
return e
|
|
341
497
|
|
|
342
498
|
def clean(self):
|
|
@@ -345,7 +501,8 @@ class EmailTemplate(CodenerixModel):
|
|
|
345
501
|
if len(re.findall(r"[A-Za-z0-9]+", self.cid)) != 1:
|
|
346
502
|
raise ValidationError(
|
|
347
503
|
_(
|
|
348
|
-
"CID can contains only number and letters with
|
|
504
|
+
"CID can contains only number and letters with "
|
|
505
|
+
"no spaces"
|
|
349
506
|
)
|
|
350
507
|
)
|
|
351
508
|
|
|
@@ -378,8 +535,10 @@ for info in MODELS:
|
|
|
378
535
|
field = info[0]
|
|
379
536
|
model = info[1]
|
|
380
537
|
for lang_code in settings.LANGUAGES_DATABASES:
|
|
381
|
-
query = "class {}Text{}(GenText):\n"
|
|
382
|
-
query +=
|
|
383
|
-
field
|
|
538
|
+
query = f"class {model}Text{lang_code}(GenText):\n"
|
|
539
|
+
query += (
|
|
540
|
+
f" {field} = models.OneToOneField({model}, "
|
|
541
|
+
f"on_delete=models.CASCADE, blank=False, null=False, "
|
|
542
|
+
f"related_name='{lang_code.lower()}')\n"
|
|
384
543
|
)
|
|
385
544
|
exec(query)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<td>
|
|
2
|
+
<center>
|
|
3
|
+
<span class='fa fa-refresh fa-spin fa-fw text-info' ng-if='!row.error && row.sending' alt='{{data.meta.gentranslate.sending}}...' title='{{data.meta.gentranslate.sending}}...'></span>
|
|
4
|
+
<span class='fa fa-envelope-o text-success' ng-if='!row.error && !row.sending && row.sent' alt='{{data.meta.gentranslate.sent}}' title='{{data.meta.gentranslate.sent}}'></span>
|
|
5
|
+
<span class='fa fa-envelope-open-o' ng-if='!row.error && !row.sending && !row.sent' alt='{{data.meta.gentranslate.waiting}}' title='{{data.meta.gentranslate.waiting}}'></span>
|
|
6
|
+
<span ng-if='row.error' alt='{{data.meta.gentranslate.notsent}}' title='{{data.meta.gentranslate.notsent}}' codenerix-html-compile="false|codenerix"></span>
|
|
7
|
+
</center>
|
|
8
|
+
</td>
|
|
9
|
+
<td><center>{{row.priority|codenerix}}</center></td>
|
|
10
|
+
<td class="text-nowrap">{{row.updated|codenerix}}</td>
|
|
11
|
+
<td>
|
|
12
|
+
<span title="{{row.opened}}" codenerix-html-compile="row.opened|codenerix:'bool'"><span>
|
|
13
|
+
</td>
|
|
14
|
+
<td>{{row.efrom|codenerix}}</td>
|
|
15
|
+
<td>{{row.eto|codenerix}}</td>
|
|
16
|
+
<td>{{row.subject|codenerix}}</td>
|
|
17
|
+
<td><center>{{row.retries|codenerix}}</center></td>
|
|
18
|
+
<td class="text-nowrap">{{row.next_retry|codenerix}}</td>
|
|
19
|
+
<td><center>{{row.pk|codenerix}}</center></td>
|
|
20
|
+
<td>
|
|
21
|
+
<center>
|
|
22
|
+
<button class="btn" title="{{row.content_subtype|codenerix}}">
|
|
23
|
+
<i ng-show="row.content_subtype=='plain'" class="fa fa-file-text-o" aria-hidden="true"></i>
|
|
24
|
+
<i ng-show="row.content_subtype=='html'" class="fa fa-code" aria-hidden="true"></i>
|
|
25
|
+
<i ng-hide="(row.content_subtype=='plain') || (row.content_subtype=='html')"class="fa fa-question-circle-o" aria-hidden="true"></i>
|
|
26
|
+
</button>
|
|
27
|
+
</center>
|
|
28
|
+
</td>
|
|
29
|
+
<td>{{row.uuid|codenerix}}</td>
|
|
@@ -144,7 +144,8 @@ class EmailTemplateDelete(GenDelete):
|
|
|
144
144
|
class EmailMessageList(GenList):
|
|
145
145
|
model = EmailMessage
|
|
146
146
|
show_details = True
|
|
147
|
-
|
|
147
|
+
search_filter_button = True
|
|
148
|
+
default_ordering = ["-updated"]
|
|
148
149
|
static_partial_row = "codenerix_email/partials/emailmessages_rows.html"
|
|
149
150
|
gentranslate = {
|
|
150
151
|
"sending": _("Sending"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: django-codenerix-email
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.11
|
|
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>
|
|
@@ -18,6 +18,8 @@ codenerix_email/management/__pycache__/__init__.cpython-39.pyc
|
|
|
18
18
|
codenerix_email/management/commands/__init__.py
|
|
19
19
|
codenerix_email/management/commands/send_emails.py
|
|
20
20
|
codenerix_email/management/commands/test_email.py
|
|
21
|
+
codenerix_email/management/commands/__pycache__/__init__.cpython-311.pyc
|
|
22
|
+
codenerix_email/management/commands/__pycache__/send_emails.cpython-311.pyc
|
|
21
23
|
codenerix_email/migrations/0001_initial.py
|
|
22
24
|
codenerix_email/migrations/0002_auto_20170502_1043.py
|
|
23
25
|
codenerix_email/migrations/0003_auto_20170921_1206.py
|
|
@@ -27,6 +29,8 @@ codenerix_email/migrations/0006_emailmessage_error.py
|
|
|
27
29
|
codenerix_email/migrations/0007_emailmessage_next_retry.py
|
|
28
30
|
codenerix_email/migrations/0008_auto_20171201_0928.py
|
|
29
31
|
codenerix_email/migrations/0009_emailmessage_opened_emailmessage_uuid.py
|
|
32
|
+
codenerix_email/migrations/0010_emailmessage_content_subtype_and_more.py
|
|
33
|
+
codenerix_email/migrations/0011_alter_emailmessage_content_subtype_and_more.py
|
|
30
34
|
codenerix_email/migrations/__init__.py
|
|
31
35
|
codenerix_email/migrations/__pycache__/0001_initial.cpython-310.pyc
|
|
32
36
|
codenerix_email/migrations/__pycache__/0001_initial.cpython-311.pyc
|
|
@@ -62,7 +66,9 @@ codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-35.pyc
|
|
|
62
66
|
codenerix_email/migrations/__pycache__/0008_auto_20171201_0928.cpython-39.pyc
|
|
63
67
|
codenerix_email/migrations/__pycache__/0009_delete_emailtemplatetexten.cpython-311.pyc
|
|
64
68
|
codenerix_email/migrations/__pycache__/0009_emailmessage_opened_emailmessage_uuid.cpython-311.pyc
|
|
69
|
+
codenerix_email/migrations/__pycache__/0010_emailmessage_content_subtype_and_more.cpython-311.pyc
|
|
65
70
|
codenerix_email/migrations/__pycache__/0010_emailmessage_opened_emailmessage_uuid_and_more.cpython-311.pyc
|
|
71
|
+
codenerix_email/migrations/__pycache__/0011_alter_emailmessage_content_subtype_and_more.cpython-311.pyc
|
|
66
72
|
codenerix_email/migrations/__pycache__/__init__.cpython-310.pyc
|
|
67
73
|
codenerix_email/migrations/__pycache__/__init__.cpython-311.pyc
|
|
68
74
|
codenerix_email/migrations/__pycache__/__init__.cpython-35.pyc
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<td>
|
|
2
|
-
<span class='fa fa-refresh fa-spin fa-fw text-info' ng-if='!row.error && row.sending' alt='{{data.meta.gentranslate.sending}}...' title='{{data.meta.gentranslate.sending}}...'></span>
|
|
3
|
-
<span class='fa fa-envelope-o text-success' ng-if='!row.error && !row.sending && row.sent' alt='{{data.meta.gentranslate.sent}}' title='{{data.meta.gentranslate.sent}}'></span>
|
|
4
|
-
<span class='fa fa-envelope-open-o' ng-if='!row.error && !row.sending && !row.sent' alt='{{data.meta.gentranslate.waiting}}' title='{{data.meta.gentranslate.waiting}}'></span>
|
|
5
|
-
<span ng-if='row.error' alt='{{data.meta.gentranslate.notsent}}' title='{{data.meta.gentranslate.notsent}}' codenerix-html-compile="false|codenerix"></span>
|
|
6
|
-
</td>
|
|
7
|
-
<td>{{row.priority|codenerix}}</td>
|
|
8
|
-
<td>{{row.uuid|codenerix}}</td>
|
|
9
|
-
<td class="text-nowrap">{{row.created|codenerix}}</td>
|
|
10
|
-
<td>
|
|
11
|
-
<span title="{{row.opened}}" codenerix-html-compile="row.opened|codenerix:'bool'"><span>
|
|
12
|
-
</td>
|
|
13
|
-
<td>{{row.efrom|codenerix}}</td>
|
|
14
|
-
<td>{{row.eto|codenerix}}</td>
|
|
15
|
-
<td>{{row.subject|codenerix}}</td>
|
|
16
|
-
<td>{{row.retries|codenerix}}</td>
|
|
17
|
-
<td class="text-nowrap">{{row.next_retry|codenerix}}</td>
|
|
18
|
-
<td>{{row.pk|codenerix}}</td>
|
|
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
|
|
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
|
{django-codenerix-email-4.0.10 → django-codenerix-email-4.0.11}/codenerix_email/urls_frontend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|