django-cms-qe 3.3.0__py3-none-any.whl → 3.4.1__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.
@@ -9,3 +9,6 @@ LOGIN_REDIRECT_URL = '/'
9
9
  LOGIN_URL = '/auth/login'
10
10
 
11
11
  CMS_QE_AUTH_ENABLED = False # Enable cms_qe_auth registration.
12
+
13
+ ALDRYN_FORMS_EMAIL_AVAILABILITY_CHECKER_FNC = 'cms_qe_auth.utils.smtp_server_accepts_email_address'
14
+ ALDRYN_FORMS_EMAIL_AVAILABILITY_CHECKER_CLASS = 'cms_qe_auth.utils.SMTPCheckRecipient'
cms_qe_auth/admin.py CHANGED
@@ -1,6 +1,33 @@
1
+ from django import forms
1
2
  from django.contrib import admin
2
3
  from django.contrib.auth.admin import UserAdmin
4
+ from django.core.exceptions import ValidationError
5
+ from django.utils.translation import gettext_lazy as _
3
6
 
4
7
  from .models import User
8
+ from .utils import smtp_server_accepts_email_address
5
9
 
6
- admin.register(User)(UserAdmin)
10
+
11
+ class CmsQeAuthUserForm(forms.ModelForm):
12
+
13
+ def clean(self):
14
+ field_name = "email"
15
+ if self.cleaned_data.get(field_name) and self.cleaned_data.get("is_active") and \
16
+ self.cleaned_data.get("is_staff"):
17
+ try:
18
+ smtp_server_accepts_email_address(self.cleaned_data[field_name])
19
+ except ValidationError as err:
20
+ msg = _("Enter a valid email or don't enter any.")
21
+ if "email" in self._errors:
22
+ self._errors[field_name].append(err)
23
+ self._errors[field_name].append(msg)
24
+ else:
25
+ self._errors[field_name] = self.error_class([err, msg])
26
+ return self.cleaned_data
27
+
28
+
29
+ class CmsQeAuthUserAdmin(UserAdmin):
30
+ form = CmsQeAuthUserForm
31
+
32
+
33
+ admin.register(User)(CmsQeAuthUserAdmin)
Binary file
@@ -329,3 +329,6 @@ msgstr ""
329
329
  "Jste přihlášen jako <strong>%(username)s</strong>.\n"
330
330
  "Chcete se <a href=\"%(logout_url)s?next=%(register_url)s>i tak registrovat</"
331
331
  "a>?"
332
+
333
+ msgid "Enter a valid email or don't enter any."
334
+ msgstr "Zadejte platný e-mail nebo nedávejte žádný."
cms_qe_auth/utils.py CHANGED
@@ -1,7 +1,18 @@
1
+ import logging
2
+ import smtplib
3
+ import socket
4
+ from typing import Optional
5
+
6
+ from django.conf import settings
1
7
  from django.contrib.auth import get_user_model
8
+ from django.core.exceptions import ValidationError
2
9
  from django.utils.encoding import force_bytes, force_str
3
10
  from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
4
11
 
12
+ ACTION_OK = 250 # Requested mail action okay, completed.
13
+
14
+ logger = logging.getLogger(__name__)
15
+
5
16
  # pylint:disable=invalid-name
6
17
 
7
18
 
@@ -21,3 +32,57 @@ def get_user_by_uidb64(uidb64):
21
32
  except (TypeError, ValueError, OverflowError, User.DoesNotExist):
22
33
  user = None
23
34
  return user
35
+
36
+
37
+ class ActionIsNoOkResponse(Exception):
38
+ """Action si not OK response."""
39
+
40
+
41
+ def check_smtp_response(response: tuple[int, bytes]) -> None:
42
+ """Check if response is valid."""
43
+ if response[0] != ACTION_OK:
44
+ raise ActionIsNoOkResponse(force_str(response[1]))
45
+
46
+
47
+ class SMTPCheckRecipient:
48
+ """SMTP server checks recipient email if the server accepts it."""
49
+
50
+ def __init__(self, hostname: str):
51
+ self.smtp: Optional[smtplib.SMTP] = None
52
+ self.hostname = hostname
53
+
54
+ def connect(self) -> None:
55
+ if self.hostname and self.smtp is None:
56
+ try:
57
+ self.smtp = smtplib.SMTP(self.hostname, timeout=5)
58
+ check_smtp_response(self.smtp.helo())
59
+ check_smtp_response(self.smtp.docmd('MAIL FROM:""'))
60
+ except (ActionIsNoOkResponse, OSError, socket.gaierror, smtplib.SMTPException) as error:
61
+ logger.error(error)
62
+
63
+ def close(self) -> None:
64
+ if self.smtp is not None and self.smtp.sock is not None:
65
+ self.smtp.close()
66
+
67
+ def __enter__(self):
68
+ return self
69
+
70
+ def __exit__(self, exc_type, exc_value, exc_tb):
71
+ self.close()
72
+
73
+ def check(self, address: str) -> None:
74
+ """Check if SMTP server accepts email address. Raise ValidationError if not."""
75
+ self.connect()
76
+ if self.smtp is not None and self.smtp.sock is not None:
77
+ try:
78
+ code, message = self.smtp.docmd(f'RCPT TO:{address}')
79
+ if code != ACTION_OK:
80
+ raise ValidationError(force_str(message), code="invalid")
81
+ except (socket.gaierror, smtplib.SMTPException) as error:
82
+ logger.error(error)
83
+
84
+
85
+ def smtp_server_accepts_email_address(address: str) -> None:
86
+ """SMTP server accepts email address. Raise ValidationError if not."""
87
+ with SMTPCheckRecipient(settings.EMAIL_HOST) as checker:
88
+ checker.check(address)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-cms-qe
3
- Version: 3.3.0
3
+ Version: 3.4.1
4
4
  Summary: Django CMS Quick & Easy provides all important modules to run new page withouta lot of coding. Aims to do it very easily and securely.
