modoboa 2.4.11__py3-none-any.whl → 2.5.0__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.
- modoboa/admin/api/v2/serializers.py +14 -0
- modoboa/amavis/__init__.py +3 -0
- modoboa/amavis/app_settings.py +276 -0
- modoboa/amavis/apps.py +18 -0
- modoboa/amavis/checks/__init__.py +2 -0
- modoboa/amavis/checks/settings_checks.py +59 -0
- modoboa/amavis/dbrouter.py +35 -0
- modoboa/amavis/factories.py +164 -0
- modoboa/amavis/handlers.py +146 -0
- modoboa/amavis/lib.py +381 -0
- modoboa/amavis/management/__init__.py +0 -0
- modoboa/amavis/management/commands/__init__.py +0 -0
- modoboa/amavis/management/commands/amnotify.py +99 -0
- modoboa/amavis/management/commands/qcleanup.py +84 -0
- modoboa/amavis/migrations/0001_initial.py +340 -0
- modoboa/amavis/migrations/__init__.py +0 -0
- modoboa/amavis/models.py +226 -0
- modoboa/amavis/serializers.py +139 -0
- modoboa/amavis/sql_connector.py +240 -0
- modoboa/amavis/sql_email.py +66 -0
- modoboa/amavis/tasks.py +33 -0
- modoboa/amavis/templates/amavis/notifications/pending_requests.html +16 -0
- modoboa/amavis/tests/__init__.py +0 -0
- modoboa/amavis/tests/sa-learn +3 -0
- modoboa/amavis/tests/sample_messages/quarantined-input.txt +80 -0
- modoboa/amavis/tests/sample_messages/quarantined-output-plain_nolinks.txt +17 -0
- modoboa/amavis/tests/spamc +3 -0
- modoboa/amavis/tests/test_checks.py +25 -0
- modoboa/amavis/tests/test_handlers.py +214 -0
- modoboa/amavis/tests/test_lib.py +90 -0
- modoboa/amavis/tests/test_management_commands.py +45 -0
- modoboa/amavis/tests/test_sql_email.py +67 -0
- modoboa/amavis/tests/test_utils.py +19 -0
- modoboa/amavis/tests/test_viewsets.py +319 -0
- modoboa/amavis/urls.py +11 -0
- modoboa/amavis/utils.py +105 -0
- modoboa/amavis/viewsets.py +265 -0
- modoboa/core/api/v1/serializers.py +7 -5
- modoboa/core/api/v2/serializers.py +4 -2
- modoboa/core/api/v2/tests.py +16 -4
- modoboa/core/api/v2/urls.py +5 -5
- modoboa/core/api/v2/views.py +3 -1
- modoboa/core/api/v2/viewsets.py +24 -3
- modoboa/core/handlers.py +6 -2
- modoboa/core/management/commands/add_allowed_hosts.py +33 -0
- modoboa/core/management/commands/load_initial_data.py +10 -0
- modoboa/core/migrations/0025_rename_user_email_is_active_core_user_email_c0c03f_idx.py +23 -5
- modoboa/core/tests/test_core.py +24 -0
- modoboa/core/utils.py +3 -0
- modoboa/frontend_dist/assets/AccountAliasForm-BuSy_1n9.js +1 -0
- modoboa/frontend_dist/assets/AccountEditView-qdJmLM_e.js +1 -0
- modoboa/frontend_dist/assets/AccountLayout-DrN7vHsX.js +1 -0
- modoboa/frontend_dist/assets/AccountPasswordSubForm-DZGt_Xgq.js +1 -0
- modoboa/frontend_dist/assets/AccountView-CO65y0vZ.js +1 -0
- modoboa/frontend_dist/assets/AddressBook-BZNUlhek.js +1 -0
- modoboa/frontend_dist/assets/AdminLayout-CTNhuwTw.js +1 -0
- modoboa/frontend_dist/assets/AlarmsView-9yKGbmkC.css +1 -0
- modoboa/frontend_dist/assets/AlarmsView-DN_JIw9g.js +1 -0
- modoboa/frontend_dist/assets/AliasEditView-DjpPUTp9.js +1 -0
- modoboa/frontend_dist/assets/{AliasRecipientForm-IOae6sjF.js → AliasRecipientForm-B1Y8wFdP.js} +1 -1
- modoboa/frontend_dist/assets/AliasView-GOJ5lyQH.js +1 -0
- modoboa/frontend_dist/assets/AuditTrailView-fbXmq70e.js +1 -0
- modoboa/frontend_dist/assets/CalendarView-LlQQNEPL.js +1 -0
- modoboa/frontend_dist/assets/{ChoiceField-DJ_c78Cm.js → ChoiceField-B3ReQHVe.js} +1 -1
- modoboa/frontend_dist/assets/ComposeEmailForm-Bs1fZXAL.js +1 -0
- modoboa/frontend_dist/assets/ComposeEmailView-s3LMl3pO.js +1 -0
- modoboa/frontend_dist/assets/ConfirmDialog-DY_kUHLG.js +1 -0
- modoboa/frontend_dist/assets/{ConnectedLayout-Dvwmicnc.css → ConnectedLayout-Bxh21hcH.css} +1 -1
- modoboa/frontend_dist/assets/ConnectedLayout-UWjiYBNw.js +1 -0
- modoboa/frontend_dist/assets/CreationForm-ORg3fazt.js +1 -0
- modoboa/frontend_dist/assets/DashboardView-Dplk9itS.js +1 -0
- modoboa/frontend_dist/assets/DomainAdminList-DVn9x0rB.js +1 -0
- modoboa/frontend_dist/assets/DomainEditView-nAoL64D_.js +1 -0
- modoboa/frontend_dist/assets/{DomainTransportForm-C2xo0Yd7.js → DomainTransportForm-CA-DNUxX.js} +1 -1
- modoboa/frontend_dist/assets/{DomainView-BDKoBFYr.css → DomainView-CCLYXPHx.css} +1 -1
- modoboa/frontend_dist/assets/DomainView-CdXPpwJG.js +5 -0
- modoboa/frontend_dist/assets/DomainsView-B_59gowf.js +1 -0
- modoboa/frontend_dist/assets/DomainsView-DZ-ss9bI.css +1 -0
- modoboa/frontend_dist/assets/EmailField-CwcwI5xW.js +1 -0
- modoboa/frontend_dist/assets/EmailView-BshxcfAK.js +1 -0
- modoboa/frontend_dist/assets/EmptyLayout-DFfhnhLi.js +1 -0
- modoboa/frontend_dist/assets/FiltersView-Cf20MSTK.js +1 -0
- modoboa/frontend_dist/assets/ForwardEmailView-CZG062os.js +1 -0
- modoboa/frontend_dist/assets/{HtmlEditor-CJ9umKeO.js → HtmlEditor-Bh4c689R.js} +1 -1
- modoboa/frontend_dist/assets/IdentitiesView-BXAuU1YX.js +1 -0
- modoboa/frontend_dist/assets/{IdentitiesView-0ziuQ5s-.css → IdentitiesView-DPrrRMS5.css} +1 -1
- modoboa/frontend_dist/assets/InformationView-C9vvvQhJ.css +1 -0
- modoboa/frontend_dist/assets/InformationView-Cn5FZW7H.js +1 -0
- modoboa/frontend_dist/assets/{LoadingData-CYwX3Jpn.js → LoadingData-CdVvm4FI.js} +1 -1
- modoboa/frontend_dist/assets/{LoginCallbackView-E01qkKn0.js → LoginCallbackView-B9hAH4MI.js} +1 -1
- modoboa/frontend_dist/assets/{LoginView-Cy4uFV9h.js → LoginView-tHIR4Adc.js} +1 -1
- modoboa/frontend_dist/assets/MailboxView-Bugu2vhg.js +1 -0
- modoboa/frontend_dist/assets/MenuItems-PXjiG-fs.js +1 -0
- modoboa/frontend_dist/assets/MessageView-Cy4STShm.js +1 -0
- modoboa/frontend_dist/assets/MessagesView-DdkuEgfX.js +1 -0
- modoboa/frontend_dist/assets/MigrationsView-CidSEjCF.js +1 -0
- modoboa/frontend_dist/assets/{ParametersForm-BZM0QSvg.js → ParametersForm-CAv4SH-E.js} +1 -1
- modoboa/frontend_dist/assets/ParametersView-CX7Ffemw.js +1 -0
- modoboa/frontend_dist/assets/ParametersView-CrbNcmV3.js +1 -0
- modoboa/frontend_dist/assets/ProviderEditView-CrltAQXl.js +1 -0
- modoboa/frontend_dist/assets/ProviderGeneralForm-BYAzVnXM.js +1 -0
- modoboa/frontend_dist/assets/ProvidersView-osjIY4Ex.js +1 -0
- modoboa/frontend_dist/assets/QuarantineLayout-B8EcU9vS.js +1 -0
- modoboa/frontend_dist/assets/QuarantineView-D4gOE4EQ.css +1 -0
- modoboa/frontend_dist/assets/QuarantineView-D8Qg0MXA.js +1 -0
- modoboa/frontend_dist/assets/ReplyEmailView-BABPqWhd.js +1 -0
- modoboa/frontend_dist/assets/ResourcesForm-OaqdRYVs.js +1 -0
- modoboa/frontend_dist/assets/SelfServiceLayout-d277YTGR.js +1 -0
- modoboa/frontend_dist/assets/{SettingsView-BxLJBFY0.js → SettingsView-9iNcDhkI.js} +2 -2
- modoboa/frontend_dist/assets/StatisticsView-cHsPyGkL.js +1 -0
- modoboa/frontend_dist/assets/TimeSerieChart--V83dcJ9.js +1 -0
- modoboa/frontend_dist/assets/UserLayout-B3sBiTcZ.js +1 -0
- modoboa/frontend_dist/assets/VAlert-BuaaYN2h.js +1 -0
- modoboa/frontend_dist/assets/VApp-CKP-6zGP.js +1 -0
- modoboa/frontend_dist/assets/VAutocomplete-Dwv6_Rzq.js +1 -0
- modoboa/frontend_dist/assets/VAvatar-Cmga0vj6.js +1 -0
- modoboa/frontend_dist/assets/VBadge-BQrRJ9S0.css +1 -0
- modoboa/frontend_dist/assets/VBadge-CixeK87a.js +1 -0
- modoboa/frontend_dist/assets/VCard-CxH9DWoK.js +1 -0
- modoboa/frontend_dist/assets/VCheckbox-62GOpvvP.js +1 -0
- modoboa/frontend_dist/assets/{VCheckboxBtn-Dt810gWf.js → VCheckboxBtn-DMoNtKT8.js} +1 -1
- modoboa/frontend_dist/assets/VChip-D_styETR.js +1 -0
- modoboa/frontend_dist/assets/VColorPicker-BHscBGQV.js +1 -0
- modoboa/frontend_dist/assets/{VContainer-DvTbsotR.js → VContainer-B46caNs1.js} +1 -1
- modoboa/frontend_dist/assets/VDataTable-Bh8NbVSx.js +1 -0
- modoboa/frontend_dist/assets/VDataTableServer-BDR5hOmo.js +1 -0
- modoboa/frontend_dist/assets/VDataTableVirtual-BOQlNtIG.js +1 -0
- modoboa/frontend_dist/assets/{VDialog-Bk6EWNhz.js → VDialog-BcTg7w6P.js} +1 -1
- modoboa/frontend_dist/assets/VExpansionPanels-BmH5Jl2Z.js +1 -0
- modoboa/frontend_dist/assets/VFileInput-BC4yAygd.js +1 -0
- modoboa/frontend_dist/assets/VForm-D5iPGkde.js +1 -0
- modoboa/frontend_dist/assets/VInput-CcxkaOXT.css +1 -0
- modoboa/frontend_dist/assets/VInput-CoDJzvaW.js +1 -0
- modoboa/frontend_dist/assets/VMenu-gUG70-zD.js +1 -0
- modoboa/frontend_dist/assets/VPicker-BXuKT3zB.js +1 -0
- modoboa/frontend_dist/assets/VProgressCircular-BtOPiGCg.js +1 -0
- modoboa/frontend_dist/assets/VRadioGroup-DIFZKSn-.js +1 -0
- modoboa/frontend_dist/assets/{VRow-BF35mT1S.js → VRow-ozg66L7j.js} +1 -1
- modoboa/frontend_dist/assets/VSelect-C3RjAa45.js +1 -0
- modoboa/frontend_dist/assets/VSelectionControl-zyz-fJvC.js +1 -0
- modoboa/frontend_dist/assets/VSheet-BNx2X4Mk.js +1 -0
- modoboa/frontend_dist/assets/VSpacer-DinPiXs9.js +1 -0
- modoboa/frontend_dist/assets/VSwitch-DwxdeAEq.js +1 -0
- modoboa/frontend_dist/assets/VTable-DaLxa4FO.js +1 -0
- modoboa/frontend_dist/assets/VTabs-BP0Hgsgm.js +1 -0
- modoboa/frontend_dist/assets/VTextField-BzBVKKob.css +1 -0
- modoboa/frontend_dist/assets/VTextField-XoGTj1KG.js +1 -0
- modoboa/frontend_dist/assets/VTextarea-wBlRMIv_.js +1 -0
- modoboa/frontend_dist/assets/VToolbar-CFZfqeOr.js +1 -0
- modoboa/frontend_dist/assets/VWindowItem-BB7ETW3b.js +1 -0
- modoboa/frontend_dist/assets/WebmailLayout-_Hk1XhVq.js +1 -0
- modoboa/frontend_dist/assets/accounts-DUzbx6k8.js +1 -0
- modoboa/frontend_dist/assets/{admin-o-HRGnmT.js → admin-DewTk2H8.js} +1 -1
- modoboa/frontend_dist/assets/{aliases-DDVeehyg.js → aliases-4sXmjwXp.js} +1 -1
- modoboa/frontend_dist/assets/amavis-CC0li7_T.js +1 -0
- modoboa/frontend_dist/assets/amavis-DK8SHE6o.js +1 -0
- modoboa/frontend_dist/assets/{contacts-C84DY-Q1.js → contacts-BjghrPqZ.js} +1 -1
- modoboa/frontend_dist/assets/{domains-Bgn4ixHL.js → domains-BSawReeu.js} +1 -1
- modoboa/frontend_dist/assets/{domains.store-DTE-V7Y1.js → domains.store-D-vWCEIK.js} +1 -1
- modoboa/frontend_dist/assets/{filter-CnffiQAW.js → filter-C82FUCw_.js} +1 -1
- modoboa/frontend_dist/assets/forwardRefs-cvcnlhoK.js +1 -0
- modoboa/frontend_dist/assets/global.store-DbkcI5o2.js +1 -0
- modoboa/frontend_dist/assets/{importExport-BlQYb0NO.js → importExport-DzoL4Mvc.js} +1 -1
- modoboa/frontend_dist/assets/index-BImkz5Jx.js +984 -0
- modoboa/frontend_dist/assets/layout-C5FyYCHK.js +1 -0
- modoboa/frontend_dist/assets/{layout.store-DkjrAoXt.js → layout.store-NXWtFIwL.js} +1 -1
- modoboa/frontend_dist/assets/{logos-q8SEyAa4.js → logos-BswdveCV.js} +1 -1
- modoboa/frontend_dist/assets/{logs-B7IJ7LBa.js → logs-6CbtfaZS.js} +1 -1
- modoboa/frontend_dist/assets/{parameters-A6iBEYQq.js → parameters-aSQiR7kN.js} +1 -1
- modoboa/frontend_dist/assets/{parameters.store-BiXS4_6w.js → parameters.store-CzQqVatx.js} +1 -1
- modoboa/frontend_dist/assets/permissions-DNoefz-n.js +1 -0
- modoboa/frontend_dist/assets/{ssrBoot-AzTdjPjk.js → ssrBoot-CKUX4kcb.js} +1 -1
- modoboa/frontend_dist/assets/{tag-BnSYRTcD.js → tag-B_yWNNJD.js} +1 -1
- modoboa/frontend_dist/assets/transports-BDNB9wR5.js +1 -0
- modoboa/frontend_dist/assets/{webmail-CSH_3l6R.js → webmail-CdU6CD9b.js} +1 -1
- modoboa/frontend_dist/index.html +1 -1
- modoboa/lib/email_utils.py +2 -2
- modoboa/lib/permissions.py +7 -0
- modoboa/lib/test_runners.py +29 -0
- modoboa/lib/tests/__init__.py +5 -1
- modoboa/locale/br/LC_MESSAGES/django.po +87 -75
- modoboa/locale/cs/LC_MESSAGES/django.po +82 -74
- modoboa/locale/cs_CZ/LC_MESSAGES/django.po +145 -121
- modoboa/locale/de/LC_MESSAGES/django.mo +0 -0
- modoboa/locale/de/LC_MESSAGES/django.po +339 -651
- modoboa/locale/de_DE/LC_MESSAGES/django.po +87 -75
- modoboa/locale/el_GR/LC_MESSAGES/django.po +160 -135
- modoboa/locale/en/LC_MESSAGES/django.po +82 -74
- modoboa/locale/es/LC_MESSAGES/django.po +158 -131
- modoboa/locale/es_MX/LC_MESSAGES/django.po +82 -74
- modoboa/locale/fi/LC_MESSAGES/django.po +87 -75
- modoboa/locale/fr/LC_MESSAGES/django.mo +0 -0
- modoboa/locale/fr/LC_MESSAGES/django.po +469 -201
- modoboa/locale/hu/LC_MESSAGES/django.po +82 -74
- modoboa/locale/it/LC_MESSAGES/django.mo +0 -0
- modoboa/locale/it/LC_MESSAGES/django.po +148 -122
- modoboa/locale/ja_JP/LC_MESSAGES/django.mo +0 -0
- modoboa/locale/ja_JP/LC_MESSAGES/django.po +80 -72
- modoboa/locale/ka/LC_MESSAGES/django.po +82 -74
- modoboa/locale/nl_NL/LC_MESSAGES/django.po +160 -132
- modoboa/locale/no/LC_MESSAGES/django.po +82 -74
- modoboa/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
- modoboa/locale/pl_PL/LC_MESSAGES/django.po +172 -149
- modoboa/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- modoboa/locale/pt_BR/LC_MESSAGES/django.po +172 -144
- modoboa/locale/pt_PT/LC_MESSAGES/django.po +135 -112
- modoboa/locale/ro_RO/LC_MESSAGES/django.po +87 -75
- modoboa/locale/ru/LC_MESSAGES/django.po +142 -118
- modoboa/locale/si/LC_MESSAGES/django.po +82 -74
- modoboa/locale/sk/LC_MESSAGES/django.po +82 -74
- modoboa/locale/sk_SK/LC_MESSAGES/django.po +84 -76
- modoboa/locale/sl_SI/LC_MESSAGES/django.po +90 -76
- modoboa/locale/sv/LC_MESSAGES/django.mo +0 -0
- modoboa/locale/sv/LC_MESSAGES/django.po +172 -139
- modoboa/locale/tr/LC_MESSAGES/django.po +87 -75
- modoboa/locale/tr_TR/LC_MESSAGES/django.po +84 -74
- modoboa/locale/uk/LC_MESSAGES/django.po +82 -74
- modoboa/locale/zh/LC_MESSAGES/django.po +82 -74
- modoboa/locale/zh_CN/LC_MESSAGES/django.po +82 -74
- modoboa/locale/zh_TW/LC_MESSAGES/django.po +87 -75
- modoboa/parameters/api/v2/tests.py +2 -2
- modoboa/parameters/api/v2/viewsets.py +2 -0
- modoboa/policyd/tests.py +2 -0
- modoboa/urls_api_v2.py +6 -0
- {modoboa-2.4.11.dist-info → modoboa-2.5.0.dist-info}/METADATA +6 -4
- {modoboa-2.4.11.dist-info → modoboa-2.5.0.dist-info}/RECORD +231 -181
- modoboa/frontend_dist/assets/AccountAliasForm-BV6KvTu6.js +0 -1
- modoboa/frontend_dist/assets/AccountEditView-DDOFyfBD.js +0 -1
- modoboa/frontend_dist/assets/AccountLayout-rX51xgxT.js +0 -1
- modoboa/frontend_dist/assets/AccountPasswordSubForm-D9S6LaeH.js +0 -1
- modoboa/frontend_dist/assets/AccountView-cmvaZNq3.js +0 -1
- modoboa/frontend_dist/assets/AddressBook-DCJxL8SU.js +0 -1
- modoboa/frontend_dist/assets/AdminLayout-r0wfG2lO.js +0 -1
- modoboa/frontend_dist/assets/AlarmsView-Bheey-gp.css +0 -1
- modoboa/frontend_dist/assets/AlarmsView-C0bqC4PA.js +0 -1
- modoboa/frontend_dist/assets/AliasEditView-DVoWoCGY.js +0 -1
- modoboa/frontend_dist/assets/AliasView-DrONZXOh.js +0 -1
- modoboa/frontend_dist/assets/AuditTrailView-OTkoZaMU.js +0 -1
- modoboa/frontend_dist/assets/CalendarView-CqF4_Ui9.js +0 -1
- modoboa/frontend_dist/assets/ComposeEmailForm-DO5_GB3e.js +0 -1
- modoboa/frontend_dist/assets/ComposeEmailView-A91HCBsN.js +0 -1
- modoboa/frontend_dist/assets/ConfirmDialog-BBcgdAnO.js +0 -1
- modoboa/frontend_dist/assets/ConnectedLayout-1oRW-Rql.js +0 -1
- modoboa/frontend_dist/assets/CreationForm-71YJbjsA.js +0 -1
- modoboa/frontend_dist/assets/DashboardView-CdLpSfUl.js +0 -1
- modoboa/frontend_dist/assets/DomainAdminList-BjC4KsqI.js +0 -1
- modoboa/frontend_dist/assets/DomainEditView-CQjKwYxl.js +0 -1
- modoboa/frontend_dist/assets/DomainView-BhhuZI_N.js +0 -5
- modoboa/frontend_dist/assets/DomainsView-Cft4BP8Z.js +0 -1
- modoboa/frontend_dist/assets/DomainsView-DasJ0NdZ.css +0 -1
- modoboa/frontend_dist/assets/EmailField-C8umy0EU.js +0 -1
- modoboa/frontend_dist/assets/EmailView-ki7uEQPD.js +0 -1
- modoboa/frontend_dist/assets/EmptyLayout-DaA1XH9n.js +0 -1
- modoboa/frontend_dist/assets/FiltersView-FYFZxG4B.js +0 -1
- modoboa/frontend_dist/assets/ForwardEmailView-cUbnSYCF.js +0 -1
- modoboa/frontend_dist/assets/IdentitiesView-njNo8N5n.js +0 -1
- modoboa/frontend_dist/assets/InformationView-D1h38POt.js +0 -1
- modoboa/frontend_dist/assets/InformationView-U5Ww-Sx1.css +0 -1
- modoboa/frontend_dist/assets/MailboxView-IlrLWm_H.js +0 -1
- modoboa/frontend_dist/assets/MenuItems-BAtHWzAE.js +0 -1
- modoboa/frontend_dist/assets/MessagesView-OSpjixFq.js +0 -1
- modoboa/frontend_dist/assets/MigrationsView-DKNOsVzF.js +0 -1
- modoboa/frontend_dist/assets/ParametersView-C4bXASiq.js +0 -1
- modoboa/frontend_dist/assets/ParametersView-CYXgNmc1.js +0 -1
- modoboa/frontend_dist/assets/ProviderEditView-CyxCWTST.js +0 -1
- modoboa/frontend_dist/assets/ProviderGeneralForm-BYPjNHqB.js +0 -1
- modoboa/frontend_dist/assets/ProvidersView-CxrMkRyk.js +0 -1
- modoboa/frontend_dist/assets/ReplyEmailView-Dkw9-N26.js +0 -1
- modoboa/frontend_dist/assets/ResourcesForm-CuUvrOdY.js +0 -1
- modoboa/frontend_dist/assets/StatisticsView-BN7QsZMT.js +0 -1
- modoboa/frontend_dist/assets/TimeSerieChart-BMN8BeFZ.js +0 -1
- modoboa/frontend_dist/assets/UserLayout-B6-JQg4F.js +0 -1
- modoboa/frontend_dist/assets/VAlert-DIQTrRif.js +0 -1
- modoboa/frontend_dist/assets/VApp-CpkYA7js.js +0 -1
- modoboa/frontend_dist/assets/VAutocomplete-C4IpXyl8.js +0 -1
- modoboa/frontend_dist/assets/VAvatar-Lpb-Dion.js +0 -1
- modoboa/frontend_dist/assets/VCard-er_isjE_.js +0 -1
- modoboa/frontend_dist/assets/VCheckbox-D-u8JXP1.js +0 -1
- modoboa/frontend_dist/assets/VChip-B4iSpj8_.js +0 -1
- modoboa/frontend_dist/assets/VColorPicker-BAjGDsXv.js +0 -1
- modoboa/frontend_dist/assets/VDataTable-4JRjbtgF.js +0 -1
- modoboa/frontend_dist/assets/VDataTableServer-tIDT1m3-.js +0 -1
- modoboa/frontend_dist/assets/VDataTableVirtual-BlnO18u_.js +0 -1
- modoboa/frontend_dist/assets/VExpansionPanels-CwGtXDhr.js +0 -1
- modoboa/frontend_dist/assets/VFileInput-D1_7ZkO_.js +0 -1
- modoboa/frontend_dist/assets/VForm-DAkW4nfy.js +0 -1
- modoboa/frontend_dist/assets/VMenu-BPFJwj2f.js +0 -1
- modoboa/frontend_dist/assets/VPicker-CfT82M8N.js +0 -1
- modoboa/frontend_dist/assets/VProgressCircular-w75-3ogi.js +0 -1
- modoboa/frontend_dist/assets/VRadioGroup-0j6DNC_k.js +0 -1
- modoboa/frontend_dist/assets/VSelect-Cs4ARbAS.js +0 -1
- modoboa/frontend_dist/assets/VSelectionControl-Dg-XyRRS.js +0 -1
- modoboa/frontend_dist/assets/VSheet-Btq_Mu4s.js +0 -1
- modoboa/frontend_dist/assets/VSpacer-C7xukQmu.js +0 -1
- modoboa/frontend_dist/assets/VSwitch-Cs1NQrmk.js +0 -1
- modoboa/frontend_dist/assets/VTable-CNz2SGk4.js +0 -1
- modoboa/frontend_dist/assets/VTabs-B1fyVn4M.js +0 -1
- modoboa/frontend_dist/assets/VTextField-BdyvgvkG.js +0 -1
- modoboa/frontend_dist/assets/VTextField-C-J20yj_.css +0 -1
- modoboa/frontend_dist/assets/VTextarea-DnOMpe0Q.js +0 -1
- modoboa/frontend_dist/assets/VToolbar-BiCiBxBJ.js +0 -1
- modoboa/frontend_dist/assets/VWindowItem-ChWm_kz3.js +0 -1
- modoboa/frontend_dist/assets/WebmailLayout-o4uEkp9e.js +0 -1
- modoboa/frontend_dist/assets/forwardRefs-Dvjn_Xq4.js +0 -1
- modoboa/frontend_dist/assets/global.store-BaiD63EN.js +0 -1
- modoboa/frontend_dist/assets/index-I1VDlN4g.js +0 -984
- modoboa/frontend_dist/assets/layout-D8ZJPiJ_.js +0 -1
- modoboa/frontend_dist/assets/permissions-CITHLHVg.js +0 -1
- modoboa/frontend_dist/assets/transports-Dz7c6kIy.js +0 -1
- {modoboa-2.4.11.data → modoboa-2.5.0.data}/scripts/modoboa-admin.py +0 -0
- {modoboa-2.4.11.dist-info → modoboa-2.5.0.dist-info}/WHEEL +0 -0
- {modoboa-2.4.11.dist-info → modoboa-2.5.0.dist-info}/entry_points.txt +0 -0
- {modoboa-2.4.11.dist-info → modoboa-2.5.0.dist-info}/licenses/LICENSE +0 -0
- {modoboa-2.4.11.dist-info → modoboa-2.5.0.dist-info}/top_level.txt +0 -0
|
@@ -398,6 +398,20 @@ class AccountMeSerializer(v1_serializers.AccountSerializer):
|
|
|
398
398
|
return [f"{p.content_type.app_label}.{p.codename}" for p in permissions]
|
|
399
399
|
|
|
400
400
|
|
|
401
|
+
class AccountMeUpdateSerializer(serializers.ModelSerializer):
|
|
402
|
+
"""Update serializer for connected user."""
|
|
403
|
+
|
|
404
|
+
class Meta:
|
|
405
|
+
model = core_models.User
|
|
406
|
+
fields = (
|
|
407
|
+
"first_name",
|
|
408
|
+
"last_name",
|
|
409
|
+
"language",
|
|
410
|
+
"phone_number",
|
|
411
|
+
"secondary_email",
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
|
|
401
415
|
class AccountSerializer(v1_serializers.AccountSerializer):
|
|
402
416
|
"""Add support for user resources."""
|
|
403
417
|
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import collections
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext_lazy
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
GLOBAL_PARAMETERS_STRUCT = collections.OrderedDict(
|
|
7
|
+
[
|
|
8
|
+
(
|
|
9
|
+
"amavis",
|
|
10
|
+
{
|
|
11
|
+
"label": gettext_lazy("Amavis settings"),
|
|
12
|
+
"params": collections.OrderedDict(
|
|
13
|
+
[
|
|
14
|
+
(
|
|
15
|
+
"localpart_is_case_sensitive",
|
|
16
|
+
{
|
|
17
|
+
"label": gettext_lazy("Localpart is case sensitive"),
|
|
18
|
+
"help_text": gettext_lazy(
|
|
19
|
+
"Value should match amavisd.conf variable "
|
|
20
|
+
"$localpart_is_case_sensitive"
|
|
21
|
+
),
|
|
22
|
+
},
|
|
23
|
+
),
|
|
24
|
+
(
|
|
25
|
+
"recipient_delimiter",
|
|
26
|
+
{
|
|
27
|
+
"label": gettext_lazy("Recipient delimiter"),
|
|
28
|
+
"help_text": gettext_lazy(
|
|
29
|
+
"Value should match amavisd.conf variable "
|
|
30
|
+
"$recipient_delimiter"
|
|
31
|
+
),
|
|
32
|
+
},
|
|
33
|
+
),
|
|
34
|
+
]
|
|
35
|
+
),
|
|
36
|
+
},
|
|
37
|
+
),
|
|
38
|
+
(
|
|
39
|
+
"quarantine",
|
|
40
|
+
{
|
|
41
|
+
"label": gettext_lazy("Quarantine settings"),
|
|
42
|
+
"params": collections.OrderedDict(
|
|
43
|
+
[
|
|
44
|
+
(
|
|
45
|
+
"max_messages_age",
|
|
46
|
+
{
|
|
47
|
+
"label": gettext_lazy("Maximum message age"),
|
|
48
|
+
"help_text": gettext_lazy(
|
|
49
|
+
"Quarantine messages maximum age (in days) before deletion"
|
|
50
|
+
),
|
|
51
|
+
},
|
|
52
|
+
)
|
|
53
|
+
]
|
|
54
|
+
),
|
|
55
|
+
},
|
|
56
|
+
),
|
|
57
|
+
(
|
|
58
|
+
"releasing",
|
|
59
|
+
{
|
|
60
|
+
"label": gettext_lazy("Message releasing"),
|
|
61
|
+
"params": collections.OrderedDict(
|
|
62
|
+
[
|
|
63
|
+
(
|
|
64
|
+
"released_msgs_cleanup",
|
|
65
|
+
{
|
|
66
|
+
"label": gettext_lazy("Remove released messages"),
|
|
67
|
+
"help_text": gettext_lazy(
|
|
68
|
+
"Remove messages marked as released while cleaning up "
|
|
69
|
+
"the database"
|
|
70
|
+
),
|
|
71
|
+
},
|
|
72
|
+
),
|
|
73
|
+
(
|
|
74
|
+
"am_pdp_mode",
|
|
75
|
+
{
|
|
76
|
+
"label": gettext_lazy("Amavis connection mode"),
|
|
77
|
+
"help_text": gettext_lazy(
|
|
78
|
+
"Mode used to access the PDP server"
|
|
79
|
+
),
|
|
80
|
+
},
|
|
81
|
+
),
|
|
82
|
+
(
|
|
83
|
+
"am_pdp_host",
|
|
84
|
+
{
|
|
85
|
+
"label": gettext_lazy("PDP server address"),
|
|
86
|
+
"help_text": gettext_lazy(
|
|
87
|
+
"PDP server address (if inet mode)"
|
|
88
|
+
),
|
|
89
|
+
"display": "am_pdp_mode=inet",
|
|
90
|
+
},
|
|
91
|
+
),
|
|
92
|
+
(
|
|
93
|
+
"am_pdp_port",
|
|
94
|
+
{
|
|
95
|
+
"label": gettext_lazy("PDP server port"),
|
|
96
|
+
"help_text": gettext_lazy(
|
|
97
|
+
"PDP server port (if inet mode)"
|
|
98
|
+
),
|
|
99
|
+
"display": "am_pdp_mode=inet",
|
|
100
|
+
},
|
|
101
|
+
),
|
|
102
|
+
(
|
|
103
|
+
"am_pdp_socket",
|
|
104
|
+
{
|
|
105
|
+
"label": gettext_lazy("PDP server socket"),
|
|
106
|
+
"help_text": gettext_lazy(
|
|
107
|
+
"Path to the PDP server socket (if unix mode)"
|
|
108
|
+
),
|
|
109
|
+
"display": "am_pdp_mode=unix",
|
|
110
|
+
},
|
|
111
|
+
),
|
|
112
|
+
(
|
|
113
|
+
"user_can_release",
|
|
114
|
+
{
|
|
115
|
+
"label": gettext_lazy("Allow direct release"),
|
|
116
|
+
"help_text": gettext_lazy(
|
|
117
|
+
"Allow users to directly release their messages"
|
|
118
|
+
),
|
|
119
|
+
},
|
|
120
|
+
),
|
|
121
|
+
(
|
|
122
|
+
"self_service",
|
|
123
|
+
{
|
|
124
|
+
"label": gettext_lazy("Enable self-service mode"),
|
|
125
|
+
"help_text": gettext_lazy(
|
|
126
|
+
"Activate the 'self-service' mode"
|
|
127
|
+
),
|
|
128
|
+
},
|
|
129
|
+
),
|
|
130
|
+
(
|
|
131
|
+
"notifications_sender",
|
|
132
|
+
{
|
|
133
|
+
"label": gettext_lazy("Notifications sender"),
|
|
134
|
+
"help_text": gettext_lazy(
|
|
135
|
+
"The e-mail address used to send notitications"
|
|
136
|
+
),
|
|
137
|
+
},
|
|
138
|
+
),
|
|
139
|
+
]
|
|
140
|
+
),
|
|
141
|
+
},
|
|
142
|
+
),
|
|
143
|
+
(
|
|
144
|
+
"learning",
|
|
145
|
+
{
|
|
146
|
+
"label": gettext_lazy("Manual learning"),
|
|
147
|
+
"params": collections.OrderedDict(
|
|
148
|
+
[
|
|
149
|
+
(
|
|
150
|
+
"manual_learning",
|
|
151
|
+
{
|
|
152
|
+
"label": gettext_lazy("Enable manual learning"),
|
|
153
|
+
"help_text": gettext_lazy(
|
|
154
|
+
"Allow super administrators to manually train Spamassassin"
|
|
155
|
+
),
|
|
156
|
+
},
|
|
157
|
+
),
|
|
158
|
+
(
|
|
159
|
+
"sa_is_local",
|
|
160
|
+
{
|
|
161
|
+
"label": gettext_lazy("Is Spamassassin local?"),
|
|
162
|
+
"help_text": gettext_lazy(
|
|
163
|
+
"Tell if Spamassassin is running on the same server than modoboa"
|
|
164
|
+
),
|
|
165
|
+
"display": "manual_learning=true",
|
|
166
|
+
},
|
|
167
|
+
),
|
|
168
|
+
(
|
|
169
|
+
"default_user",
|
|
170
|
+
{
|
|
171
|
+
"label": gettext_lazy("Default user"),
|
|
172
|
+
"help_text": gettext_lazy(
|
|
173
|
+
"Name of the user owning the default bayesian database"
|
|
174
|
+
),
|
|
175
|
+
"display": "manual_learning=true",
|
|
176
|
+
},
|
|
177
|
+
),
|
|
178
|
+
(
|
|
179
|
+
"spamd_address",
|
|
180
|
+
{
|
|
181
|
+
"label": gettext_lazy("Spamd address"),
|
|
182
|
+
"help_text": gettext_lazy(
|
|
183
|
+
"The IP address where spamd can be reached"
|
|
184
|
+
),
|
|
185
|
+
"display": "sa_is_local=false",
|
|
186
|
+
},
|
|
187
|
+
),
|
|
188
|
+
(
|
|
189
|
+
"spamd_port",
|
|
190
|
+
{
|
|
191
|
+
"label": gettext_lazy("Spamd port"),
|
|
192
|
+
"help_text": gettext_lazy(
|
|
193
|
+
"The TCP port spamd is listening on"
|
|
194
|
+
),
|
|
195
|
+
"display": "sa_is_local=false",
|
|
196
|
+
},
|
|
197
|
+
),
|
|
198
|
+
(
|
|
199
|
+
"domain_level_learning",
|
|
200
|
+
{
|
|
201
|
+
"label": gettext_lazy(
|
|
202
|
+
"Enable per-domain manual learning"
|
|
203
|
+
),
|
|
204
|
+
"help_text": gettext_lazy(
|
|
205
|
+
"Allow domain administrators to train Spamassassin "
|
|
206
|
+
"(within dedicated per-domain databases)"
|
|
207
|
+
),
|
|
208
|
+
"display": "manual_learning=true",
|
|
209
|
+
},
|
|
210
|
+
),
|
|
211
|
+
(
|
|
212
|
+
"user_level_learning",
|
|
213
|
+
{
|
|
214
|
+
"label": gettext_lazy(
|
|
215
|
+
"Enable per-user manual learning"
|
|
216
|
+
),
|
|
217
|
+
"help_text": gettext_lazy(
|
|
218
|
+
"Allow simple users to personally train Spamassassin "
|
|
219
|
+
"(within a dedicated database)"
|
|
220
|
+
),
|
|
221
|
+
"display": "manual_learning=true",
|
|
222
|
+
},
|
|
223
|
+
),
|
|
224
|
+
]
|
|
225
|
+
),
|
|
226
|
+
},
|
|
227
|
+
),
|
|
228
|
+
]
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
USER_PREFERENCES_STRUCT = collections.OrderedDict(
|
|
232
|
+
[
|
|
233
|
+
(
|
|
234
|
+
"display",
|
|
235
|
+
{
|
|
236
|
+
"label": gettext_lazy("Display"),
|
|
237
|
+
"params": collections.OrderedDict(
|
|
238
|
+
[
|
|
239
|
+
(
|
|
240
|
+
"messages_per_page",
|
|
241
|
+
{
|
|
242
|
+
"label": gettext_lazy(
|
|
243
|
+
"Number of displayed emails per page"
|
|
244
|
+
),
|
|
245
|
+
"help_text": gettext_lazy(
|
|
246
|
+
"Set the maximum number of messages displayed in a page"
|
|
247
|
+
),
|
|
248
|
+
},
|
|
249
|
+
)
|
|
250
|
+
]
|
|
251
|
+
),
|
|
252
|
+
},
|
|
253
|
+
)
|
|
254
|
+
]
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def load_settings():
|
|
259
|
+
"""Load amavis settings."""
|
|
260
|
+
from modoboa.parameters import tools as param_tools
|
|
261
|
+
from modoboa.amavis import serializers
|
|
262
|
+
|
|
263
|
+
param_tools.registry.add(
|
|
264
|
+
"global",
|
|
265
|
+
"amavis",
|
|
266
|
+
gettext_lazy("Amavis"),
|
|
267
|
+
GLOBAL_PARAMETERS_STRUCT,
|
|
268
|
+
serializers.GlobalParametersSerializer,
|
|
269
|
+
)
|
|
270
|
+
param_tools.registry.add(
|
|
271
|
+
"user",
|
|
272
|
+
"amavis",
|
|
273
|
+
gettext_lazy("Amavis"),
|
|
274
|
+
USER_PREFERENCES_STRUCT,
|
|
275
|
+
serializers.UserPreferencesSerializer,
|
|
276
|
+
)
|
modoboa/amavis/apps.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""AppConfig for amavis."""
|
|
2
|
+
|
|
3
|
+
from django.apps import AppConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AmavisConfig(AppConfig):
|
|
7
|
+
"""App configuration."""
|
|
8
|
+
|
|
9
|
+
name = "modoboa.amavis"
|
|
10
|
+
verbose_name = "Modoboa amavis frontend"
|
|
11
|
+
|
|
12
|
+
def ready(self):
|
|
13
|
+
# Import these to force registration of checks and signals
|
|
14
|
+
from . import checks # NOQA:F401
|
|
15
|
+
from . import handlers # NOQA:F401
|
|
16
|
+
from modoboa.amavis.app_settings import load_settings
|
|
17
|
+
|
|
18
|
+
load_settings()
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
from django.core.checks import Warning, register
|
|
3
|
+
from django.db import connections
|
|
4
|
+
from django.utils.translation import gettext as _
|
|
5
|
+
|
|
6
|
+
W001 = Warning(
|
|
7
|
+
_(
|
|
8
|
+
"AMAVIS_DEFAULT_DATABASE_ENCODING does not match the character "
|
|
9
|
+
"encoding used by the Amavis database."
|
|
10
|
+
),
|
|
11
|
+
hint=_(
|
|
12
|
+
"Check your database character encoding and set/update "
|
|
13
|
+
"AMAVIS_DEFAULT_DATABASE_ENCODING."
|
|
14
|
+
),
|
|
15
|
+
id="modoboa-amavis.W001",
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
W002 = Warning(
|
|
19
|
+
_("Modoboa Amavis has not been tested using the selected database engine."),
|
|
20
|
+
hint=_("Try using PostgreSQL, MySQL or MariaDB."),
|
|
21
|
+
id="modoboa-amavis.W002",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@register(deploy=True)
|
|
26
|
+
def check_amavis_database_encoding(app_configs, **kwargs):
|
|
27
|
+
"""Ensure AMAVIS_DEFAULT_DATABASE_ENCODING is set to the correct value."""
|
|
28
|
+
errors = []
|
|
29
|
+
db_engine = settings.DATABASES["amavis"]["ENGINE"]
|
|
30
|
+
sql_query = None
|
|
31
|
+
if "postgresql" in db_engine:
|
|
32
|
+
sql_query = (
|
|
33
|
+
"SELECT pg_encoding_to_char(encoding) "
|
|
34
|
+
"FROM pg_database "
|
|
35
|
+
"WHERE datname = %s;"
|
|
36
|
+
)
|
|
37
|
+
elif "mysql" in db_engine:
|
|
38
|
+
sql_query = (
|
|
39
|
+
"SELECT DEFAULT_CHARACTER_SET_NAME "
|
|
40
|
+
"FROM INFORMATION_SCHEMA.SCHEMATA "
|
|
41
|
+
"WHERE SCHEMA_NAME = %s;"
|
|
42
|
+
)
|
|
43
|
+
elif "sqlite" in db_engine:
|
|
44
|
+
sql_query = "PRAGMA encoding;"
|
|
45
|
+
else:
|
|
46
|
+
errors.append(W002)
|
|
47
|
+
return errors
|
|
48
|
+
|
|
49
|
+
with connections["amavis"].cursor() as cursor:
|
|
50
|
+
if "sqlite" in db_engine:
|
|
51
|
+
cursor.execute(sql_query)
|
|
52
|
+
else:
|
|
53
|
+
cursor.execute(sql_query, [settings.DATABASES["amavis"]["NAME"]])
|
|
54
|
+
encoding = cursor.fetchone()[0]
|
|
55
|
+
|
|
56
|
+
if encoding.lower() != settings.AMAVIS_DEFAULT_DATABASE_ENCODING.lower():
|
|
57
|
+
errors.append(W001)
|
|
58
|
+
|
|
59
|
+
return errors
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class AmavisRouter:
|
|
2
|
+
"""A router to control all database operations on models in
|
|
3
|
+
the amavis application"""
|
|
4
|
+
|
|
5
|
+
def db_for_read(self, model, **hints):
|
|
6
|
+
"""Point all operations on amavis models to 'amavis'."""
|
|
7
|
+
if model._meta.app_label == "amavis":
|
|
8
|
+
return "amavis"
|
|
9
|
+
return None
|
|
10
|
+
|
|
11
|
+
def db_for_write(self, model, **hints):
|
|
12
|
+
"""Point all operations on amavis models to 'amavis'."""
|
|
13
|
+
if model._meta.app_label == "amavis":
|
|
14
|
+
return "amavis"
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
def allow_relation(self, obj1, obj2, **hints):
|
|
18
|
+
"""Allow any relation if a model in amavis is involved."""
|
|
19
|
+
if obj1._meta.app_label == "amavis" or obj2._meta.app_label == "amavis":
|
|
20
|
+
return True
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
def allow_migrate(self, db, app_label, model=None, **hints):
|
|
24
|
+
"""
|
|
25
|
+
Make sure the auth app only appears in the 'amavis'
|
|
26
|
+
database.
|
|
27
|
+
"""
|
|
28
|
+
if app_label == "amavis":
|
|
29
|
+
# modoboa_amavis migrations should be created in the amavis
|
|
30
|
+
# database.
|
|
31
|
+
return db == "amavis"
|
|
32
|
+
elif db == "amavis":
|
|
33
|
+
# Don't create non modoboa_amavis migrations in the amavis database.
|
|
34
|
+
return False
|
|
35
|
+
return None
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Amavis factories."""
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
import factory
|
|
7
|
+
|
|
8
|
+
from . import models
|
|
9
|
+
from .utils import smart_bytes
|
|
10
|
+
|
|
11
|
+
SPAM_BODY = """X-Envelope-To: <{rcpt}>
|
|
12
|
+
X-Envelope-To-Blocked: <{rcpt}>
|
|
13
|
+
X-Quarantine-ID: <nq6ekd4wtXZg>
|
|
14
|
+
X-Spam-Flag: YES
|
|
15
|
+
X-Spam-Score: 1000.985
|
|
16
|
+
X-Spam-Level: ****************************************************************
|
|
17
|
+
X-Spam-Status: Yes, score=1000.985 tag=2 tag2=6.31 kill=6.31
|
|
18
|
+
tests=[ALL_TRUSTED=-1, GTUBE=1000, PYZOR_CHECK=1.985]
|
|
19
|
+
autolearn=no autolearn_force=no
|
|
20
|
+
Received: from demo.modoboa.org ([127.0.0.1])
|
|
21
|
+
by localhost (demo.modoboa.org [127.0.0.1]) (amavisd-new, port 10024)
|
|
22
|
+
with ESMTP id nq6ekd4wtXZg for <user@demo.local>;
|
|
23
|
+
Thu, 9 Nov 2017 15:59:52 +0100 (CET)
|
|
24
|
+
Received: from demo.modoboa.org (localhost [127.0.0.1])
|
|
25
|
+
by demo.modoboa.org (Postfix) with ESMTP
|
|
26
|
+
for <user@demo.local>; Thu, 9 Nov 2017 15:59:52 +0100 (CET)
|
|
27
|
+
Content-Type: text/plain; charset="utf-8"
|
|
28
|
+
MIME-Version: 1.0
|
|
29
|
+
Content-Transfer-Encoding: quoted-printable
|
|
30
|
+
Subject: Sample message
|
|
31
|
+
From: {sender}
|
|
32
|
+
To: {rcpt}
|
|
33
|
+
Message-ID: <151023959268.5550.5713670714483771838@demo.modoboa.org>
|
|
34
|
+
Date: Thu, 09 Nov 2017 15:59:52 +0100
|
|
35
|
+
|
|
36
|
+
This is the GTUBE, the
|
|
37
|
+
Generic
|
|
38
|
+
Test for
|
|
39
|
+
Unsolicited
|
|
40
|
+
Bulk
|
|
41
|
+
Email
|
|
42
|
+
|
|
43
|
+
If your spam filter supports it, the GTUBE provides a test by which you
|
|
44
|
+
can verify that the filter is installed correctly and is detecting incoming
|
|
45
|
+
spam. You can send yourself a test mail containing the following string of
|
|
46
|
+
characters (in upper case and with no white spaces and line breaks):
|
|
47
|
+
|
|
48
|
+
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
|
|
49
|
+
|
|
50
|
+
You should send this test mail from an account outside of your network.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
VIRUS_BODY = r"""Subject: Virus Test Message (EICAR)
|
|
54
|
+
MIME-Version: 1.0
|
|
55
|
+
Content-Type: multipart/mixed; boundary="huq684BweRXVnRxX"
|
|
56
|
+
Content-Disposition: inline
|
|
57
|
+
Date: Sun, 06 Nov 2011 10:08:18 -0800
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
--huq684BweRXVnRxX
|
|
61
|
+
Content-Type: text/plain; charset=us-ascii
|
|
62
|
+
Content-Disposition: inline
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
This is a virus test message. It contains an attached file 'eicar.com',
|
|
66
|
+
which contains the EICAR virus <http://eicar.org/86-0-Intended-use.html>
|
|
67
|
+
test pattern.
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
--huq684BweRXVnRxX
|
|
71
|
+
Content-Type: application/x-msdos-program
|
|
72
|
+
Content-Disposition: attachment; filename="eicar.com"
|
|
73
|
+
Content-Transfer-Encoding: quoted-printable
|
|
74
|
+
|
|
75
|
+
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*=0A
|
|
76
|
+
--huq684BweRXVnRxX--
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class MaddrFactory(factory.django.DjangoModelFactory):
|
|
81
|
+
"""Factory for Maddr."""
|
|
82
|
+
|
|
83
|
+
class Meta:
|
|
84
|
+
model = models.Maddr
|
|
85
|
+
django_get_or_create = ("email",)
|
|
86
|
+
|
|
87
|
+
id = factory.Sequence(lambda n: n) # NOQA:A003
|
|
88
|
+
email = factory.Sequence(lambda n: f"user_{n}@domain.test")
|
|
89
|
+
domain = "test.domain"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class MsgsFactory(factory.django.DjangoModelFactory):
|
|
93
|
+
"""Factory for Mailaddr."""
|
|
94
|
+
|
|
95
|
+
class Meta:
|
|
96
|
+
model = models.Msgs
|
|
97
|
+
|
|
98
|
+
mail_id = factory.Sequence(lambda n: f"mailid{n}".encode("ascii"))
|
|
99
|
+
secret_id = factory.Sequence(lambda n: smart_bytes(f"id{n}"))
|
|
100
|
+
sid = factory.SubFactory(MaddrFactory)
|
|
101
|
+
client_addr = "127.0.0.1"
|
|
102
|
+
originating = "Y"
|
|
103
|
+
dsn_sent = "N"
|
|
104
|
+
subject = factory.Sequence(lambda n: f"Test message {n}")
|
|
105
|
+
time_num = factory.LazyAttribute(lambda o: int(time.time()))
|
|
106
|
+
time_iso = factory.LazyAttribute(
|
|
107
|
+
lambda o: datetime.datetime.fromtimestamp(o.time_num).isoformat()
|
|
108
|
+
)
|
|
109
|
+
size = 100
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class MsgrcptFactory(factory.django.DjangoModelFactory):
|
|
113
|
+
"""Factory for Msgrcpt."""
|
|
114
|
+
|
|
115
|
+
class Meta:
|
|
116
|
+
model = models.Msgrcpt
|
|
117
|
+
|
|
118
|
+
rseqnum = 1
|
|
119
|
+
is_local = "Y"
|
|
120
|
+
bl = "N"
|
|
121
|
+
wl = "N"
|
|
122
|
+
mail = factory.SubFactory(MsgsFactory)
|
|
123
|
+
rid = factory.SubFactory(MaddrFactory)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class QuarantineFactory(factory.django.DjangoModelFactory):
|
|
127
|
+
"""Factory for Quarantine."""
|
|
128
|
+
|
|
129
|
+
class Meta:
|
|
130
|
+
model = models.Quarantine
|
|
131
|
+
|
|
132
|
+
chunk_ind = 1
|
|
133
|
+
mail = factory.SubFactory(MsgsFactory)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def create_quarantined_msg(rcpt, sender, rs, body, **kwargs):
|
|
137
|
+
"""Create a quarantined msg."""
|
|
138
|
+
msgrcpt = MsgrcptFactory(
|
|
139
|
+
rs=rs,
|
|
140
|
+
rid__email=rcpt,
|
|
141
|
+
rid__domain="com.test", # FIXME
|
|
142
|
+
mail__sid__email=smart_bytes(sender),
|
|
143
|
+
mail__sid__domain="", # FIXME
|
|
144
|
+
**kwargs,
|
|
145
|
+
)
|
|
146
|
+
QuarantineFactory(
|
|
147
|
+
mail=msgrcpt.mail,
|
|
148
|
+
mail_text=smart_bytes(SPAM_BODY.format(rcpt=rcpt, sender=sender)),
|
|
149
|
+
)
|
|
150
|
+
return msgrcpt
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def create_spam(rcpt, sender="spam@evil.corp", rs=" "):
|
|
154
|
+
"""Create a spam."""
|
|
155
|
+
body = SPAM_BODY.format(rcpt=rcpt, sender=sender)
|
|
156
|
+
body += "fóó bár"
|
|
157
|
+
return create_quarantined_msg(
|
|
158
|
+
rcpt, sender, rs, body, bspam_level=999.0, content="S"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def create_virus(rcpt, sender="virus@evil.corp", rs=" "):
|
|
163
|
+
"""Create a virus."""
|
|
164
|
+
return create_quarantined_msg(rcpt, sender, rs, VIRUS_BODY, content="V")
|