diff --git a/requirements/base.in b/requirements/base.in index e2888b2348..b783d2a35e 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -44,7 +44,7 @@ mozilla-django-oidc-db django-open-forms-client django-htmx playwright -django-yubin +django-mailer django-image-cropping django-log-outgoing-requests xsdata diff --git a/requirements/base.txt b/requirements/base.txt index 01169d06b3..921dd5a06b 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -29,9 +29,7 @@ brotli==1.0.9 cbor2==5.6.2 # via webauthn celery==5.2.7 - # via - # django-yubin - # notifications-api-common + # via notifications-api-common certifi==2023.11.17 # via # django-simple-certmanager @@ -106,6 +104,7 @@ django==4.2.10 # django-jsonform # django-localflavor # django-log-outgoing-requests + # django-mailer # django-open-forms-client # django-otp # django-phonenumber-field @@ -206,6 +205,8 @@ django-localflavor==3.1 # via -r requirements/base.in django-log-outgoing-requests==0.6.1 # via -r requirements/base.in +django-mailer==2.3.1 + # via -r requirements/base.in django-open-forms-client==0.3.0 # via -r requirements/base.in django-ordered-model==3.7.4 @@ -262,8 +263,6 @@ django-two-factor-auth[phonenumberslite,webauthn]==1.16.0 # via maykin-2fa django-view-breadcrumbs==2.5.1 # via -r requirements/base.in -django-yubin==2.0.3 - # via -r requirements/base.in djangocms-admin-style==3.2.3 # via django-cms djangocms-attributes-field==2.1.0 @@ -350,6 +349,8 @@ jsonschema==4.1.0 # via drf-spectacular kombu==5.2.4 # via celery +lockfile==0.12.2 + # via django-mailer lxml==4.9.1 # via # django-digid-eherkenning @@ -359,8 +360,6 @@ lxml==4.9.1 # xmlsec mail-editor @ git+https://github.com/maykinmedia/mail-editor.git@0.3.6 # via -r requirements/base.in -mail-parser==3.15.0 - # via django-yubin markdown==3.3.6 # via -r requirements/base.in markuppy==1.14 @@ -443,7 +442,6 @@ pytz==2021.3 # via # -r requirements/base.in # celery - # django-yubin # djangorestframework pyyaml==6.0 # via @@ -471,8 +469,6 @@ requests==2.31.0 # zgw-consumers sentry-sdk==1.38.0 # via -r requirements/base.in -simplejson==3.18.0 - # via mail-parser six==1.16.0 # via # click-repl @@ -481,7 +477,6 @@ six==1.16.0 # furl # html5lib # isodate - # mail-parser # orderedmultidict # python-dateutil # qrcode diff --git a/requirements/ci.txt b/requirements/ci.txt index 3e00b1ceb9..6bc30f3a76 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -67,7 +67,6 @@ celery==5.2.7 # via # -c requirements/base.txt # -r requirements/base.txt - # django-yubin # notifications-api-common certifi==2023.11.17 # via @@ -182,6 +181,7 @@ django==4.2.10 # django-jsonform # django-localflavor # django-log-outgoing-requests + # django-mailer # django-open-forms-client # django-otp # django-phonenumber-field @@ -338,6 +338,10 @@ django-log-outgoing-requests==0.6.1 # via # -c requirements/base.txt # -r requirements/base.txt +django-mailer==2.3.1 + # via + # -c requirements/base.txt + # -r requirements/base.txt django-open-forms-client==0.3.0 # via # -c requirements/base.txt @@ -437,10 +441,6 @@ django-view-breadcrumbs==2.5.1 # -r requirements/base.txt django-webtest==1.9.11 # via -r requirements/test-tools.in -django-yubin==2.0.3 - # via - # -c requirements/base.txt - # -r requirements/base.txt djangocms-admin-style==3.2.3 # via # -c requirements/base.txt @@ -616,6 +616,11 @@ kombu==5.2.4 # celery lazy-object-proxy==1.6.0 # via astroid +lockfile==0.12.2 + # via + # -c requirements/base.txt + # -r requirements/base.txt + # django-mailer lxml==4.9.1 # via # -c requirements/base.txt @@ -630,11 +635,6 @@ mail-editor @ git+https://github.com/maykinmedia/mail-editor.git@0.3.6 # via # -c requirements/base.txt # -r requirements/base.txt -mail-parser==3.15.0 - # via - # -c requirements/base.txt - # -r requirements/base.txt - # django-yubin markdown==3.3.6 # via # -c requirements/base.txt @@ -816,7 +816,6 @@ pytz==2021.3 # -c requirements/base.txt # -r requirements/base.txt # celery - # django-yubin # djangorestframework pyyaml==6.0 # via @@ -861,11 +860,6 @@ sentry-sdk==1.38.0 # via # -c requirements/base.txt # -r requirements/base.txt -simplejson==3.18.0 - # via - # -c requirements/base.txt - # -r requirements/base.txt - # mail-parser six==1.16.0 # via # -c requirements/base.txt @@ -876,7 +870,6 @@ six==1.16.0 # furl # html5lib # isodate - # mail-parser # orderedmultidict # python-dateutil # qrcode diff --git a/requirements/dev.txt b/requirements/dev.txt index 026d469620..cccca99f61 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -90,7 +90,6 @@ celery==5.2.7 # via # -c requirements/ci.txt # -r requirements/ci.txt - # django-yubin # notifications-api-common certifi==2023.11.17 # via @@ -220,6 +219,7 @@ django==4.2.10 # django-jsonform # django-localflavor # django-log-outgoing-requests + # django-mailer # django-open-forms-client # django-otp # django-phonenumber-field @@ -381,6 +381,10 @@ django-log-outgoing-requests==0.6.1 # via # -c requirements/ci.txt # -r requirements/ci.txt +django-mailer==2.3.1 + # via + # -c requirements/ci.txt + # -r requirements/ci.txt django-open-forms-client==0.3.0 # via # -c requirements/ci.txt @@ -484,10 +488,6 @@ django-webtest==1.9.11 # via # -c requirements/ci.txt # -r requirements/ci.txt -django-yubin==2.0.3 - # via - # -c requirements/ci.txt - # -r requirements/ci.txt djangocms-admin-style==3.2.3 # via # -c requirements/ci.txt @@ -710,6 +710,11 @@ lazy-object-proxy==1.6.0 # -c requirements/ci.txt # -r requirements/ci.txt # astroid +lockfile==0.12.2 + # via + # -c requirements/ci.txt + # -r requirements/ci.txt + # django-mailer locust==2.20.0 # via -r requirements/dev.in lxml==4.9.1 @@ -726,11 +731,6 @@ mail-editor @ git+https://github.com/maykinmedia/mail-editor.git@0.3.6 # via # -c requirements/ci.txt # -r requirements/ci.txt -mail-parser==3.15.0 - # via - # -c requirements/ci.txt - # -r requirements/ci.txt - # django-yubin markdown==3.3.6 # via # -c requirements/ci.txt @@ -952,7 +952,6 @@ pytz==2021.3 # -r requirements/ci.txt # babel # celery - # django-yubin # djangorestframework pyyaml==6.0 # via @@ -1006,11 +1005,6 @@ sentry-sdk==1.38.0 # via # -c requirements/ci.txt # -r requirements/ci.txt -simplejson==3.18.0 - # via - # -c requirements/ci.txt - # -r requirements/ci.txt - # mail-parser six==1.16.0 # via # -c requirements/ci.txt @@ -1022,7 +1016,6 @@ six==1.16.0 # geventhttpclient # html5lib # isodate - # mail-parser # orderedmultidict # python-dateutil # qrcode diff --git a/src/open_inwoner/conf/base.py b/src/open_inwoner/conf/base.py index d7b7da2635..b7f1ca3d55 100644 --- a/src/open_inwoner/conf/base.py +++ b/src/open_inwoner/conf/base.py @@ -194,7 +194,7 @@ "sessionprofile", "openformsclient", "django_htmx", - "django_yubin", + "mailer", "log_outgoing_requests", "formtools", # Project applications. @@ -340,7 +340,9 @@ DEFAULT_FROM_EMAIL = config("DEFAULT_FROM_EMAIL", default="openinwoner@maykinmedia.nl") -EMAIL_BACKEND = "django_yubin.smtp_queue.EmailBackend" + +EMAIL_BACKEND = "mailer.backend.DbBackend" +MAILER_EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" # # LOGGING diff --git a/src/open_inwoner/conf/fixtures/auth-groups.json b/src/open_inwoner/conf/fixtures/auth-groups.json deleted file mode 100644 index 1e7793b72c..0000000000 --- a/src/open_inwoner/conf/fixtures/auth-groups.json +++ /dev/null @@ -1 +0,0 @@ -[{"model": "auth.group", "fields": {"name": "Beheerder", "permissions": [["add_emailaddress", "account", "emailaddress"], ["change_emailaddress", "account", "emailaddress"], ["delete_emailaddress", "account", "emailaddress"], ["view_emailaddress", "account", "emailaddress"], ["add_emailconfirmation", "account", "emailconfirmation"], ["change_emailconfirmation", "account", "emailconfirmation"], ["delete_emailconfirmation", "account", "emailconfirmation"], ["view_emailconfirmation", "account", "emailconfirmation"], ["add_action", "accounts", "action"], ["change_action", "accounts", "action"], ["delete_action", "accounts", "action"], ["view_action", "accounts", "action"], ["add_contact", "accounts", "contact"], ["change_contact", "accounts", "contact"], ["delete_contact", "accounts", "contact"], ["view_contact", "accounts", "contact"], ["add_document", "accounts", "document"], ["change_document", "accounts", "document"], ["delete_document", "accounts", "document"], ["view_document", "accounts", "document"], ["add_invite", "accounts", "invite"], ["change_invite", "accounts", "invite"], ["delete_invite", "accounts", "invite"], ["view_invite", "accounts", "invite"], ["add_message", "accounts", "message"], ["change_message", "accounts", "message"], ["delete_message", "accounts", "message"], ["view_message", "accounts", "message"], ["add_user", "accounts", "user"], ["change_user", "accounts", "user"], ["delete_user", "accounts", "user"], ["view_user", "accounts", "user"], ["add_logentry", "admin", "logentry"], ["change_logentry", "admin", "logentry"], ["delete_logentry", "admin", "logentry"], ["view_logentry", "admin", "logentry"], ["add_appgroup", "admin_index", "appgroup"], ["change_appgroup", "admin_index", "appgroup"], ["delete_appgroup", "admin_index", "appgroup"], ["view_appgroup", "admin_index", "appgroup"], ["add_applink", "admin_index", "applink"], ["change_applink", "admin_index", "applink"], ["delete_applink", "admin_index", "applink"], ["view_applink", "admin_index", "applink"], ["add_contenttypeproxy", "admin_index", "contenttypeproxy"], ["change_contenttypeproxy", "admin_index", "contenttypeproxy"], ["delete_contenttypeproxy", "admin_index", "contenttypeproxy"], ["view_contenttypeproxy", "admin_index", "contenttypeproxy"], ["add_group", "auth", "group"], ["change_group", "auth", "group"], ["delete_group", "auth", "group"], ["view_group", "auth", "group"], ["add_permission", "auth", "permission"], ["change_permission", "auth", "permission"], ["delete_permission", "auth", "permission"], ["view_permission", "auth", "permission"], ["add_token", "authtoken", "token"], ["change_token", "authtoken", "token"], ["delete_token", "authtoken", "token"], ["view_token", "authtoken", "token"], ["add_tokenproxy", "authtoken", "tokenproxy"], ["change_tokenproxy", "authtoken", "tokenproxy"], ["delete_tokenproxy", "authtoken", "tokenproxy"], ["view_tokenproxy", "authtoken", "tokenproxy"], ["add_accessattempt", "axes", "accessattempt"], ["change_accessattempt", "axes", "accessattempt"], ["delete_accessattempt", "axes", "accessattempt"], ["view_accessattempt", "axes", "accessattempt"], ["add_accesslog", "axes", "accesslog"], ["change_accesslog", "axes", "accesslog"], ["delete_accesslog", "axes", "accesslog"], ["view_accesslog", "axes", "accesslog"], ["add_siteconfiguration", "configurations", "siteconfiguration"], ["change_siteconfiguration", "configurations", "siteconfiguration"], ["delete_siteconfiguration", "configurations", "siteconfiguration"], ["view_siteconfiguration", "configurations", "siteconfiguration"], ["add_siteconfigurationpage", "configurations", "siteconfigurationpage"], ["change_siteconfigurationpage", "configurations", "siteconfigurationpage"], ["delete_siteconfigurationpage", "configurations", "siteconfigurationpage"], ["view_siteconfigurationpage", "configurations", "siteconfigurationpage"], ["add_contenttype", "contenttypes", "contenttype"], ["change_contenttype", "contenttypes", "contenttype"], ["delete_contenttype", "contenttypes", "contenttype"], ["view_contenttype", "contenttypes", "contenttype"], ["add_cspreport", "cspreports", "cspreport"], ["change_cspreport", "cspreports", "cspreport"], ["delete_cspreport", "cspreports", "cspreport"], ["view_cspreport", "cspreports", "cspreport"], ["add_cspsetting", "custom_csp", "cspsetting"], ["change_cspsetting", "custom_csp", "cspsetting"], ["delete_cspsetting", "custom_csp", "cspsetting"], ["view_cspsetting", "custom_csp", "cspsetting"], ["view_blacklist", "django_yubin", "blacklist"], ["view_log", "django_yubin", "log"], ["view_message", "django_yubin", "message"], ["view_queuedmessage", "django_yubin", "queuedmessage"], ["add_source", "easy_thumbnails", "source"], ["change_source", "easy_thumbnails", "source"], ["delete_source", "easy_thumbnails", "source"], ["view_source", "easy_thumbnails", "source"], ["add_thumbnail", "easy_thumbnails", "thumbnail"], ["change_thumbnail", "easy_thumbnails", "thumbnail"], ["delete_thumbnail", "easy_thumbnails", "thumbnail"], ["view_thumbnail", "easy_thumbnails", "thumbnail"], ["add_thumbnaildimensions", "easy_thumbnails", "thumbnaildimensions"], ["change_thumbnaildimensions", "easy_thumbnails", "thumbnaildimensions"], ["delete_thumbnaildimensions", "easy_thumbnails", "thumbnaildimensions"], ["view_thumbnaildimensions", "easy_thumbnails", "thumbnaildimensions"], ["add_clipboard", "filer", "clipboard"], ["change_clipboard", "filer", "clipboard"], ["delete_clipboard", "filer", "clipboard"], ["view_clipboard", "filer", "clipboard"], ["add_clipboarditem", "filer", "clipboarditem"], ["change_clipboarditem", "filer", "clipboarditem"], ["delete_clipboarditem", "filer", "clipboarditem"], ["view_clipboarditem", "filer", "clipboarditem"], ["add_file", "filer", "file"], ["change_file", "filer", "file"], ["delete_file", "filer", "file"], ["view_file", "filer", "file"], ["add_folder", "filer", "folder"], ["can_use_directory_listing", "filer", "folder"], ["change_folder", "filer", "folder"], ["delete_folder", "filer", "folder"], ["view_folder", "filer", "folder"], ["add_folderpermission", "filer", "folderpermission"], ["change_folderpermission", "filer", "folderpermission"], ["delete_folderpermission", "filer", "folderpermission"], ["view_folderpermission", "filer", "folderpermission"], ["add_image", "filer", "image"], ["change_image", "filer", "image"], ["delete_image", "filer", "image"], ["view_image", "filer", "image"], ["add_thumbnailoption", "filer", "thumbnailoption"], ["change_thumbnailoption", "filer", "thumbnailoption"], ["delete_thumbnailoption", "filer", "thumbnailoption"], ["view_thumbnailoption", "filer", "thumbnailoption"], ["add_flatpage", "flatpages", "flatpage"], ["change_flatpage", "flatpages", "flatpage"], ["delete_flatpage", "flatpages", "flatpage"], ["view_flatpage", "flatpages", "flatpage"], ["add_haalcentraalconfig", "haalcentraal", "haalcentraalconfig"], ["change_haalcentraalconfig", "haalcentraal", "haalcentraalconfig"], ["delete_haalcentraalconfig", "haalcentraal", "haalcentraalconfig"], ["view_haalcentraalconfig", "haalcentraal", "haalcentraalconfig"], ["add_mailtemplate", "mail_editor", "mailtemplate"], ["change_mailtemplate", "mail_editor", "mailtemplate"], ["delete_mailtemplate", "mail_editor", "mailtemplate"], ["view_mailtemplate", "mail_editor", "mailtemplate"], ["add_openidconnectconfig", "mozilla_django_oidc_db", "openidconnectconfig"], ["change_openidconnectconfig", "mozilla_django_oidc_db", "openidconnectconfig"], ["delete_openidconnectconfig", "mozilla_django_oidc_db", "openidconnectconfig"], ["view_openidconnectconfig", "mozilla_django_oidc_db", "openidconnectconfig"], ["add_notificationsconfig", "notifications_api_common", "notificationsconfig"], ["change_notificationsconfig", "notifications_api_common", "notificationsconfig"], ["delete_notificationsconfig", "notifications_api_common", "notificationsconfig"], ["view_notificationsconfig", "notifications_api_common", "notificationsconfig"], ["add_subscription", "notifications_api_common", "subscription"], ["change_subscription", "notifications_api_common", "subscription"], ["delete_subscription", "notifications_api_common", "subscription"], ["view_subscription", "notifications_api_common", "subscription"], ["add_configuration", "openformsclient", "configuration"], ["change_configuration", "openformsclient", "configuration"], ["delete_configuration", "openformsclient", "configuration"], ["view_configuration", "openformsclient", "configuration"], ["add_catalogusconfig", "openzaak", "catalogusconfig"], ["change_catalogusconfig", "openzaak", "catalogusconfig"], ["delete_catalogusconfig", "openzaak", "catalogusconfig"], ["view_catalogusconfig", "openzaak", "catalogusconfig"], ["add_openzaakconfig", "openzaak", "openzaakconfig"], ["change_openzaakconfig", "openzaak", "openzaakconfig"], ["delete_openzaakconfig", "openzaak", "openzaakconfig"], ["view_openzaakconfig", "openzaak", "openzaakconfig"], ["add_usercaseinfoobjectnotification", "openzaak", "usercaseinfoobjectnotification"], ["change_usercaseinfoobjectnotification", "openzaak", "usercaseinfoobjectnotification"], ["delete_usercaseinfoobjectnotification", "openzaak", "usercaseinfoobjectnotification"], ["view_usercaseinfoobjectnotification", "openzaak", "usercaseinfoobjectnotification"], ["add_usercasestatusnotification", "openzaak", "usercasestatusnotification"], ["change_usercasestatusnotification", "openzaak", "usercasestatusnotification"], ["delete_usercasestatusnotification", "openzaak", "usercasestatusnotification"], ["view_usercasestatusnotification", "openzaak", "usercasestatusnotification"], ["add_zaaktypeconfig", "openzaak", "zaaktypeconfig"], ["change_zaaktypeconfig", "openzaak", "zaaktypeconfig"], ["delete_zaaktypeconfig", "openzaak", "zaaktypeconfig"], ["view_zaaktypeconfig", "openzaak", "zaaktypeconfig"], ["add_zaaktypeinformatieobjecttypeconfig", "openzaak", "zaaktypeinformatieobjecttypeconfig"], ["change_zaaktypeinformatieobjecttypeconfig", "openzaak", "zaaktypeinformatieobjecttypeconfig"], ["delete_zaaktypeinformatieobjecttypeconfig", "openzaak", "zaaktypeinformatieobjecttypeconfig"], ["view_zaaktypeinformatieobjecttypeconfig", "openzaak", "zaaktypeinformatieobjecttypeconfig"], ["add_staticdevice", "otp_static", "staticdevice"], ["change_staticdevice", "otp_static", "staticdevice"], ["delete_staticdevice", "otp_static", "staticdevice"], ["view_staticdevice", "otp_static", "staticdevice"], ["add_statictoken", "otp_static", "statictoken"], ["change_statictoken", "otp_static", "statictoken"], ["delete_statictoken", "otp_static", "statictoken"], ["view_statictoken", "otp_static", "statictoken"], ["add_totpdevice", "otp_totp", "totpdevice"], ["change_totpdevice", "otp_totp", "totpdevice"], ["delete_totpdevice", "otp_totp", "totpdevice"], ["view_totpdevice", "otp_totp", "totpdevice"], ["add_category", "pdc", "category"], ["change_category", "pdc", "category"], ["delete_category", "pdc", "category"], ["view_category", "pdc", "category"], ["add_neighbourhood", "pdc", "neighbourhood"], ["change_neighbourhood", "pdc", "neighbourhood"], ["delete_neighbourhood", "pdc", "neighbourhood"], ["view_neighbourhood", "pdc", "neighbourhood"], ["add_organization", "pdc", "organization"], ["change_organization", "pdc", "organization"], ["delete_organization", "pdc", "organization"], ["view_organization", "pdc", "organization"], ["add_organizationtype", "pdc", "organizationtype"], ["change_organizationtype", "pdc", "organizationtype"], ["delete_organizationtype", "pdc", "organizationtype"], ["view_organizationtype", "pdc", "organizationtype"], ["add_product", "pdc", "product"], ["change_product", "pdc", "product"], ["delete_product", "pdc", "product"], ["view_product", "pdc", "product"], ["add_productcondition", "pdc", "productcondition"], ["change_productcondition", "pdc", "productcondition"], ["delete_productcondition", "pdc", "productcondition"], ["view_productcondition", "pdc", "productcondition"], ["add_productcontact", "pdc", "productcontact"], ["change_productcontact", "pdc", "productcontact"], ["delete_productcontact", "pdc", "productcontact"], ["view_productcontact", "pdc", "productcontact"], ["add_productfile", "pdc", "productfile"], ["change_productfile", "pdc", "productfile"], ["delete_productfile", "pdc", "productfile"], ["view_productfile", "pdc", "productfile"], ["add_productlink", "pdc", "productlink"], ["change_productlink", "pdc", "productlink"], ["delete_productlink", "pdc", "productlink"], ["view_productlink", "pdc", "productlink"], ["add_productlocation", "pdc", "productlocation"], ["change_productlocation", "pdc", "productlocation"], ["delete_productlocation", "pdc", "productlocation"], ["view_productlocation", "pdc", "productlocation"], ["add_question", "pdc", "question"], ["change_question", "pdc", "question"], ["delete_question", "pdc", "question"], ["view_question", "pdc", "question"], ["add_tag", "pdc", "tag"], ["change_tag", "pdc", "tag"], ["delete_tag", "pdc", "tag"], ["view_tag", "pdc", "tag"], ["add_tagtype", "pdc", "tagtype"], ["change_tagtype", "pdc", "tagtype"], ["delete_tagtype", "pdc", "tagtype"], ["view_tagtype", "pdc", "tagtype"], ["add_actiontemplate", "plans", "actiontemplate"], ["change_actiontemplate", "plans", "actiontemplate"], ["delete_actiontemplate", "plans", "actiontemplate"], ["view_actiontemplate", "plans", "actiontemplate"], ["add_plan", "plans", "plan"], ["change_plan", "plans", "plan"], ["delete_plan", "plans", "plan"], ["view_plan", "plans", "plan"], ["add_plantemplate", "plans", "plantemplate"], ["change_plantemplate", "plans", "plantemplate"], ["delete_plantemplate", "plans", "plantemplate"], ["view_plantemplate", "plans", "plantemplate"], ["add_questionnairestep", "questionnaire", "questionnairestep"], ["change_questionnairestep", "questionnaire", "questionnairestep"], ["delete_questionnairestep", "questionnaire", "questionnairestep"], ["view_questionnairestep", "questionnaire", "questionnairestep"], ["add_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["change_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["delete_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["view_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["add_feedback", "search", "feedback"], ["change_feedback", "search", "feedback"], ["delete_feedback", "search", "feedback"], ["view_feedback", "search", "feedback"], ["add_fieldboost", "search", "fieldboost"], ["change_fieldboost", "search", "fieldboost"], ["delete_fieldboost", "search", "fieldboost"], ["view_fieldboost", "search", "fieldboost"], ["add_synonym", "search", "synonym"], ["change_synonym", "search", "synonym"], ["delete_synonym", "search", "synonym"], ["view_synonym", "search", "synonym"], ["add_sessionprofile", "sessionprofile", "sessionprofile"], ["change_sessionprofile", "sessionprofile", "sessionprofile"], ["delete_sessionprofile", "sessionprofile", "sessionprofile"], ["view_sessionprofile", "sessionprofile", "sessionprofile"], ["add_session", "sessions", "session"], ["change_session", "sessions", "session"], ["delete_session", "sessions", "session"], ["view_session", "sessions", "session"], ["add_certificate", "simple_certmanager", "certificate"], ["change_certificate", "simple_certmanager", "certificate"], ["delete_certificate", "simple_certmanager", "certificate"], ["view_certificate", "simple_certmanager", "certificate"], ["add_site", "sites", "site"], ["change_site", "sites", "site"], ["delete_site", "sites", "site"], ["view_site", "sites", "site"], ["add_socialaccount", "socialaccount", "socialaccount"], ["change_socialaccount", "socialaccount", "socialaccount"], ["delete_socialaccount", "socialaccount", "socialaccount"], ["view_socialaccount", "socialaccount", "socialaccount"], ["add_socialapp", "socialaccount", "socialapp"], ["change_socialapp", "socialaccount", "socialapp"], ["delete_socialapp", "socialaccount", "socialapp"], ["view_socialapp", "socialaccount", "socialapp"], ["add_socialtoken", "socialaccount", "socialtoken"], ["change_socialtoken", "socialaccount", "socialtoken"], ["delete_socialtoken", "socialaccount", "socialtoken"], ["view_socialtoken", "socialaccount", "socialtoken"], ["add_timelinelog", "timeline_logger", "timelinelog"], ["change_timelinelog", "timeline_logger", "timelinelog"], ["delete_timelinelog", "timeline_logger", "timelinelog"], ["view_timelinelog", "timeline_logger", "timelinelog"], ["add_phonedevice", "two_factor", "phonedevice"], ["change_phonedevice", "two_factor", "phonedevice"], ["delete_phonedevice", "two_factor", "phonedevice"], ["view_phonedevice", "two_factor", "phonedevice"], ["add_certificate", "zgw_consumers", "certificate"], ["change_certificate", "zgw_consumers", "certificate"], ["delete_certificate", "zgw_consumers", "certificate"], ["view_certificate", "zgw_consumers", "certificate"], ["add_nlxconfig", "zgw_consumers", "nlxconfig"], ["change_nlxconfig", "zgw_consumers", "nlxconfig"], ["delete_nlxconfig", "zgw_consumers", "nlxconfig"], ["view_nlxconfig", "zgw_consumers", "nlxconfig"], ["add_service", "zgw_consumers", "service"], ["change_service", "zgw_consumers", "service"], ["delete_service", "zgw_consumers", "service"], ["view_service", "zgw_consumers", "service"]]}}, {"model": "auth.group", "fields": {"name": "Begeleider", "permissions": [["view_emailaddress", "account", "emailaddress"], ["view_action", "accounts", "action"], ["view_document", "accounts", "document"], ["view_invite", "accounts", "invite"], ["view_message", "accounts", "message"], ["view_user", "accounts", "user"], ["add_file", "filer", "file"], ["change_file", "filer", "file"], ["view_file", "filer", "file"], ["view_actiontemplate", "plans", "actiontemplate"], ["add_plan", "plans", "plan"], ["change_plan", "plans", "plan"], ["view_plan", "plans", "plan"], ["view_plantemplate", "plans", "plantemplate"]]}}, {"model": "auth.group", "fields": {"name": "Contentbeheer", "permissions": [["add_clipboard", "filer", "clipboard"], ["change_clipboard", "filer", "clipboard"], ["delete_clipboard", "filer", "clipboard"], ["view_clipboard", "filer", "clipboard"], ["add_clipboarditem", "filer", "clipboarditem"], ["change_clipboarditem", "filer", "clipboarditem"], ["delete_clipboarditem", "filer", "clipboarditem"], ["view_clipboarditem", "filer", "clipboarditem"], ["add_file", "filer", "file"], ["change_file", "filer", "file"], ["delete_file", "filer", "file"], ["view_file", "filer", "file"], ["add_folder", "filer", "folder"], ["can_use_directory_listing", "filer", "folder"], ["change_folder", "filer", "folder"], ["delete_folder", "filer", "folder"], ["view_folder", "filer", "folder"], ["add_image", "filer", "image"], ["change_image", "filer", "image"], ["delete_image", "filer", "image"], ["view_image", "filer", "image"], ["add_flatpage", "flatpages", "flatpage"], ["change_flatpage", "flatpages", "flatpage"], ["view_flatpage", "flatpages", "flatpage"], ["add_category", "pdc", "category"], ["change_category", "pdc", "category"], ["delete_category", "pdc", "category"], ["view_category", "pdc", "category"], ["add_neighbourhood", "pdc", "neighbourhood"], ["change_neighbourhood", "pdc", "neighbourhood"], ["delete_neighbourhood", "pdc", "neighbourhood"], ["view_neighbourhood", "pdc", "neighbourhood"], ["add_organization", "pdc", "organization"], ["change_organization", "pdc", "organization"], ["delete_organization", "pdc", "organization"], ["view_organization", "pdc", "organization"], ["add_organizationtype", "pdc", "organizationtype"], ["change_organizationtype", "pdc", "organizationtype"], ["delete_organizationtype", "pdc", "organizationtype"], ["view_organizationtype", "pdc", "organizationtype"], ["add_product", "pdc", "product"], ["change_product", "pdc", "product"], ["delete_product", "pdc", "product"], ["view_product", "pdc", "product"], ["add_productcondition", "pdc", "productcondition"], ["change_productcondition", "pdc", "productcondition"], ["delete_productcondition", "pdc", "productcondition"], ["view_productcondition", "pdc", "productcondition"], ["add_productcontact", "pdc", "productcontact"], ["change_productcontact", "pdc", "productcontact"], ["delete_productcontact", "pdc", "productcontact"], ["view_productcontact", "pdc", "productcontact"], ["add_productfile", "pdc", "productfile"], ["change_productfile", "pdc", "productfile"], ["delete_productfile", "pdc", "productfile"], ["view_productfile", "pdc", "productfile"], ["add_productlink", "pdc", "productlink"], ["change_productlink", "pdc", "productlink"], ["delete_productlink", "pdc", "productlink"], ["view_productlink", "pdc", "productlink"], ["add_productlocation", "pdc", "productlocation"], ["change_productlocation", "pdc", "productlocation"], ["delete_productlocation", "pdc", "productlocation"], ["view_productlocation", "pdc", "productlocation"], ["add_question", "pdc", "question"], ["change_question", "pdc", "question"], ["delete_question", "pdc", "question"], ["view_question", "pdc", "question"], ["add_tag", "pdc", "tag"], ["change_tag", "pdc", "tag"], ["delete_tag", "pdc", "tag"], ["view_tag", "pdc", "tag"], ["add_tagtype", "pdc", "tagtype"], ["change_tagtype", "pdc", "tagtype"], ["delete_tagtype", "pdc", "tagtype"], ["view_tagtype", "pdc", "tagtype"], ["add_questionnairestep", "questionnaire", "questionnairestep"], ["change_questionnairestep", "questionnaire", "questionnairestep"], ["delete_questionnairestep", "questionnaire", "questionnairestep"], ["view_questionnairestep", "questionnaire", "questionnairestep"], ["add_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["change_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["delete_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["view_questionnairestepfile", "questionnaire", "questionnairestepfile"], ["add_feedback", "search", "feedback"], ["change_feedback", "search", "feedback"], ["delete_feedback", "search", "feedback"], ["view_feedback", "search", "feedback"], ["add_fieldboost", "search", "fieldboost"], ["change_fieldboost", "search", "fieldboost"], ["delete_fieldboost", "search", "fieldboost"], ["view_fieldboost", "search", "fieldboost"], ["add_synonym", "search", "synonym"], ["change_synonym", "search", "synonym"], ["delete_synonym", "search", "synonym"], ["view_synonym", "search", "synonym"], ["add_site", "sites", "site"], ["change_site", "sites", "site"], ["delete_site", "sites", "site"], ["view_site", "sites", "site"]]}}] diff --git a/src/open_inwoner/conf/fixtures/django-admin-index.json b/src/open_inwoner/conf/fixtures/django-admin-index.json index 193bc56189..58521bd35a 100644 --- a/src/open_inwoner/conf/fixtures/django-admin-index.json +++ b/src/open_inwoner/conf/fixtures/django-admin-index.json @@ -3,6 +3,7 @@ "model": "admin_index.appgroup", "fields": { "order": 0, + "translations": {}, "name": "Gebruikersprofielen", "slug": "accounts", "models": [ @@ -41,6 +42,7 @@ "model": "admin_index.appgroup", "fields": { "order": 2, + "translations": {}, "name": "PDC", "slug": "pdc", "models": [ @@ -99,6 +101,7 @@ "model": "admin_index.appgroup", "fields": { "order": 4, + "translations": {}, "name": "Permissies, 2FA en logging", "slug": "permissies-2fa-en-logging", "models": [ @@ -141,6 +144,7 @@ "model": "admin_index.appgroup", "fields": { "order": 10, + "translations": {}, "name": "Overige / Diverse", "slug": "overige-diverse", "models": [ @@ -183,6 +187,7 @@ "model": "admin_index.appgroup", "fields": { "order": 8, + "translations": {}, "name": "Configuratie", "slug": "configuratie", "models": [ @@ -217,6 +222,7 @@ "model": "admin_index.appgroup", "fields": { "order": 3, + "translations": {}, "name": "Zoeken", "slug": "zoeken", "models": [ @@ -239,6 +245,7 @@ "model": "admin_index.appgroup", "fields": { "order": 1, + "translations": {}, "name": "Plannen", "slug": "plannen", "models": [ @@ -261,24 +268,23 @@ "model": "admin_index.appgroup", "fields": { "order": 9, + "translations": { + "nl": "Emails" + }, "name": "Emails", "slug": "emails", "models": [ [ - "django_yubin", - "blacklist" + "mailer", + "dontsendentry" ], [ - "django_yubin", - "log" - ], - [ - "django_yubin", + "mailer", "message" ], [ - "django_yubin", - "queuedmessage" + "mailer", + "messagelog" ] ] } @@ -287,6 +293,7 @@ "model": "admin_index.appgroup", "fields": { "order": 5, + "translations": {}, "name": "Data koppelingen", "slug": "koppelingen", "models": [ @@ -357,6 +364,7 @@ "model": "admin_index.appgroup", "fields": { "order": 7, + "translations": {}, "name": "CMS", "slug": "cms", "models": [ @@ -407,6 +415,7 @@ "model": "admin_index.appgroup", "fields": { "order": 6, + "translations": {}, "name": "Inlog koppelingen", "slug": "auth-koppelingen", "models": [ @@ -441,6 +450,7 @@ "model": "admin_index.applink", "fields": { "order": 0, + "translations": {}, "app_group": [ "overige-diverse" ], @@ -452,6 +462,7 @@ "model": "admin_index.applink", "fields": { "order": 1, + "translations": {}, "app_group": [ "overige-diverse" ], @@ -463,6 +474,7 @@ "model": "admin_index.applink", "fields": { "order": 2, + "translations": {}, "app_group": [ "overige-diverse" ], diff --git a/src/open_inwoner/conf/local_example.py b/src/open_inwoner/conf/local_example.py index 62b07924a4..15dea5dcdb 100644 --- a/src/open_inwoner/conf/local_example.py +++ b/src/open_inwoner/conf/local_example.py @@ -24,3 +24,7 @@ MAIL_EDITOR_BASE_HOST = "http://localhost:8000" + +# optional to test mail queue +EMAIL_BACKEND = "mailer.backend.DbBackend" +MAILER_EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" diff --git a/src/open_inwoner/configurations/emails.py b/src/open_inwoner/configurations/emails.py index 28d368d56e..bc79dbb5af 100644 --- a/src/open_inwoner/configurations/emails.py +++ b/src/open_inwoner/configurations/emails.py @@ -1,10 +1,9 @@ from datetime import timedelta -from django.db.models import F from django.utils import timezone -from django_yubin.models import Log from mail_editor.helpers import find_template +from mailer.models import RESULT_SUCCESS, MessageLog from open_inwoner.configurations.models import SiteConfiguration @@ -15,15 +14,25 @@ def inform_admins_about_failing_emails(): if not inform_users: return - now = timezone.now() period_start = now - timedelta(days=1) - failed_email_logs = ( - Log.objects.filter(date__gt=period_start) - .annotate(subject=F("message__subject"), recipient=F("message__to_address")) - .values("subject", "recipient", "date") - ) + failed_email_objects = MessageLog.objects.filter( + when_attempted__gt=period_start + ).exclude(result=RESULT_SUCCESS) + + # wrap with what the existing mail-template expects + failed_email_logs = [] + for log in failed_email_objects: + # re-use expensive pickled .email property + email = log.email + failed_email_logs.append( + { + "subject": email.subject, + "recipient": ", ".join(email.to), + "date": log.when_attempted, + } + ) if not failed_email_logs: return diff --git a/src/open_inwoner/configurations/tests/test_emails.py b/src/open_inwoner/configurations/tests/test_emails.py index ca2b42cc01..7a6beae31a 100644 --- a/src/open_inwoner/configurations/tests/test_emails.py +++ b/src/open_inwoner/configurations/tests/test_emails.py @@ -1,13 +1,41 @@ +import uuid + from django.core import mail +from django.core.mail import EmailMessage from django.core.management import call_command from django.test import TestCase +from django.utils import timezone -from django_yubin.models import Log, Message from freezegun import freeze_time +from mailer.models import ( + PRIORITY_MEDIUM, + RESULT_FAILURE, + RESULT_SUCCESS, + MessageLog, + email_to_db, +) from ..models import SiteConfiguration +def make_message_log(to, subject, result): + """ + hand-craft a minimal version of what django-mailer stores as log + """ + assert isinstance(to, list) + data = EmailMessage(subject=subject, to=to, from_email="from@example.com") + + log = MessageLog.objects.create( + message_id=f"message_id-{uuid.uuid4()}", + # it wraps pickle and base64 + message_data=email_to_db(data), + result=result, + when_added=timezone.now(), + priority=PRIORITY_MEDIUM, + ) + return log + + class DailyFailingEmailDigestTestCase(TestCase): def test_no_recipients_configured(self): config = SiteConfiguration.get_solo() @@ -15,12 +43,7 @@ def test_no_recipients_configured(self): config.save() with freeze_time("2024-01-01T12:00:00"): - message = Message.objects.create( - subject="Some subject", - from_address="from@example.com", - to_address="to@example.com", - ) - Log.objects.create(message=message, log_message="Some ") + make_message_log(["to@example.com"], "failed message", RESULT_FAILURE) with freeze_time("2024-01-02T00:00:00"): call_command("send_failed_mail_digest") @@ -33,12 +56,7 @@ def test_no_failing_emails_in_past_24_hours(self): config.save() with freeze_time("2023-12-31T12:00:00"): - message = Message.objects.create( - subject="Some subject", - from_address="from@example.com", - to_address="to@example.com", - ) - Log.objects.create(message=message, log_message="Some msg") + make_message_log(["to@example.com"], "failed message", RESULT_FAILURE) with freeze_time("2024-01-02T00:00:00"): call_command("send_failed_mail_digest") @@ -51,20 +69,19 @@ def test_send_daily_failing_email_digest(self): config.save() with freeze_time("2023-12-31T12:00:00"): - message = Message.objects.create( - subject="Should not show up in email", - from_address="from@example.com", - to_address="to@example.com", + # out of date range + make_message_log( + ["to@example.com"], "Should not show up in email", RESULT_SUCCESS ) - Log.objects.create(message=message, log_message="Some msg") with freeze_time("2024-01-01T12:00:00"): - message = Message.objects.create( - subject="Should show up in email", - from_address="from@example.com", - to_address="to@example.com", + make_message_log( + ["to@example.com"], "Should show up in email", RESULT_FAILURE + ) + # in range but success + make_message_log( + ["to@example.com"], "Should not show up in email", RESULT_SUCCESS ) - Log.objects.create(message=message, log_message="Some msg") with freeze_time("2024-01-02T00:00:00"): call_command("send_failed_mail_digest") diff --git a/src/open_inwoner/kvk/client.py b/src/open_inwoner/kvk/client.py index 600284a97e..09d4ac68f3 100644 --- a/src/open_inwoner/kvk/client.py +++ b/src/open_inwoner/kvk/client.py @@ -4,7 +4,7 @@ from urllib.parse import urlencode import requests -from simplejson.errors import JSONDecodeError +from requests.exceptions import JSONDecodeError from .constants import CompanyType from .models import KvKConfig diff --git a/src/open_inwoner/urls.py b/src/open_inwoner/urls.py index 4f1b33901a..2f9af3dfc8 100644 --- a/src/open_inwoner/urls.py +++ b/src/open_inwoner/urls.py @@ -127,7 +127,6 @@ ), path("login/failure/", OIDCFailureView.as_view(), name="oidc-error"), path("faq/", FAQView.as_view(), name="general_faq"), - path("yubin/", include("django_yubin.urls")), path("apimock/", include("open_inwoner.apimock.urls")), path("kvk/", include("open_inwoner.kvk.urls")), # TODO move search to products cms app?