5
5
  Home-page: https://websites.pages.nic.cz/django-cms-qe
6
6
  Author: CZ.NIC, z.s.p.o.
@@ -48,7 +48,7 @@ cms_qe/settings/dev.py,sha256=51CBwiclE8LLoNB2uioIK_L3JhM1yzukQ0gZimkcFqw,1487
48
48
  cms_qe/settings/unittest.py,sha256=folLIMJb1Arh60_Sn0eNQrvIlx0OsAs6v1tDfyRZVuQ,514
49
49
  cms_qe/settings/base/__init__.py,sha256=5yHfne9gPD_xuTaG3voZP23yzuCwROmif2mmKs-hG_A,446
50
50
  cms_qe/settings/base/app.py,sha256=pmy_0ThkSDNXmEVrWwFpRQ-mjHCvYFoo8YxmFRLG5bM,3988
51
- cms_qe/settings/base/auth.py,sha256=axEmEG5UYxyY3EE0keQjGZzkTv2iwxwfULr4LcvZPns,207
51
+ cms_qe/settings/base/auth.py,sha256=OTr1LJ4RSMZm8STs4Q3pwPXmQoURax8OKLJ8eAj7PW4,395
52
52
  cms_qe/settings/base/cache.py,sha256=9p6C5lOz1pG-6k15PyvxlShUjBYIbU0ewpA8AX_YFus,297
53
53
  cms_qe/settings/base/cms.py,sha256=8icCNxcEp_KRDyP8-LXB21UurJL4wNysY39whAyt3I4,1855
54
54
  cms_qe/settings/base/constants.py,sha256=Rdq6ESg_J2B1Xm-ImEYM8pmsid-LqkSR7LXQdb3wlZU,7899
@@ -94,7 +94,7 @@ cms_qe_analytical/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
94
94
  cms_qe_analytical/templatetags/google_analytics.py,sha256=cN87jJzwVcjhqSS2JKTmPt9WntuBLnzxEcwgjrQMJSg,7370
95
95
  cms_qe_analytical/templatetags/piwik.py,sha256=EHOaojmewFpMqHzm_QCtCXGc_HGoiCJ_G-LPc8IfjM4,4131
96
96
  cms_qe_auth/__init__.py,sha256=SZS-CdmFLgIN4WGaUX_780L-vH0lqC7CdxKWjm_EuxE,867
97
- cms_qe_auth/admin.py,sha256=_Lj2OjIGRChal66ifTsin2iYW-UwLtd32WAT7__fLLY,140
97
+ cms_qe_auth/admin.py,sha256=PVxb9G_r6R4cyKvZUehENIN-aBSNDpqzA6O2gRbdQeQ,1135
98
98
  cms_qe_auth/apps.py,sha256=YiIgOI3Bxj4-7IZdxUEvHmTK1xS9fR2qMS-fe5AZ-W0,191
99
99
  cms_qe_auth/cms_menus.py,sha256=UxzzuMfOJCC_EiCkV2__6R5JKV9q1WGbTEgO7yLy8rE,1675
100
100
  cms_qe_auth/cms_plugins.py,sha256=USiNHaWdIJqPFUMLOjhuVam4nwOckujg1uguXNIs798,1575
@@ -103,15 +103,15 @@ cms_qe_auth/forms.py,sha256=x7sdFoOrKBLTJXqESedpIh6Kc1k5zZhL4vwnmhj1gH8,1137
103
103
  cms_qe_auth/models.py,sha256=Aro43D9y1zrS-3eKHVZEuSkchusDZAcj15B2vYcdt0Q,2713
104
104
  cms_qe_auth/token.py,sha256=DG4Bu8AVV-d1ayL4Oc9DXNnERt1sstrll80RBGrplx0,224
105
105
  cms_qe_auth/urls.py,sha256=RCgr9t1YonE0yR_8gXiXZIGESvQfrwVwlKhBOWmgxkw,2040
