django-pfx 1.7.3.dev4__tar.gz → 1.7.3.dev8__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_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/.pre-commit-config.yaml +8 -8
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/PKG-INFO +4 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/django_pfx.egg-info/PKG-INFO +4 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/django_pfx.egg-info/SOURCES.txt +52 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/django_pfx.egg-info/requires.txt +4 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/conf.py +3 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/make_messages +1 -0
- django_pfx-1.7.3.dev8/pfx/emails/__init__.py +1 -0
- django_pfx-1.7.3.dev8/pfx/emails/apps.py +14 -0
- django_pfx-1.7.3.dev8/pfx/emails/email_backend/__init__.py +1 -0
- django_pfx-1.7.3.dev8/pfx/emails/email_backend/q_mailjet_email_backend.py +96 -0
- django_pfx-1.7.3.dev8/pfx/emails/exceptions.py +2 -0
- django_pfx-1.7.3.dev8/pfx/emails/mailjet/__init__.py +2 -0
- django_pfx-1.7.3.dev8/pfx/emails/mailjet/mailjet.py +18 -0
- django_pfx-1.7.3.dev8/pfx/emails/mailjet/message_result.py +32 -0
- django_pfx-1.7.3.dev8/pfx/emails/migrations/0001_initial.py +47 -0
- django_pfx-1.7.3.dev8/pfx/emails/migrations/0002_alter_email_headers.py +19 -0
- django_pfx-1.7.3.dev8/pfx/emails/migrations/0003_alter_email_options.py +18 -0
- django_pfx-1.7.3.dev8/pfx/emails/models/__init__.py +1 -0
- django_pfx-1.7.3.dev8/pfx/emails/models/email.py +378 -0
- django_pfx-1.7.3.dev8/pfx/emails/providers/__init__.py +1 -0
- django_pfx-1.7.3.dev8/pfx/emails/providers/email_django_q_executor.py +64 -0
- django_pfx-1.7.3.dev8/pfx/emails/shortcuts.py +117 -0
- django_pfx-1.7.3.dev8/pfx/emails/tasks.py +46 -0
- django_pfx-1.7.3.dev8/pfx/emails/templates/emails/base_template.html +89 -0
- django_pfx-1.7.3.dev8/pfx/emails/templates/emails/base_template.txt +7 -0
- django_pfx-1.7.3.dev8/pfx/emails/templates/emails/base_template_subject.txt +3 -0
- django_pfx-1.7.3.dev8/pfx/emails/urls.py +7 -0
- django_pfx-1.7.3.dev8/pfx/emails/views/__init__.py +1 -0
- django_pfx-1.7.3.dev8/pfx/emails/views/email_rest_view.py +44 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/__init__.py +0 -2
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/apps.py +15 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/default_settings.py +7 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/fields/media_field.py +19 -1
- django_pfx-1.7.3.dev8/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +26 -12
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/__init__.py +1 -0
- django_pfx-1.7.3.dev8/pfx/pfxcore/models/attachment_mixin.py +78 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/ordered_model_mixin.py +2 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/shortcuts.py +5 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/templates/registration/otp_code_email.txt +1 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/templates/registration/password_reset_email.txt +2 -2
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/templates/registration/welcome_email.txt +1 -1
- django_pfx-1.7.3.dev8/pfx/settings/dev.py +35 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/__init__.py +1 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/apps.py +18 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/locale/fr/LC_MESSAGES/django.mo +0 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/locale/fr/LC_MESSAGES/django.po +154 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/migrations/0001_initial.py +76 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/migrations/0002_alter_userjob_options_alter_userjob_auto_queued_and_more.py +100 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/models/__init__.py +2 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/models/user_job.py +217 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/models/user_job_attachment.py +32 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/providers/__init__.py +4 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/providers/user_job_django_q_executor.py +49 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/providers/user_job_websocket_channel_provider.py +30 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/tasks.py +72 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/urls.py +14 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/views/__init__.py +3 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/views/user_job_attachment_view.py +17 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/views/user_job_view.py +63 -0
- django_pfx-1.7.3.dev8/pfx/userjobs/views/user_websocket_consumer.py +65 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/requirements.txt +9 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/setup.cfg +1 -0
- django_pfx-1.7.3.dev8/tests/channel_group_send_calls.py +21 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/settings/common.py +29 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/__init__.py +7 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_auth_api.py +17 -14
- django_pfx-1.7.3.dev8/tests/tests/test_emails_email_api.py +86 -0
- django_pfx-1.7.3.dev8/tests/tests/test_emails_email_model.py +409 -0
- django_pfx-1.7.3.dev8/tests/tests/test_emails_q_mailjet_email_backend.py +175 -0
- django_pfx-1.7.3.dev8/tests/tests/test_emails_send_email_message.py +70 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_profiling_middleware.py +0 -1
- django_pfx-1.7.3.dev8/tests/tests/test_user_job_api.py +574 -0
- django_pfx-1.7.3.dev8/tests/tests/test_user_job_messages.py +128 -0
- django_pfx-1.7.3.dev8/tests/tests/test_user_job_model.py +302 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/urls.py +3 -1
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/settings/common.py +26 -0
- django_pfx-1.7.3.dev8/tests_custom_user/migrations/__init__.py +0 -0
- django_pfx-1.7.3.dev8/tests_custom_user/settings/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/settings/common.py +26 -0
- django_pfx-1.7.3.dev4/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
- django_pfx-1.7.3.dev4/pfx/settings/dev.py +0 -8
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/.gitignore +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/.gitlab-ci.yml +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/LICENSE +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/MANIFEST.in +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/README.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/django_pfx.egg-info/dependency_links.txt +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/django_pfx.egg-info/top_level.txt +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/Makefile +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/index.rst +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/api.views.rst +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/authentication.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/decorator.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/generate_openapi.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/getting_started.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/internationalisation.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/model.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/pfx_views.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/profiling.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/settings.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/doc/source/testing.md +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/img/pfx.png +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/img/pfx.svg +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/manage.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/__init__.py +0 -0
- {django_pfx-1.7.3.dev4/pfx/pfxcore/management → django_pfx-1.7.3.dev8/pfx/emails/migrations}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/apidoc/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/apidoc/parameters.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/apidoc/schema.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/apidoc/tags.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/decorator/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/decorator/rest.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/exceptions.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/fields/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/fields/decimal_field.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/fields/rich_text_field.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/http/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/http/json_response.py +0 -0
- {django_pfx-1.7.3.dev4/pfx/pfxcore/management/commands → django_pfx-1.7.3.dev8/pfx/pfxcore/management}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4/pfx/pfxcore/serializers → django_pfx-1.7.3.dev8/pfx/pfxcore/management/commands}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/management/commands/profile.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/middleware/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/middleware/authentication.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/middleware/locale.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/middleware/profiling.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/migrations/0004_alter_loginban_failed_counter_and_more.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/migrations/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/cache_mixins.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/login_ban.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/mfa_user_mixin.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/not_null_fields.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/pfx_models.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/pfx_user.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
- {django_pfx-1.7.3.dev4/pfx/pfxcore/sms/backends → django_pfx-1.7.3.dev8/pfx/pfxcore/serializers}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/serializers/json.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/settings.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/sms/__init__.py +0 -0
- {django_pfx-1.7.3.dev4/pfx/settings → django_pfx-1.7.3.dev8/pfx/pfxcore/sms/backends}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/sms/backends/base.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/sms/backends/console.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/storage/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/storage/exceptions.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/storage/local_storage.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/storage/s3_storage.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/test.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/urls.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/authentication_views.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/fields.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/filters_views.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/locale_views.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/media_rest_view_mixin.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/date_format.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/groups.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/list_count.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/list_items.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/list_order.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/list_search.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/subset.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pfx/pfxcore/views/rest_views.py +0 -0
- {django_pfx-1.7.3.dev4/tests → django_pfx-1.7.3.dev8/pfx/settings}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4/tests → django_pfx-1.7.3.dev8/pfx/userjobs}/migrations/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/pyproject.toml +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/serve-doc +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/setup.py +0 -0
- {django_pfx-1.7.3.dev4/tests/settings → django_pfx-1.7.3.dev8/tests}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/apps.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/migrations/0002_alter_book_cover.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/migrations/0003_book_local_file.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/migrations/0004_mfausermixin_fields.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/migrations/0005_mfausermixin_fields_fix.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/migrations/0006_rename_otp_enabled_user_mfa_authenticator_enabled_and_more.py +0 -0
- {django_pfx-1.7.3.dev4/tests_base_user → django_pfx-1.7.3.dev8/tests/migrations}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/models.py +0 -0
- {django_pfx-1.7.3.dev4/tests_base_user/migrations → django_pfx-1.7.3.dev8/tests/settings}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/settings/ci.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/settings/dev.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/settings/dev_default.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/basic_api_errors.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/basic_api_test.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_api_doc.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_api_doc_search.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_body_mixin.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_cache.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_client.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_fields_choices.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_fields_date.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_fields_decimal.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_fields_minutes_duration.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_fields_one2many.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_fields_rich_text.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_fields_time.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_filters.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_locale_api.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_perm_tests.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_permissions.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_perms_api.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_post_migrate_groups_update.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_settings.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_shortcuts.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_timezone_middleware.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_tools.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_user_queryset.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_view_decorators.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/tests/test_view_fields.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests/views.py +0 -0
- {django_pfx-1.7.3.dev4/tests_base_user/settings → django_pfx-1.7.3.dev8/tests_base_user}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.3.dev4/tests_custom_user → django_pfx-1.7.3.dev8/tests_base_user/migrations}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4/tests_custom_user/migrations → django_pfx-1.7.3.dev8/tests_base_user/settings}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/settings/ci.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/settings/dev.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/settings/dev_default.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/tests/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/tests/test_api.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/tests/test_auth_api.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/urls.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_base_user/views.py +0 -0
- {django_pfx-1.7.3.dev4/tests_custom_user/settings → django_pfx-1.7.3.dev8/tests_custom_user}/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/models.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/settings/ci.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/settings/dev.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/settings/dev_default.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/tests/__init__.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/tests/test_api.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/tests/test_auth_api.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/urls.py +0 -0
- {django_pfx-1.7.3.dev4 → django_pfx-1.7.3.dev8}/tests_custom_user/views.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
repos:
|
|
2
|
-
-
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
3
|
rev: v4.3.0
|
|
4
4
|
hooks:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
5
|
+
- id: check-yaml
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: trailing-whitespace
|
|
8
|
+
- repo: local
|
|
9
9
|
hooks:
|
|
10
10
|
- id: flake8
|
|
11
11
|
name: flake8
|
|
@@ -13,17 +13,17 @@ repos:
|
|
|
13
13
|
language: system
|
|
14
14
|
types: [python]
|
|
15
15
|
args: [--config=./setup.cfg]
|
|
16
|
-
-
|
|
16
|
+
- repo: local
|
|
17
17
|
hooks:
|
|
18
18
|
- id: isort
|
|
19
19
|
name: isort
|
|
20
20
|
entry: isort
|
|
21
21
|
language: system
|
|
22
22
|
types: [python]
|
|
23
|
-
-
|
|
23
|
+
- repo: local
|
|
24
24
|
hooks:
|
|
25
25
|
- id: make-messages
|
|
26
26
|
name: make messages
|
|
27
27
|
entry: ./make_messages
|
|
28
28
|
language: system
|
|
29
|
-
|
|
29
|
+
pass_filenames: false
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-pfx
|
|
3
|
-
Version: 1.7.3.
|
|
3
|
+
Version: 1.7.3.dev8
|
|
4
4
|
Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
|
|
5
5
|
Author: Hervé Martinet
|
|
6
6
|
Author-email: herve.martinet@gmail.com
|
|
@@ -37,6 +37,9 @@ Requires-Dist: dill
|
|
|
37
37
|
Requires-Dist: nh3
|
|
38
38
|
Provides-Extra: otp
|
|
39
39
|
Requires-Dist: pyotp; extra == "otp"
|
|
40
|
+
Provides-Extra: heic-converter
|
|
41
|
+
Requires-Dist: python-magic; extra == "heic-converter"
|
|
42
|
+
Requires-Dist: pillow-heif; extra == "heic-converter"
|
|
40
43
|
Dynamic: license-file
|
|
41
44
|
|
|
42
45
|
# Django PFX
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-pfx
|
|
3
|
-
Version: 1.7.3.
|
|
3
|
+
Version: 1.7.3.dev8
|
|
4
4
|
Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
|
|
5
5
|
Author: Hervé Martinet
|
|
6
6
|
Author-email: herve.martinet@gmail.com
|
|
@@ -37,6 +37,9 @@ Requires-Dist: dill
|
|
|
37
37
|
Requires-Dist: nh3
|
|
38
38
|
Provides-Extra: otp
|
|
39
39
|
Requires-Dist: pyotp; extra == "otp"
|
|
40
|
+
Provides-Extra: heic-converter
|
|
41
|
+
Requires-Dist: python-magic; extra == "heic-converter"
|
|
42
|
+
Requires-Dist: pillow-heif; extra == "heic-converter"
|
|
40
43
|
Dynamic: license-file
|
|
41
44
|
|
|
42
45
|
# Django PFX
|
|
@@ -33,6 +33,30 @@ doc/source/testing.md
|
|
|
33
33
|
img/pfx.png
|
|
34
34
|
img/pfx.svg
|
|
35
35
|
pfx/__init__.py
|
|
36
|
+
pfx/emails/__init__.py
|
|
37
|
+
pfx/emails/apps.py
|
|
38
|
+
pfx/emails/exceptions.py
|
|
39
|
+
pfx/emails/shortcuts.py
|
|
40
|
+
pfx/emails/tasks.py
|
|
41
|
+
pfx/emails/urls.py
|
|
42
|
+
pfx/emails/email_backend/__init__.py
|
|
43
|
+
pfx/emails/email_backend/q_mailjet_email_backend.py
|
|
44
|
+
pfx/emails/mailjet/__init__.py
|
|
45
|
+
pfx/emails/mailjet/mailjet.py
|
|
46
|
+
pfx/emails/mailjet/message_result.py
|
|
47
|
+
pfx/emails/migrations/0001_initial.py
|
|
48
|
+
pfx/emails/migrations/0002_alter_email_headers.py
|
|
49
|
+
pfx/emails/migrations/0003_alter_email_options.py
|
|
50
|
+
pfx/emails/migrations/__init__.py
|
|
51
|
+
pfx/emails/models/__init__.py
|
|
52
|
+
pfx/emails/models/email.py
|
|
53
|
+
pfx/emails/providers/__init__.py
|
|
54
|
+
pfx/emails/providers/email_django_q_executor.py
|
|
55
|
+
pfx/emails/templates/emails/base_template.html
|
|
56
|
+
pfx/emails/templates/emails/base_template.txt
|
|
57
|
+
pfx/emails/templates/emails/base_template_subject.txt
|
|
58
|
+
pfx/emails/views/__init__.py
|
|
59
|
+
pfx/emails/views/email_rest_view.py
|
|
36
60
|
pfx/pfxcore/__init__.py
|
|
37
61
|
pfx/pfxcore/apps.py
|
|
38
62
|
pfx/pfxcore/default_settings.py
|
|
@@ -73,6 +97,7 @@ pfx/pfxcore/migrations/operations/__init__.py
|
|
|
73
97
|
pfx/pfxcore/migrations/operations/permissions.py
|
|
74
98
|
pfx/pfxcore/models/__init__.py
|
|
75
99
|
pfx/pfxcore/models/abstract_pfx_base_user.py
|
|
100
|
+
pfx/pfxcore/models/attachment_mixin.py
|
|
76
101
|
pfx/pfxcore/models/cache_mixins.py
|
|
77
102
|
pfx/pfxcore/models/login_ban.py
|
|
78
103
|
pfx/pfxcore/models/mfa_user_mixin.py
|
|
@@ -125,8 +150,28 @@ pfx/pfxcore/views/parameters/subset_page_size.py
|
|
|
125
150
|
pfx/pfxcore/views/parameters/subset_page_subset.py
|
|
126
151
|
pfx/settings/__init__.py
|
|
127
152
|
pfx/settings/dev.py
|
|
153
|
+
pfx/userjobs/__init__.py
|
|
154
|
+
pfx/userjobs/apps.py
|
|
155
|
+
pfx/userjobs/tasks.py
|
|
156
|
+
pfx/userjobs/urls.py
|
|
157
|
+
pfx/userjobs/locale/fr/LC_MESSAGES/django.mo
|
|
158
|
+
pfx/userjobs/locale/fr/LC_MESSAGES/django.po
|
|
159
|
+
pfx/userjobs/migrations/0001_initial.py
|
|
160
|
+
pfx/userjobs/migrations/0002_alter_userjob_options_alter_userjob_auto_queued_and_more.py
|
|
161
|
+
pfx/userjobs/migrations/__init__.py
|
|
162
|
+
pfx/userjobs/models/__init__.py
|
|
163
|
+
pfx/userjobs/models/user_job.py
|
|
164
|
+
pfx/userjobs/models/user_job_attachment.py
|
|
165
|
+
pfx/userjobs/providers/__init__.py
|
|
166
|
+
pfx/userjobs/providers/user_job_django_q_executor.py
|
|
167
|
+
pfx/userjobs/providers/user_job_websocket_channel_provider.py
|
|
168
|
+
pfx/userjobs/views/__init__.py
|
|
169
|
+
pfx/userjobs/views/user_job_attachment_view.py
|
|
170
|
+
pfx/userjobs/views/user_job_view.py
|
|
171
|
+
pfx/userjobs/views/user_websocket_consumer.py
|
|
128
172
|
tests/__init__.py
|
|
129
173
|
tests/apps.py
|
|
174
|
+
tests/channel_group_send_calls.py
|
|
130
175
|
tests/models.py
|
|
131
176
|
tests/urls.py
|
|
132
177
|
tests/views.py
|
|
@@ -153,6 +198,10 @@ tests/tests/test_auth_api.py
|
|
|
153
198
|
tests/tests/test_body_mixin.py
|
|
154
199
|
tests/tests/test_cache.py
|
|
155
200
|
tests/tests/test_client.py
|
|
201
|
+
tests/tests/test_emails_email_api.py
|
|
202
|
+
tests/tests/test_emails_email_model.py
|
|
203
|
+
tests/tests/test_emails_q_mailjet_email_backend.py
|
|
204
|
+
tests/tests/test_emails_send_email_message.py
|
|
156
205
|
tests/tests/test_fields_choices.py
|
|
157
206
|
tests/tests/test_fields_date.py
|
|
158
207
|
tests/tests/test_fields_decimal.py
|
|
@@ -172,6 +221,9 @@ tests/tests/test_settings.py
|
|
|
172
221
|
tests/tests/test_shortcuts.py
|
|
173
222
|
tests/tests/test_timezone_middleware.py
|
|
174
223
|
tests/tests/test_tools.py
|
|
224
|
+
tests/tests/test_user_job_api.py
|
|
225
|
+
tests/tests/test_user_job_messages.py
|
|
226
|
+
tests/tests/test_user_job_model.py
|
|
175
227
|
tests/tests/test_user_queryset.py
|
|
176
228
|
tests/tests/test_view_decorators.py
|
|
177
229
|
tests/tests/test_view_fields.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .apps import EmailsConfig
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from django.apps import AppConfig
|
|
2
|
+
from django.db.models.signals import post_migrate
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EmailsConfig(AppConfig):
|
|
6
|
+
name = 'pfx.emails'
|
|
7
|
+
default = True
|
|
8
|
+
|
|
9
|
+
def ready(self):
|
|
10
|
+
from pfx.emails.models.email import get_executor
|
|
11
|
+
executor = get_executor()
|
|
12
|
+
executor.validate_setup()
|
|
13
|
+
post_migrate.connect(executor.register_periodic_tasks, sender=self)
|
|
14
|
+
super().ready()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .q_mailjet_email_backend import QMailjetEmailBackend
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import email.utils
|
|
3
|
+
import logging
|
|
4
|
+
from email.mime.base import MIMEBase
|
|
5
|
+
|
|
6
|
+
from django.core.mail import EmailMultiAlternatives
|
|
7
|
+
from django.core.mail.backends.base import BaseEmailBackend
|
|
8
|
+
|
|
9
|
+
from pfx.emails.models import get_email_model
|
|
10
|
+
from pfx.emails.shortcuts import default_mail_from, default_reply_to
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def getaddresses(fieldvalues):
|
|
14
|
+
return email.utils.getaddresses(fieldvalues, strict=False)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class QMailjetEmailBackend(BaseEmailBackend):
|
|
18
|
+
|
|
19
|
+
def send_messages(self, email_messages):
|
|
20
|
+
cnt = 0
|
|
21
|
+
for message in email_messages:
|
|
22
|
+
self.create_mail(message)
|
|
23
|
+
cnt += 1
|
|
24
|
+
return cnt
|
|
25
|
+
|
|
26
|
+
def create_extra_values(self, message):
|
|
27
|
+
return {}
|
|
28
|
+
|
|
29
|
+
def create_mail(self, message):
|
|
30
|
+
if not message.from_email:
|
|
31
|
+
mail_from = default_mail_from()
|
|
32
|
+
else:
|
|
33
|
+
mail_from = self.mail_dict(*getaddresses(
|
|
34
|
+
[message.from_email])[0])
|
|
35
|
+
|
|
36
|
+
parts = {}
|
|
37
|
+
if isinstance(message, EmailMultiAlternatives):
|
|
38
|
+
html_content = None
|
|
39
|
+
for content, mt in message.alternatives:
|
|
40
|
+
if mt == 'text/html':
|
|
41
|
+
html_content = content
|
|
42
|
+
parts['text_part'] = message.body
|
|
43
|
+
parts['html_part'] = html_content
|
|
44
|
+
elif message.content_subtype == "html":
|
|
45
|
+
parts['html_part'] = message.body
|
|
46
|
+
else:
|
|
47
|
+
parts['text_part'] = message.body
|
|
48
|
+
|
|
49
|
+
attachments = []
|
|
50
|
+
for msg_att in message.attachments:
|
|
51
|
+
if isinstance(msg_att, MIMEBase):
|
|
52
|
+
filename = msg_att.get_filename()
|
|
53
|
+
content_type = msg_att.get_content_type()
|
|
54
|
+
content = msg_att.get_payload(decode=True)
|
|
55
|
+
else:
|
|
56
|
+
filename, content, content_type = msg_att
|
|
57
|
+
if isinstance(content, str):
|
|
58
|
+
content = content.encode('utf-8')
|
|
59
|
+
attachments.append({
|
|
60
|
+
'ContentType': content_type,
|
|
61
|
+
'Filename': filename,
|
|
62
|
+
'Base64Content': base64.b64encode(content).decode('utf-8')})
|
|
63
|
+
|
|
64
|
+
headers = message.extra_headers
|
|
65
|
+
reply_to = default_reply_to()
|
|
66
|
+
if message.reply_to:
|
|
67
|
+
headers["Reply-To"] = ', '.join(message.reply_to)
|
|
68
|
+
elif not headers.get("Reply-To") and reply_to:
|
|
69
|
+
headers["Reply-To"] = reply_to
|
|
70
|
+
|
|
71
|
+
email = get_email_model()(
|
|
72
|
+
mail_from=mail_from,
|
|
73
|
+
mail_to=[
|
|
74
|
+
self.mail_dict(*e) for e in getaddresses(message.to)],
|
|
75
|
+
mail_cc=[
|
|
76
|
+
self.mail_dict(*e) for e in getaddresses(message.cc)],
|
|
77
|
+
mail_bcc=[
|
|
78
|
+
self.mail_dict(*e) for e in getaddresses(message.bcc)],
|
|
79
|
+
subject=message.subject,
|
|
80
|
+
headers=headers,
|
|
81
|
+
attachments=attachments,
|
|
82
|
+
send_mode=getattr(message, 'send_mode', 'auto_async'),
|
|
83
|
+
**parts,
|
|
84
|
+
**self.create_extra_values(message))
|
|
85
|
+
email.full_clean()
|
|
86
|
+
email.save()
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
def mail_dict(name, mail):
|
|
90
|
+
res = {'Email': mail}
|
|
91
|
+
if name:
|
|
92
|
+
res['Name'] = name
|
|
93
|
+
return res
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
logger = logging.getLogger(__name__)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def Mailjet(version='v3'):
|
|
5
|
+
try:
|
|
6
|
+
from mailjet_rest.client import Client
|
|
7
|
+
except Exception as e:
|
|
8
|
+
raise RuntimeError(
|
|
9
|
+
"mailjet_rest library missing.") from e
|
|
10
|
+
|
|
11
|
+
key_public = getattr(settings, 'PFX_MJ_APIKEY_PUBLIC', None)
|
|
12
|
+
key_private = getattr(settings, 'PFX_MJ_APIKEY_PRIVATE', None)
|
|
13
|
+
try:
|
|
14
|
+
return Client(auth=(key_public, key_private), version=version)
|
|
15
|
+
except Exception as e:
|
|
16
|
+
raise RuntimeError(
|
|
17
|
+
"Invalid PFX_MJ_APIKEY_PUBLIC and/or "
|
|
18
|
+
"PFX_MJ_APIKEY_PRIVATE settings") from e
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Event:
|
|
7
|
+
def __init__(self, json):
|
|
8
|
+
self.json = json
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def status(self):
|
|
12
|
+
return self.json.get("Status", 'unknown')
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def is_permanent(self):
|
|
16
|
+
return self.status == 'sent' or self.json.get("StatePermanent")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Message:
|
|
20
|
+
def __init__(self, json):
|
|
21
|
+
self.json = json
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def event(self):
|
|
25
|
+
events = self.json.get('Data', [])
|
|
26
|
+
return Event(events and "Status" in events[0] and events[0] or {})
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class MessageResult(Message):
|
|
30
|
+
def __init__(self, result):
|
|
31
|
+
super().__init__(result.json())
|
|
32
|
+
self.status_code = result.status_code
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Generated by Django 4.2.30 on 2026-05-27 09:11
|
|
2
|
+
# flake8: noqa
|
|
3
|
+
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
import pfx.emails.shortcuts
|
|
7
|
+
import pfx.pfxcore.models.not_null_fields
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Migration(migrations.Migration):
|
|
11
|
+
|
|
12
|
+
initial = True
|
|
13
|
+
|
|
14
|
+
dependencies = [
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
operations = [
|
|
18
|
+
migrations.CreateModel(
|
|
19
|
+
name='Email',
|
|
20
|
+
fields=[
|
|
21
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
22
|
+
('send_date', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Send date')),
|
|
23
|
+
('mail_from', models.JSONField(default=pfx.emails.shortcuts.default_mail_from, verbose_name='Mail From')),
|
|
24
|
+
('mail_to', models.JSONField(default=list, verbose_name='Mail To')),
|
|
25
|
+
('mail_cc', models.JSONField(blank=True, default=list, verbose_name='Mail Cc')),
|
|
26
|
+
('mail_bcc', models.JSONField(blank=True, default=list, verbose_name='Mail Bcc')),
|
|
27
|
+
('subject', models.CharField(max_length=255, verbose_name='Subject')),
|
|
28
|
+
('text_part', pfx.pfxcore.models.not_null_fields.NotNullTextField(blank=True, verbose_name='Text Part')),
|
|
29
|
+
('html_part', pfx.pfxcore.models.not_null_fields.NotNullTextField(blank=True, verbose_name='HTML Part')),
|
|
30
|
+
('headers', models.JSONField(default=dict, verbose_name='Headers')),
|
|
31
|
+
('attachments', models.JSONField(blank=True, default=list, verbose_name='Attachments')),
|
|
32
|
+
('status', models.CharField(choices=[('to_send', 'To send'), ('sending', 'Sending'), ('sent', 'Sent'), ('delivered', 'Delivered'), ('delivery_error', 'Delivery Error'), ('error', 'Error'), ('error_retry', 'Error Retry'), ('blocked', 'Blocked')], db_index=True, default='to_send', max_length=32, verbose_name='Status')),
|
|
33
|
+
('status_code', models.IntegerField(blank=True, null=True, verbose_name='HTTP Status Code')),
|
|
34
|
+
('errors', models.JSONField(blank=True, null=True, verbose_name='Errors')),
|
|
35
|
+
('send_mode', models.CharField(choices=[('manual', 'Manual'), ('auto', 'Auto'), ('auto_async', 'Auto Async')], db_index=True, default='auto_async', max_length=32, verbose_name='Send Mode')),
|
|
36
|
+
('delete_delivered', models.BooleanField(default=True, verbose_name='Delete Delivered')),
|
|
37
|
+
('send_task_id', models.CharField(blank=True, max_length=255, null=True, unique=True, verbose_name='Send Task Id')),
|
|
38
|
+
('retry_count', models.IntegerField(default=0, verbose_name='Retry count')),
|
|
39
|
+
],
|
|
40
|
+
options={
|
|
41
|
+
'verbose_name': 'Email',
|
|
42
|
+
'verbose_name_plural': 'Emails',
|
|
43
|
+
'db_table': 'emails_email',
|
|
44
|
+
'ordering': ['send_date'],
|
|
45
|
+
},
|
|
46
|
+
),
|
|
47
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Generated by Django 4.2.30 on 2026-06-01 00:26
|
|
2
|
+
# flake8: noqa
|
|
3
|
+
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('emails', '0001_initial'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterField(
|
|
15
|
+
model_name='email',
|
|
16
|
+
name='headers',
|
|
17
|
+
field=models.JSONField(blank=True, default=dict, verbose_name='Headers'),
|
|
18
|
+
),
|
|
19
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 4.2.30 on 2026-06-01 00:58
|
|
2
|
+
# flake8: noqa
|
|
3
|
+
|
|
4
|
+
from django.db import migrations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('emails', '0002_alter_email_headers'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterModelOptions(
|
|
15
|
+
name='email',
|
|
16
|
+
options={},
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .email import AbstractEmail, Email, get_email_model
|