106
- cms_qe_auth/utils.py,sha256=d5K5i_YOahd1qCTc9gqRYQ3-docIKusDMS_Az0-cVT0,614
106
+ cms_qe_auth/utils.py,sha256=94aELOVicanApvKkZ3xw5sFjd2C8AEzyCrHdgpFW8Pc,2790
107
107
  cms_qe_auth/views.py,sha256=TG7kwG2xtRUt9S8nG3rUlNOU_BsfvRVybNexGpF_9uI,2233
108
108
  cms_qe_auth/boilerplates/bootstrap3/templates/cms_qe/auth/login_form.html,sha256=nG9X-nvfXA4_9h4lVJGIHdcYFhf7sNEg_rVPa6ze9a4,884
109
109
  cms_qe_auth/boilerplates/bootstrap3/templates/cms_qe/auth/password_change_form.html,sha256=1khb3qibf_YpVV2GyT6W9sgTMtFetNmjs2mbCdCFtIo,599
110
110
  cms_qe_auth/boilerplates/bootstrap3/templates/cms_qe/auth/password_reset_confirm.html,sha256=5x4jB2vKZIRG5CSUxsKKHnSF0laVsUALR4Vqo7ZgQTU,920
111
111
  cms_qe_auth/boilerplates/bootstrap3/templates/cms_qe/auth/password_reset_form.html,sha256=RforEA_H8W7EOIIFqeJtJ3H1FE8dsWgUW5vDVjzTIw4,571
112
112
  cms_qe_auth/boilerplates/bootstrap3/templates/cms_qe/auth/register_form.html,sha256=oyq6uHRx2DHzSO1j-AlV99xgaoRgF9zXdetfOUz0JQs,653
113
- cms_qe_auth/locale/cs/LC_MESSAGES/django.mo,sha256=0_J63-IStzcNYEQHC-9R75pILWbRc4Yz0QFMtqtTo2A,6609
114
- cms_qe_auth/locale/cs/LC_MESSAGES/django.po,sha256=WTbW4z7vgmywNG1sKsA5TKSGQPLFN9IKgFgDCPD2S7Y,11891
113
+ cms_qe_auth/locale/cs/LC_MESSAGES/django.mo,sha256=YhgQa3TxE9VvULZaMt4YJfC3HC8wU8pp_s4m2RMiXWU,6722
114
+ cms_qe_auth/locale/cs/LC_MESSAGES/django.po,sha256=pBsbpADrzEImaS-Ib4hCUGsW6sWC9MlbdXrpZsF5ZiM,11998
115
115
  cms_qe_auth/locale/en/LC_MESSAGES/django.mo,sha256=1Oza0kFTJYv1uLpu51-XbZShcMmsgRMPdKVmSFB0mZk,378
116
116
  cms_qe_auth/locale/en/LC_MESSAGES/django.po,sha256=oKfD16eQBOFiMYTJ_nMrhWiHUmTOqMkOEExuFfbZlb4,9205
117
117
  cms_qe_auth/migrations/0001_initial.py,sha256=6cJuHqIgIqa2G5jhCJfGFh6tWdAShujT5PHK9S38MDI,3403
@@ -3971,8 +3971,8 @@ test_selenium/pages/cms/__init__.py,sha256=_qe4YZYaQbrXp7Szmmeo4TUSkXlE5Rozu8E3t
3971
3971
  test_selenium/pages/cms/login.py,sha256=UPzJQcYff8NUAT4nvmfQoJQxzOJyPrJ_cKtH35NVfNg,521
3972
3972
  test_selenium/pages/cms/page.py,sha256=YQnpZkopfVnhoyQKpRDGqjNeV6xUl-pEHjEcZ9HRiPk,489
3973
3973
  test_selenium/pages/cms/wizard.py,sha256=yatbXH-rf1ap4O1hY0I13WikM3zkm_NrAiSK6bqENIU,545
3974
- django_cms_qe-3.3.0.dist-info/LICENSE,sha256=5wLaeUil0gfU9p8C4zn2Yu_PvZBNieUoYl0z9FcFWdA,1521
3975
- django_cms_qe-3.3.0.dist-info/METADATA,sha256=IqUIoCRDoEpA_bKnEWxPZK-8Fe2Phz-Ugxszg5B3Oco,4677
3976
- django_cms_qe-3.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
3977
- django_cms_qe-3.3.0.dist-info/top_level.txt,sha256=T4dauFwJy7FmxCy7WoQI3pPwiDessNB2LkfOAP76ssE,172
3978
- django_cms_qe-3.3.0.dist-info/RECORD,,
3974
+ django_cms_qe-3.4.1.dist-info/LICENSE,sha256=5wLaeUil0gfU9p8C4zn2Yu_PvZBNieUoYl0z9FcFWdA,1521
3975
+ django_cms_qe-3.4.1.dist-info/METADATA,sha256=4GwpR4Vo-XJx0k4xZRWxwjzjr4i4DF3IIYEImvYNW_8,4677
3976
+ django_cms_qe-3.4.1.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
3977
+ django_cms_qe-3.4.1.dist-info/top_level.txt,sha256=T4dauFwJy7FmxCy7WoQI3pPwiDessNB2LkfOAP76ssE,172
3978
+ django_cms_qe-3.4.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5