modoboa 2.4.11__py3-none-any.whl → 2.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. modoboa/admin/api/v2/serializers.py +14 -0
  2. modoboa/amavis/__init__.py +3 -0
  3. modoboa/amavis/app_settings.py +276 -0
  4. modoboa/amavis/apps.py +18 -0
  5. modoboa/amavis/checks/__init__.py +2 -0
  6. modoboa/amavis/checks/settings_checks.py +59 -0
  7. modoboa/amavis/dbrouter.py +35 -0
  8. modoboa/amavis/factories.py +164 -0
  9. modoboa/amavis/handlers.py +146 -0
  10. modoboa/amavis/lib.py +381 -0
  11. modoboa/amavis/management/__init__.py +0 -0
  12. modoboa/amavis/management/commands/__init__.py +0 -0
  13. modoboa/amavis/management/commands/amnotify.py +99 -0
  14. modoboa/amavis/management/commands/qcleanup.py +84 -0
  15. modoboa/amavis/migrations/0001_initial.py +340 -0
  16. modoboa/amavis/migrations/__init__.py +0 -0
  17. modoboa/amavis/models.py +226 -0
  18. modoboa/amavis/serializers.py +139 -0
  19. modoboa/amavis/sql_connector.py +240 -0
  20. modoboa/amavis/sql_email.py +66 -0
  21. modoboa/amavis/tasks.py +33 -0
  22. modoboa/amavis/templates/amavis/notifications/pending_requests.html +16 -0
  23. modoboa/amavis/tests/__init__.py +0 -0
  24. modoboa/amavis/tests/sa-learn +3 -0
  25. modoboa/amavis/tests/sample_messages/quarantined-input.txt +80 -0
  26. modoboa/amavis/tests/sample_messages/quarantined-output-plain_nolinks.txt +17 -0
  27. modoboa/amavis/tests/spamc +3 -0
  28. modoboa/amavis/tests/test_checks.py +25 -0
  29. modoboa/amavis/tests/test_handlers.py +214 -0
  30. modoboa/amavis/tests/test_lib.py +90 -0
  31. modoboa/amavis/tests/test_management_commands.py +45 -0
  32. modoboa/amavis/tests/test_sql_email.py +67 -0
  33. modoboa/amavis/tests/test_utils.py +19 -0
  34. modoboa/amavis/tests/test_viewsets.py +319 -0
  35. modoboa/amavis/urls.py +11 -0
  36. modoboa/amavis/utils.py +105 -0
  37. modoboa/amavis/viewsets.py +265 -0
  38. modoboa/core/api/v1/serializers.py +7 -5
  39. modoboa/core/api/v2/serializers.py +4 -2
  40. modoboa/core/api/v2/tests.py +16 -4
  41. modoboa/core/api/v2/urls.py +5 -5
  42. modoboa/core/api/v2/views.py +6 -2
  43. modoboa/core/api/v2/viewsets.py +24 -3
  44. modoboa/core/commands/deploy.py +3 -0
  45. modoboa/core/commands/templates/settings.py.tpl +12 -11
  46. modoboa/core/handlers.py +6 -2
  47. modoboa/core/management/commands/add_allowed_hosts.py +33 -0
  48. modoboa/core/management/commands/load_initial_data.py +10 -0
  49. modoboa/core/migrations/0025_rename_user_email_is_active_core_user_email_c0c03f_idx.py +23 -5
  50. modoboa/core/tests/test_core.py +24 -0
  51. modoboa/core/utils.py +3 -0
  52. modoboa/frontend_dist/assets/AccountAliasForm-C0oHHyZL.js +1 -0
  53. modoboa/frontend_dist/assets/AccountEditView-lgSJ2Se8.js +1 -0
  54. modoboa/frontend_dist/assets/AccountLayout-U386K8zy.js +1 -0
  55. modoboa/frontend_dist/assets/AccountPasswordSubForm-YsaE_cDx.js +1 -0
  56. modoboa/frontend_dist/assets/AccountView-1jfKFDwb.js +1 -0
  57. modoboa/frontend_dist/assets/AddressBook-CwN64Zls.js +1 -0
  58. modoboa/frontend_dist/assets/AdminLayout-Cxm1lggg.js +1 -0
  59. modoboa/frontend_dist/assets/AlarmsView-9yKGbmkC.css +1 -0
  60. modoboa/frontend_dist/assets/AlarmsView-Bcjsicac.js +1 -0
  61. modoboa/frontend_dist/assets/AliasEditView-k3rVt1tG.js +1 -0
  62. modoboa/frontend_dist/assets/{AliasRecipientForm-IOae6sjF.js → AliasRecipientForm-IehUzKok.js} +1 -1
  63. modoboa/frontend_dist/assets/AliasView-DMzA10eD.js +1 -0
  64. modoboa/frontend_dist/assets/AuditTrailView-5dnGX5El.js +1 -0
  65. modoboa/frontend_dist/assets/CalendarView-DZONeDA9.js +1 -0
  66. modoboa/frontend_dist/assets/{ChoiceField-DJ_c78Cm.js → ChoiceField-DnwXRkht.js} +1 -1
  67. modoboa/frontend_dist/assets/ComposeEmailForm-kghmfNuE.js +1 -0
  68. modoboa/frontend_dist/assets/ComposeEmailView-DLv3wk1k.js +1 -0
  69. modoboa/frontend_dist/assets/ConfirmDialog-CcPrCKuI.js +1 -0
  70. modoboa/frontend_dist/assets/{ConnectedLayout-Dvwmicnc.css → ConnectedLayout-Bxh21hcH.css} +1 -1
  71. modoboa/frontend_dist/assets/ConnectedLayout-CWlBK7Hf.js +1 -0
  72. modoboa/frontend_dist/assets/CreationForm-CW4lxnPg.js +1 -0
  73. modoboa/frontend_dist/assets/DashboardView-DXVZMbMo.js +1 -0
  74. modoboa/frontend_dist/assets/DomainAdminList-C3jcDDc3.js +1 -0
  75. modoboa/frontend_dist/assets/DomainEditView-ph8AaElX.js +1 -0
  76. modoboa/frontend_dist/assets/{DomainTransportForm-C2xo0Yd7.js → DomainTransportForm-NCz6Bl-h.js} +1 -1
  77. modoboa/frontend_dist/assets/DomainView-BgMSSuU-.js +5 -0
  78. modoboa/frontend_dist/assets/{DomainView-BDKoBFYr.css → DomainView-CCLYXPHx.css} +1 -1
  79. modoboa/frontend_dist/assets/DomainsView-CEEU9btK.js +1 -0
  80. modoboa/frontend_dist/assets/DomainsView-DZ-ss9bI.css +1 -0
  81. modoboa/frontend_dist/assets/EmailField-DeqDPm5j.js +1 -0
  82. modoboa/frontend_dist/assets/EmailView-DczVhVO0.js +1 -0
  83. modoboa/frontend_dist/assets/EmptyLayout-BXgcfMLH.js +1 -0
  84. modoboa/frontend_dist/assets/FiltersView-nJj_gSCx.js +1 -0
  85. modoboa/frontend_dist/assets/ForwardEmailView-Bgv3JQb6.js +1 -0
  86. modoboa/frontend_dist/assets/{HtmlEditor-CJ9umKeO.js → HtmlEditor-BWRdelVw.js} +1 -1
  87. modoboa/frontend_dist/assets/{IdentitiesView-0ziuQ5s-.css → IdentitiesView-DPrrRMS5.css} +1 -1
  88. modoboa/frontend_dist/assets/IdentitiesView-Dld9IloZ.js +1 -0
  89. modoboa/frontend_dist/assets/InformationView-BBWKSX8D.js +1 -0
  90. modoboa/frontend_dist/assets/InformationView-C9vvvQhJ.css +1 -0
  91. modoboa/frontend_dist/assets/{LoadingData-CYwX3Jpn.js → LoadingData-G57nJ_JV.js} +1 -1
  92. modoboa/frontend_dist/assets/{LoginCallbackView-E01qkKn0.js → LoginCallbackView-DjyE2SG_.js} +1 -1
  93. modoboa/frontend_dist/assets/{LoginView-Cy4uFV9h.js → LoginView-CqCCXYLo.js} +1 -1
  94. modoboa/frontend_dist/assets/{MailboxView-B-aI4XBq.css → MailboxView-CfStlWhk.css} +1 -1
  95. modoboa/frontend_dist/assets/MailboxView-DRrs9eLO.js +1 -0
  96. modoboa/frontend_dist/assets/MenuItems-BqIZW5av.js +1 -0
  97. modoboa/frontend_dist/assets/MessageView-D_6tx_gd.js +1 -0
  98. modoboa/frontend_dist/assets/MessagesView-BH7JIR03.js +1 -0
  99. modoboa/frontend_dist/assets/MigrationsView-Cv_So9T-.js +1 -0
  100. modoboa/frontend_dist/assets/{ParametersForm-BZM0QSvg.js → ParametersForm-3qXttTuQ.js} +1 -1
  101. modoboa/frontend_dist/assets/ParametersView-3Ns04cpQ.js +1 -0
  102. modoboa/frontend_dist/assets/ParametersView-B5B5Dt6K.js +1 -0
  103. modoboa/frontend_dist/assets/ProviderEditView-zh7CY832.js +1 -0
  104. modoboa/frontend_dist/assets/ProviderGeneralForm-BQU7t3ma.js +1 -0
  105. modoboa/frontend_dist/assets/ProvidersView-CoF_ZkZA.js +1 -0
  106. modoboa/frontend_dist/assets/QuarantineLayout-CYBsrbJM.js +1 -0
  107. modoboa/frontend_dist/assets/QuarantineView-D4gOE4EQ.css +1 -0
  108. modoboa/frontend_dist/assets/QuarantineView-DNvpoycb.js +1 -0
  109. modoboa/frontend_dist/assets/ReplyEmailView-D1XTcglu.js +1 -0
  110. modoboa/frontend_dist/assets/ResourcesForm-BW8rUGgZ.js +1 -0
  111. modoboa/frontend_dist/assets/SelfServiceLayout-DfDHiYeX.js +1 -0
  112. modoboa/frontend_dist/assets/{SettingsView-BxLJBFY0.js → SettingsView-gQiJ2NVb.js} +2 -2
  113. modoboa/frontend_dist/assets/StatisticsView-DYalet_q.js +1 -0
  114. modoboa/frontend_dist/assets/TimeSerieChart-BZ2htbFk.js +1 -0
  115. modoboa/frontend_dist/assets/UserLayout-zUtHi-z-.js +1 -0
  116. modoboa/frontend_dist/assets/VAlert-4r6LxKtg.js +1 -0
  117. modoboa/frontend_dist/assets/VApp-CX_C7AUN.js +1 -0
  118. modoboa/frontend_dist/assets/VAutocomplete-DNKmBvyZ.js +1 -0
  119. modoboa/frontend_dist/assets/VAvatar-DbuoZWmf.js +1 -0
  120. modoboa/frontend_dist/assets/VBadge-BQrRJ9S0.css +1 -0
  121. modoboa/frontend_dist/assets/VBadge-Bv2nvUmC.js +1 -0
  122. modoboa/frontend_dist/assets/VCard-DzjUT5OP.js +1 -0
  123. modoboa/frontend_dist/assets/VCheckbox-dr7UFjl4.js +1 -0
  124. modoboa/frontend_dist/assets/{VCheckboxBtn-Dt810gWf.js → VCheckboxBtn-CpFdBnTv.js} +1 -1
  125. modoboa/frontend_dist/assets/VChip-CaQvfmkw.js +1 -0
  126. modoboa/frontend_dist/assets/VColorPicker-ByGpCW5O.js +1 -0
  127. modoboa/frontend_dist/assets/{VContainer-DvTbsotR.js → VContainer-74Dnn8Ux.js} +1 -1
  128. modoboa/frontend_dist/assets/VDataTable-CL7yHvG7.js +1 -0
  129. modoboa/frontend_dist/assets/VDataTableServer-BqvNcIdw.js +1 -0
  130. modoboa/frontend_dist/assets/VDataTableVirtual--KsOP8i6.js +1 -0
  131. modoboa/frontend_dist/assets/{VDialog-Bk6EWNhz.js → VDialog-DmTGCGR0.js} +1 -1
  132. modoboa/frontend_dist/assets/VExpansionPanels-B7sSTCwd.js +1 -0
  133. modoboa/frontend_dist/assets/VFileInput-SULIc6F3.js +1 -0
  134. modoboa/frontend_dist/assets/VForm-DsRLc-sa.js +1 -0
  135. modoboa/frontend_dist/assets/VInput-CcxkaOXT.css +1 -0
  136. modoboa/frontend_dist/assets/VInput-DVKUObZe.js +1 -0
  137. modoboa/frontend_dist/assets/VMenu-nv0XOgg0.js +1 -0
  138. modoboa/frontend_dist/assets/VPicker-DnDSWJHJ.js +1 -0
  139. modoboa/frontend_dist/assets/VProgressCircular-qK6p5X_Y.js +1 -0
  140. modoboa/frontend_dist/assets/VRadioGroup-CbiPLy0t.js +1 -0
  141. modoboa/frontend_dist/assets/{VRow-BF35mT1S.js → VRow-DJ0NB63-.js} +1 -1
  142. modoboa/frontend_dist/assets/VSelect-CxCFMHyF.js +1 -0
  143. modoboa/frontend_dist/assets/VSelectionControl-C-6A4us5.js +1 -0
  144. modoboa/frontend_dist/assets/VSheet-DI6SxLnG.js +1 -0
  145. modoboa/frontend_dist/assets/VSpacer-CoJVmx8k.js +1 -0
  146. modoboa/frontend_dist/assets/VSwitch-DPnjPQuU.js +1 -0
  147. modoboa/frontend_dist/assets/VTable-ldTxgQPW.js +1 -0
  148. modoboa/frontend_dist/assets/VTabs-aS8WSL9I.js +1 -0
  149. modoboa/frontend_dist/assets/VTextField-BzBVKKob.css +1 -0
  150. modoboa/frontend_dist/assets/VTextField-DKbr4H5w.js +1 -0
  151. modoboa/frontend_dist/assets/VTextarea-BttkFsM4.js +1 -0
  152. modoboa/frontend_dist/assets/VToolbar-BxX3W2kR.js +1 -0
  153. modoboa/frontend_dist/assets/VWindowItem-Cvqvdegd.js +1 -0
  154. modoboa/frontend_dist/assets/WebmailLayout-BT2k6U7q.js +1 -0
  155. modoboa/frontend_dist/assets/accounts-CC2F0a0c.js +1 -0
  156. modoboa/frontend_dist/assets/{admin-o-HRGnmT.js → admin-CHCHFGI6.js} +1 -1
  157. modoboa/frontend_dist/assets/{aliases-DDVeehyg.js → aliases-C9bUD4Ws.js} +1 -1
  158. modoboa/frontend_dist/assets/amavis-BhzV4rgf.js +1 -0
  159. modoboa/frontend_dist/assets/amavis-DCVJxuui.js +1 -0
  160. modoboa/frontend_dist/assets/{contacts-C84DY-Q1.js → contacts-Dxz6eWpf.js} +1 -1
  161. modoboa/frontend_dist/assets/{domains-Bgn4ixHL.js → domains-C2cornvL.js} +1 -1
  162. modoboa/frontend_dist/assets/{domains.store-DTE-V7Y1.js → domains.store-BLKRipG8.js} +1 -1
  163. modoboa/frontend_dist/assets/{filter-CnffiQAW.js → filter-rmxrcjKk.js} +1 -1
  164. modoboa/frontend_dist/assets/forwardRefs-CpzzjgpX.js +1 -0
  165. modoboa/frontend_dist/assets/global.store-DndbMXYb.js +1 -0
  166. modoboa/frontend_dist/assets/{importExport-BlQYb0NO.js → importExport-C3uqrcok.js} +1 -1
  167. modoboa/frontend_dist/assets/index-LhNzkzAh.js +984 -0
  168. modoboa/frontend_dist/assets/layout-DbjDe3Wl.js +1 -0
  169. modoboa/frontend_dist/assets/{layout.store-DkjrAoXt.js → layout.store-Vq5mvIp7.js} +1 -1
  170. modoboa/frontend_dist/assets/{logos-q8SEyAa4.js → logos-Bvcy0usu.js} +1 -1
  171. modoboa/frontend_dist/assets/{logs-B7IJ7LBa.js → logs-BuItINky.js} +1 -1
  172. modoboa/frontend_dist/assets/{parameters-A6iBEYQq.js → parameters-C8IYEP7q.js} +1 -1
  173. modoboa/frontend_dist/assets/{parameters.store-BiXS4_6w.js → parameters.store-1cwSP2JP.js} +1 -1
  174. modoboa/frontend_dist/assets/permissions-DQjAcO9S.js +1 -0
  175. modoboa/frontend_dist/assets/{ssrBoot-AzTdjPjk.js → ssrBoot-BxIQ9ccA.js} +1 -1
  176. modoboa/frontend_dist/assets/{tag-BnSYRTcD.js → tag-3cfI1_f7.js} +1 -1
  177. modoboa/frontend_dist/assets/transports-D4Jk4-AP.js +1 -0
  178. modoboa/frontend_dist/assets/{webmail-CSH_3l6R.js → webmail-B2IUjaxM.js} +1 -1
  179. modoboa/frontend_dist/index.html +1 -1
  180. modoboa/lib/email_utils.py +2 -2
  181. modoboa/lib/permissions.py +7 -0
  182. modoboa/lib/test_runners.py +29 -0
  183. modoboa/lib/tests/__init__.py +5 -1
  184. modoboa/locale/br/LC_MESSAGES/django.po +87 -75
  185. modoboa/locale/cs/LC_MESSAGES/django.po +82 -74
  186. modoboa/locale/cs_CZ/LC_MESSAGES/django.po +145 -121
  187. modoboa/locale/de/LC_MESSAGES/django.mo +0 -0
  188. modoboa/locale/de/LC_MESSAGES/django.po +339 -651
  189. modoboa/locale/de_DE/LC_MESSAGES/django.po +87 -75
  190. modoboa/locale/el_GR/LC_MESSAGES/django.po +160 -135
  191. modoboa/locale/en/LC_MESSAGES/django.po +82 -74
  192. modoboa/locale/es/LC_MESSAGES/django.po +158 -131
  193. modoboa/locale/es_MX/LC_MESSAGES/django.po +82 -74
  194. modoboa/locale/fi/LC_MESSAGES/django.po +87 -75
  195. modoboa/locale/fr/LC_MESSAGES/django.mo +0 -0
  196. modoboa/locale/fr/LC_MESSAGES/django.po +469 -201
  197. modoboa/locale/hu/LC_MESSAGES/django.po +82 -74
  198. modoboa/locale/it/LC_MESSAGES/django.mo +0 -0
  199. modoboa/locale/it/LC_MESSAGES/django.po +148 -122
  200. modoboa/locale/ja_JP/LC_MESSAGES/django.mo +0 -0
  201. modoboa/locale/ja_JP/LC_MESSAGES/django.po +80 -72
  202. modoboa/locale/ka/LC_MESSAGES/django.po +82 -74
  203. modoboa/locale/nl_NL/LC_MESSAGES/django.po +160 -132
  204. modoboa/locale/no/LC_MESSAGES/django.po +82 -74
  205. modoboa/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
  206. modoboa/locale/pl_PL/LC_MESSAGES/django.po +172 -149
  207. modoboa/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  208. modoboa/locale/pt_BR/LC_MESSAGES/django.po +172 -144
  209. modoboa/locale/pt_PT/LC_MESSAGES/django.po +135 -112
  210. modoboa/locale/ro_RO/LC_MESSAGES/django.po +87 -75
  211. modoboa/locale/ru/LC_MESSAGES/django.po +142 -118
  212. modoboa/locale/si/LC_MESSAGES/django.po +82 -74
  213. modoboa/locale/sk/LC_MESSAGES/django.po +82 -74
  214. modoboa/locale/sk_SK/LC_MESSAGES/django.po +84 -76
  215. modoboa/locale/sl_SI/LC_MESSAGES/django.po +90 -76
  216. modoboa/locale/sv/LC_MESSAGES/django.mo +0 -0
  217. modoboa/locale/sv/LC_MESSAGES/django.po +172 -139
  218. modoboa/locale/tr/LC_MESSAGES/django.po +87 -75
  219. modoboa/locale/tr_TR/LC_MESSAGES/django.po +84 -74
  220. modoboa/locale/uk/LC_MESSAGES/django.po +82 -74
  221. modoboa/locale/zh/LC_MESSAGES/django.po +82 -74
  222. modoboa/locale/zh_CN/LC_MESSAGES/django.po +82 -74
  223. modoboa/locale/zh_TW/LC_MESSAGES/django.po +87 -75
  224. modoboa/parameters/api/v2/tests.py +2 -2
  225. modoboa/parameters/api/v2/viewsets.py +2 -0
  226. modoboa/policyd/tests.py +2 -0
  227. modoboa/urls_api_v2.py +6 -0
  228. modoboa/webmail/lib/imaputils.py +2 -2
  229. {modoboa-2.4.11.dist-info → modoboa-2.5.1.dist-info}/METADATA +6 -4
  230. {modoboa-2.4.11.dist-info → modoboa-2.5.1.dist-info}/RECORD +235 -185
  231. modoboa/frontend_dist/assets/AccountAliasForm-BV6KvTu6.js +0 -1
  232. modoboa/frontend_dist/assets/AccountEditView-DDOFyfBD.js +0 -1
  233. modoboa/frontend_dist/assets/AccountLayout-rX51xgxT.js +0 -1
  234. modoboa/frontend_dist/assets/AccountPasswordSubForm-D9S6LaeH.js +0 -1
  235. modoboa/frontend_dist/assets/AccountView-cmvaZNq3.js +0 -1
  236. modoboa/frontend_dist/assets/AddressBook-DCJxL8SU.js +0 -1
  237. modoboa/frontend_dist/assets/AdminLayout-r0wfG2lO.js +0 -1
  238. modoboa/frontend_dist/assets/AlarmsView-Bheey-gp.css +0 -1
  239. modoboa/frontend_dist/assets/AlarmsView-C0bqC4PA.js +0 -1
  240. modoboa/frontend_dist/assets/AliasEditView-DVoWoCGY.js +0 -1
  241. modoboa/frontend_dist/assets/AliasView-DrONZXOh.js +0 -1
  242. modoboa/frontend_dist/assets/AuditTrailView-OTkoZaMU.js +0 -1
  243. modoboa/frontend_dist/assets/CalendarView-CqF4_Ui9.js +0 -1
  244. modoboa/frontend_dist/assets/ComposeEmailForm-DO5_GB3e.js +0 -1
  245. modoboa/frontend_dist/assets/ComposeEmailView-A91HCBsN.js +0 -1
  246. modoboa/frontend_dist/assets/ConfirmDialog-BBcgdAnO.js +0 -1
  247. modoboa/frontend_dist/assets/ConnectedLayout-1oRW-Rql.js +0 -1
  248. modoboa/frontend_dist/assets/CreationForm-71YJbjsA.js +0 -1
  249. modoboa/frontend_dist/assets/DashboardView-CdLpSfUl.js +0 -1
  250. modoboa/frontend_dist/assets/DomainAdminList-BjC4KsqI.js +0 -1
  251. modoboa/frontend_dist/assets/DomainEditView-CQjKwYxl.js +0 -1
  252. modoboa/frontend_dist/assets/DomainView-BhhuZI_N.js +0 -5
  253. modoboa/frontend_dist/assets/DomainsView-Cft4BP8Z.js +0 -1
  254. modoboa/frontend_dist/assets/DomainsView-DasJ0NdZ.css +0 -1
  255. modoboa/frontend_dist/assets/EmailField-C8umy0EU.js +0 -1
  256. modoboa/frontend_dist/assets/EmailView-ki7uEQPD.js +0 -1
  257. modoboa/frontend_dist/assets/EmptyLayout-DaA1XH9n.js +0 -1
  258. modoboa/frontend_dist/assets/FiltersView-FYFZxG4B.js +0 -1
  259. modoboa/frontend_dist/assets/ForwardEmailView-cUbnSYCF.js +0 -1
  260. modoboa/frontend_dist/assets/IdentitiesView-njNo8N5n.js +0 -1
  261. modoboa/frontend_dist/assets/InformationView-D1h38POt.js +0 -1
  262. modoboa/frontend_dist/assets/InformationView-U5Ww-Sx1.css +0 -1
  263. modoboa/frontend_dist/assets/MailboxView-IlrLWm_H.js +0 -1
  264. modoboa/frontend_dist/assets/MenuItems-BAtHWzAE.js +0 -1
  265. modoboa/frontend_dist/assets/MessagesView-OSpjixFq.js +0 -1
  266. modoboa/frontend_dist/assets/MigrationsView-DKNOsVzF.js +0 -1
  267. modoboa/frontend_dist/assets/ParametersView-C4bXASiq.js +0 -1
  268. modoboa/frontend_dist/assets/ParametersView-CYXgNmc1.js +0 -1
  269. modoboa/frontend_dist/assets/ProviderEditView-CyxCWTST.js +0 -1
  270. modoboa/frontend_dist/assets/ProviderGeneralForm-BYPjNHqB.js +0 -1
  271. modoboa/frontend_dist/assets/ProvidersView-CxrMkRyk.js +0 -1
  272. modoboa/frontend_dist/assets/ReplyEmailView-Dkw9-N26.js +0 -1
  273. modoboa/frontend_dist/assets/ResourcesForm-CuUvrOdY.js +0 -1
  274. modoboa/frontend_dist/assets/StatisticsView-BN7QsZMT.js +0 -1
  275. modoboa/frontend_dist/assets/TimeSerieChart-BMN8BeFZ.js +0 -1
  276. modoboa/frontend_dist/assets/UserLayout-B6-JQg4F.js +0 -1
  277. modoboa/frontend_dist/assets/VAlert-DIQTrRif.js +0 -1
  278. modoboa/frontend_dist/assets/VApp-CpkYA7js.js +0 -1
  279. modoboa/frontend_dist/assets/VAutocomplete-C4IpXyl8.js +0 -1
  280. modoboa/frontend_dist/assets/VAvatar-Lpb-Dion.js +0 -1
  281. modoboa/frontend_dist/assets/VCard-er_isjE_.js +0 -1
  282. modoboa/frontend_dist/assets/VCheckbox-D-u8JXP1.js +0 -1
  283. modoboa/frontend_dist/assets/VChip-B4iSpj8_.js +0 -1
  284. modoboa/frontend_dist/assets/VColorPicker-BAjGDsXv.js +0 -1
  285. modoboa/frontend_dist/assets/VDataTable-4JRjbtgF.js +0 -1
  286. modoboa/frontend_dist/assets/VDataTableServer-tIDT1m3-.js +0 -1
  287. modoboa/frontend_dist/assets/VDataTableVirtual-BlnO18u_.js +0 -1
  288. modoboa/frontend_dist/assets/VExpansionPanels-CwGtXDhr.js +0 -1
  289. modoboa/frontend_dist/assets/VFileInput-D1_7ZkO_.js +0 -1
  290. modoboa/frontend_dist/assets/VForm-DAkW4nfy.js +0 -1
  291. modoboa/frontend_dist/assets/VMenu-BPFJwj2f.js +0 -1
  292. modoboa/frontend_dist/assets/VPicker-CfT82M8N.js +0 -1
  293. modoboa/frontend_dist/assets/VProgressCircular-w75-3ogi.js +0 -1
  294. modoboa/frontend_dist/assets/VRadioGroup-0j6DNC_k.js +0 -1
  295. modoboa/frontend_dist/assets/VSelect-Cs4ARbAS.js +0 -1
  296. modoboa/frontend_dist/assets/VSelectionControl-Dg-XyRRS.js +0 -1
  297. modoboa/frontend_dist/assets/VSheet-Btq_Mu4s.js +0 -1
  298. modoboa/frontend_dist/assets/VSpacer-C7xukQmu.js +0 -1
  299. modoboa/frontend_dist/assets/VSwitch-Cs1NQrmk.js +0 -1
  300. modoboa/frontend_dist/assets/VTable-CNz2SGk4.js +0 -1
  301. modoboa/frontend_dist/assets/VTabs-B1fyVn4M.js +0 -1
  302. modoboa/frontend_dist/assets/VTextField-BdyvgvkG.js +0 -1
  303. modoboa/frontend_dist/assets/VTextField-C-J20yj_.css +0 -1
  304. modoboa/frontend_dist/assets/VTextarea-DnOMpe0Q.js +0 -1
  305. modoboa/frontend_dist/assets/VToolbar-BiCiBxBJ.js +0 -1
  306. modoboa/frontend_dist/assets/VWindowItem-ChWm_kz3.js +0 -1
  307. modoboa/frontend_dist/assets/WebmailLayout-o4uEkp9e.js +0 -1
  308. modoboa/frontend_dist/assets/forwardRefs-Dvjn_Xq4.js +0 -1
  309. modoboa/frontend_dist/assets/global.store-BaiD63EN.js +0 -1
  310. modoboa/frontend_dist/assets/index-I1VDlN4g.js +0 -984
  311. modoboa/frontend_dist/assets/layout-D8ZJPiJ_.js +0 -1
  312. modoboa/frontend_dist/assets/permissions-CITHLHVg.js +0 -1
  313. modoboa/frontend_dist/assets/transports-Dz7c6kIy.js +0 -1
  314. {modoboa-2.4.11.data → modoboa-2.5.1.data}/scripts/modoboa-admin.py +0 -0
  315. {modoboa-2.4.11.dist-info → modoboa-2.5.1.dist-info}/WHEEL +0 -0
  316. {modoboa-2.4.11.dist-info → modoboa-2.5.1.dist-info}/entry_points.txt +0 -0
  317. {modoboa-2.4.11.dist-info → modoboa-2.5.1.dist-info}/licenses/LICENSE +0 -0
  318. {modoboa-2.4.11.dist-info → modoboa-2.5.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1 @@
1
+ import{d as ne}from"./tag-3cfI1_f7.js";import{J as Z,N as T,h as v,g as ae,aT as $,a7 as E,a2 as R,aR as D,a6 as W,d as se,av as ue,aU as le,aV as ie,aw as re,ak as X,aW as ce}from"./index-LhNzkzAh.js";const M=Symbol.for("vuetify:layout"),q=Symbol.for("vuetify:layout-item"),U=1e3,pe=Z({overlaps:{type:Array,default:()=>[]},fullHeight:Boolean},"layout"),me=Z({name:{type:String},order:{type:[Number,String],default:0},absolute:Boolean},"layout-item");function ge(){const s=T(M);if(!s)throw new Error("[Vuetify] Could not find injected layout");return{getLayoutItem:s.getLayoutItem,mainRect:s.mainRect,mainStyles:s.mainStyles}}function he(s){const u=T(M);if(!u)throw new Error("[Vuetify] Could not find injected layout");const d=s.id??`layout-item-${ue()}`,i=D("useLayoutItem");X(q,{id:d});const n=W(!1);le(()=>n.value=!0),ie(()=>n.value=!1);const{layoutItemStyles:r,layoutItemScrimStyles:c}=u.register(i,{...s,active:v(()=>n.value?!1:s.active.value),id:d});return re(()=>u.unregister(d)),{layoutItemStyles:r,layoutRect:u.layoutRect,layoutItemScrimStyles:c}}const ve=(s,u,d,i)=>{let n={top:0,left:0,right:0,bottom:0};const r=[{id:"",layer:{...n}}];for(const c of s){const m=u.get(c),g=d.get(c),z=i.get(c);if(!m||!g||!z)continue;const h={...n,[m.value]:parseInt(n[m.value],10)+(z.value?parseInt(g.value,10):0)};r.push({id:c,layer:h}),n=h}return r};function Ie(s){const u=T(M,null),d=v(()=>u?u.rootZIndex.value-100:U),i=ae([]),n=$(new Map),r=$(new Map),c=$(new Map),m=$(new Map),g=$(new Map),{resizeRef:z,contentRect:h}=ne(),F=v(()=>{const t=new Map,l=s.overlaps??[];for(const e of l.filter(a=>a.includes(":"))){const[a,o]=e.split(":");if(!i.value.includes(a)||!i.value.includes(o))continue;const f=n.get(a),p=n.get(o),S=r.get(a),w=r.get(o);!f||!p||!S||!w||(t.set(o,{position:f.value,amount:parseInt(S.value,10)}),t.set(a,{position:p.value,amount:-parseInt(w.value,10)}))}return t}),I=v(()=>{const t=[...new Set([...c.values()].map(e=>e.value))].sort((e,a)=>e-a),l=[];for(const e of t){const a=i.value.filter(o=>{var f;return((f=c.get(o))==null?void 0:f.value)===e});l.push(...a)}return ve(l,n,r,m)}),H=v(()=>!Array.from(g.values()).some(t=>t.value)),b=v(()=>I.value[I.value.length-1].layer),J=E(()=>({"--v-layout-left":R(b.value.left),"--v-layout-right":R(b.value.right),"--v-layout-top":R(b.value.top),"--v-layout-bottom":R(b.value.bottom),...H.value?void 0:{transition:"none"}})),x=v(()=>I.value.slice(1).map((t,l)=>{let{id:e}=t;const{layer:a}=I.value[l],o=r.get(e),f=n.get(e);return{id:e,...a,size:Number(o.value),position:f.value}})),N=t=>x.value.find(l=>l.id===t),O=D("createLayout"),j=W(!1);se(()=>{j.value=!0}),X(M,{register:(t,l)=>{let{id:e,order:a,position:o,layoutSize:f,elementSize:p,active:S,disableTransitions:w,absolute:G}=l;c.set(e,a),n.set(e,o),r.set(e,f),m.set(e,S),w&&g.set(e,w);const k=ce(q,O==null?void 0:O.vnode).indexOf(t);k>-1?i.value.splice(k,0,e):i.value.push(e);const B=v(()=>x.value.findIndex(L=>L.id===e)),V=v(()=>d.value+I.value.length*2-B.value*2),Q=v(()=>{const L=o.value==="left"||o.value==="right",A=o.value==="right",te=o.value==="bottom",C=p.value??f.value,oe=C===0?"%":"px",K={[o.value]:0,zIndex:V.value,transform:`translate${L?"X":"Y"}(${(S.value?0:-(C===0?100:C))*(A||te?-1:1)}${oe})`,position:G.value||d.value!==U?"absolute":"fixed",...H.value?void 0:{transition:"none"}};if(!j.value)return K;const y=x.value[B.value];if(!y)throw new Error(`[Vuetify] Could not find layout item "${e}"`);const P=F.value.get(e);return P&&(y[P.position]+=P.amount),{...K,height:L?`calc(100% - ${y.top}px - ${y.bottom}px)`:p.value?`${p.value}px`:void 0,left:A?void 0:`${y.left}px`,right:A?`${y.right}px`:void 0,top:o.value!=="bottom"?`${y.top}px`:void 0,bottom:o.value!=="top"?`${y.bottom}px`:void 0,width:L?p.value?`${p.value}px`:void 0:`calc(100% - ${y.left}px - ${y.right}px)`}}),ee=v(()=>({zIndex:V.value-1}));return{layoutItemStyles:Q,layoutItemScrimStyles:ee,zIndex:V}},unregister:t=>{c.delete(t),n.delete(t),r.delete(t),m.delete(t),g.delete(t),i.value=i.value.filter(l=>l!==t)},mainRect:b,mainStyles:J,getLayoutItem:N,items:x,layoutRect:h,rootZIndex:d});const Y=E(()=>["v-layout",{"v-layout--full-height":s.fullHeight}]),_=E(()=>({zIndex:u?d.value:void 0,position:u?"relative":void 0,overflow:u?"hidden":void 0}));return{layoutClasses:Y,layoutStyles:_,getLayoutItem:N,items:x,layoutRect:h,layoutRef:z}}export{M as V,he as a,me as b,Ie as c,pe as m,ge as u};
@@ -1 +1 @@
1
- import{O as a,g as s}from"./index-I1VDlN4g.js";const r=a("layout",()=>{const e=s([]),t=s(!1);function n(u){e.value=u}async function o(){e.value=[],t.value=!1}return{leftMenuItems:e,compactLeftMenu:t,setLeftMenuItems:n,$reset:o}});export{r as u};
1
+ import{E as a,g as s}from"./index-LhNzkzAh.js";const r=a("layout",()=>{const e=s([]),t=s(!1);function n(u){e.value=u}async function o(){e.value=[],t.value=!1}return{leftMenuItems:e,compactLeftMenu:t,setLeftMenuItems:n,$reset:o}});export{r as u};
@@ -1 +1 @@
1
- import{h as r,b7 as s}from"./index-I1VDlN4g.js";function i(){const o=s(),t=r(()=>o.MENU_LOGO_PATH?o.MENU_LOGO_PATH:new URL("/assets/Modoboa_RVB-BLANC-SANS-BBGoASES.png",import.meta.url).href),n=r(()=>o.CREATION_FORM_LOGO_PATH?o.CREATION_FORM_LOGO_PATH:new URL("/assets/Modoboa_RVB-BLEU-SANS-pKrnjsR_.png",import.meta.url).href);return{menuLogoPath:t,creationFormLogoPath:n}}export{i as u};
1
+ import{h as r,bl as s}from"./index-LhNzkzAh.js";function i(){const o=s(),t=r(()=>o.MENU_LOGO_PATH?o.MENU_LOGO_PATH:new URL("/assets/Modoboa_RVB-BLANC-SANS-BBGoASES.png",import.meta.url).href),n=r(()=>o.CREATION_FORM_LOGO_PATH?o.CREATION_FORM_LOGO_PATH:new URL("/assets/Modoboa_RVB-BLEU-SANS-pKrnjsR_.png",import.meta.url).href);return{menuLogoPath:t,creationFormLogoPath:n}}export{i as u};
@@ -1 +1 @@
1
- import{_ as e}from"./index-I1VDlN4g.js";const t="logs",o={getAuditTrail(s){return e.get(`/${t}/audit-trail/`,{params:s})},getMessages(s){return e.get(`/${t}/messages/`,{params:s})}};export{o as l};
1
+ import{C as e}from"./index-LhNzkzAh.js";const t="logs",o={getAuditTrail(s){return e.get(`/${t}/audit-trail/`,{params:s})},getMessages(s){return e.get(`/${t}/messages/`,{params:s})}};export{o as l};
@@ -1 +1 @@
1
- import{_ as e}from"./index-I1VDlN4g.js";const r="parameters",l={getGlobalApplications(){return e.get(`/${r}/global/applications/`)},getGlobalApplication(t){return e.get(`/${r}/global/${t}/`)},getGlobalApplicationStructure(t){return e.get(`/${r}/global/structure/?app=${t}`)},saveGlobalApplication(t,p){return e.put(`/${r}/global/${t}/`,p)},getUserApplications(){return e.get(`/${r}/user/applications/`)},getUserApplication(t){return e.get(`/${r}/user/${t}/`)},getUserApplicationStructure(t){return e.get(`/${r}/user/structure/?app=${t}`)},saveUserApplication(t,p){return e.put(`/${r}/user/${t}/`,p)}};export{l as p};
1
+ import{C as e}from"./index-LhNzkzAh.js";const r="parameters",l={getGlobalApplications(){return e.get(`/${r}/global/applications/`)},getGlobalApplication(t){return e.get(`/${r}/global/${t}/`)},getGlobalApplicationStructure(t){return e.get(`/${r}/global/structure/?app=${t}`)},saveGlobalApplication(t,p){return e.put(`/${r}/global/${t}/`,p)},getUserApplications(){return e.get(`/${r}/user/applications/`)},getUserApplication(t){return e.get(`/${r}/user/${t}/`)},getUserApplicationStructure(t){return e.get(`/${r}/user/structure/?app=${t}`)},saveUserApplication(t,p){return e.put(`/${r}/user/${t}/`,p)}};export{l as p};
@@ -1 +1 @@
1
- import{O as a,g as t}from"./index-I1VDlN4g.js";const s=a("parameters",()=>{const e=t(null);async function r(){e.value=null}return{imapMigrationEnabled:e,$reset:r}});export{s as u};
1
+ import{E as a,g as t}from"./index-LhNzkzAh.js";const s=a("parameters",()=>{const e=t(null);async function r(){e.value=null}return{imapMigrationEnabled:e,$reset:r}});export{s as u};
@@ -0,0 +1 @@
1
+ import{u,h as n,i as e}from"./index-LhNzkzAh.js";function c(){const t=u(),s=n(()=>[e.RESELLER,e.SUPER_ADMIN].includes(t.authUser.role)),r=n(()=>[e.RESELLER,e.SUPER_ADMIN].includes(t.authUser.role)),o=n(()=>[e.DOMAIN_ADMIN,e.RESELLER,e.SUPER_ADMIN].includes(t.authUser.role));return{canSetRole:s,canAddDomain:r,canViewDomain:o}}export{c as u};
@@ -1 +1 @@
1
- import{ab as t,d as e,ac as s,b4 as n}from"./index-I1VDlN4g.js";function i(){const o=t(!1);return e(()=>{window.requestAnimationFrame(()=>{o.value=!0})}),{ssrBootStyles:s(()=>o.value?void 0:{transition:"none !important"}),isBooted:n(o)}}export{i as u};
1
+ import{a6 as t,d as e,a7 as s,aS as n}from"./index-LhNzkzAh.js";function i(){const o=t(!1);return e(()=>{window.requestAnimationFrame(()=>{o.value=!0})}),{ssrBootStyles:s(()=>o.value?void 0:{transition:"none !important"}),isBooted:n(o)}}export{i as u};
@@ -1 +1 @@
1
- import{x as m,aD as c,ag as h,g as d,ar as f,az as l,L as b,b4 as R,h as S,a7 as r}from"./index-I1VDlN4g.js";const x=m({class:[String,Array,Object],style:{type:[String,Array,Object],default:null}},"component");function y(t){const a=c("useRender");a.render=t}function W(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"content";const e=h(),i=d();if(f){const s=new ResizeObserver(n=>{t==null||t(n,s),n.length&&(a==="content"?i.value=n[0].contentRect:i.value=n[0].target.getBoundingClientRect())});l(()=>{s.disconnect()}),b(()=>e.el,(n,o)=>{o&&(s.unobserve(o),i.value=void 0),n&&s.observe(n)},{flush:"post"})}return{resizeRef:e,contentRect:R(i)}}const H=m({height:[Number,String],maxHeight:[Number,String],maxWidth:[Number,String],minHeight:[Number,String],minWidth:[Number,String],width:[Number,String]},"dimension");function N(t){return{dimensionStyles:S(()=>{const e={},i=r(t.height),s=r(t.maxHeight),n=r(t.maxWidth),o=r(t.minHeight),u=r(t.minWidth),g=r(t.width);return i!=null&&(e.height=i),s!=null&&(e.maxHeight=s),n!=null&&(e.maxWidth=n),o!=null&&(e.minHeight=o),u!=null&&(e.minWidth=u),g!=null&&(e.width=g),e})}}const O=m({tag:{type:[String,Object,Function],default:"div"}},"tag");export{x as a,N as b,H as c,W as d,O as m,y as u};
1
+ import{J as m,aR as c,ab as h,g as d,an as f,aw as l,z as b,aS as R,h as S,a2 as r}from"./index-LhNzkzAh.js";const x=m({class:[String,Array,Object],style:{type:[String,Array,Object],default:null}},"component");function y(t){const a=c("useRender");a.render=t}function W(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"content";const e=h(),i=d();if(f){const s=new ResizeObserver(n=>{t==null||t(n,s),n.length&&(a==="content"?i.value=n[0].contentRect:i.value=n[0].target.getBoundingClientRect())});l(()=>{s.disconnect()}),b(()=>e.el,(n,o)=>{o&&(s.unobserve(o),i.value=void 0),n&&s.observe(n)},{flush:"post"})}return{resizeRef:e,contentRect:R(i)}}const H=m({height:[Number,String],maxHeight:[Number,String],maxWidth:[Number,String],minHeight:[Number,String],minWidth:[Number,String],width:[Number,String]},"dimension");function N(t){return{dimensionStyles:S(()=>{const e={},i=r(t.height),s=r(t.maxHeight),n=r(t.maxWidth),o=r(t.minHeight),u=r(t.minWidth),g=r(t.width);return i!=null&&(e.height=i),s!=null&&(e.maxHeight=s),n!=null&&(e.maxWidth=n),o!=null&&(e.minHeight=o),u!=null&&(e.minWidth=u),g!=null&&(e.width=g),e})}}const w=m({tag:{type:[String,Object,Function],default:"div"}},"tag");export{N as a,x as b,w as c,W as d,H as m,y as u};
@@ -0,0 +1 @@
1
+ import{C as t}from"./index-LhNzkzAh.js";const r="transports",s={getAll(){return t.get(`/${r}/`)}};export{s as t};
@@ -1 +1 @@
1
- import{_ as t}from"./index-I1VDlN4g.js";const r={getUserMailboxes(e){const s={};return e&&(s.mailbox=e),t.get("/webmail/mailboxes/",{params:s})},getUserMailboxQuota(e){const s={mailbox:e};return t.get("/webmail/mailboxes/quota/",{params:s})},getUserMailboxUnseen(e){const s={mailbox:e};return t.get("webmail/mailboxes/unseen/",{params:s})},createUserMailbox(e){return t.post("/webmail/mailboxes/",e)},renameUserMailbox(e){return t.post("/webmail/mailboxes/rename/",e)},compressUserMailbox(e){return t.post("/webmail/mailboxes/compress/",e)},deleteUserMailbox(e){return t.post("/webmail/mailboxes/delete/",e)},emptyUserMailbox(e){const s={name:e};return t.post("/webmail/mailboxes/empty/",s)},getMailboxEmails(e,s){const a={mailbox:e,...s};return t.get("/webmail/emails/",{params:a})},getEmailContent(e,s,a){const o={mailbox:e,mailid:s,...a};return t.get("/webmail/emails/content/",{params:o})},getEmailSource(e,s){const a={mailbox:e,mailid:s};return t.get("/webmail/emails/source/",{params:a})},getEmailAttachment(e,s,a){const o={mailbox:e,mailid:s,partnum:a};return t.get("/webmail/emails/attachment/",{params:o,responseType:"blob"})},deleteSelection(e,s){const a={mailbox:e,selection:s};return t.post("/webmail/emails/delete/",a)},markSelectionAsJunk(e,s){const a={mailbox:e,selection:s};return t.post("/webmail/emails/mark_as_junk/",a)},markSelectionAsNotJunk(e,s){const a={mailbox:e,selection:s};return t.post("/webmail/emails/mark_as_not_junk/",a)},flagSelection(e,s,a){const o={mailbox:e,selection:s,status:a};return t.post("/webmail/emails/flag/",o)},sendEmailFromComposeSession(e,s){return t.post(`/webmail/compose-sessions/${e}/send/`,s)},getComposeSession(e){return t.get(`/webmail/compose-sessions/${e}/`)},createComposeSession(){return t.post("/webmail/compose-sessions/")},getAllowedSenders(){return t.get("/webmail/compose-sessions/allowed_senders/")},uploadAttachment(e,s){return t.post(`/webmail/compose-sessions/${e}/attachments/`,s,{headers:{"Content-Type":"multipart/form-data"}})},removeAttachment(e,s){return t.delete(`/webmail/compose-sessions/${e}/attachments/${s}/`)}};export{r as a};
1
+ import{C as t}from"./index-LhNzkzAh.js";const r={getUserMailboxes(e){const s={};return e&&(s.mailbox=e),t.get("/webmail/mailboxes/",{params:s})},getUserMailboxQuota(e){const s={mailbox:e};return t.get("/webmail/mailboxes/quota/",{params:s})},getUserMailboxUnseen(e){const s={mailbox:e};return t.get("webmail/mailboxes/unseen/",{params:s})},createUserMailbox(e){return t.post("/webmail/mailboxes/",e)},renameUserMailbox(e){return t.post("/webmail/mailboxes/rename/",e)},compressUserMailbox(e){return t.post("/webmail/mailboxes/compress/",e)},deleteUserMailbox(e){return t.post("/webmail/mailboxes/delete/",e)},emptyUserMailbox(e){const s={name:e};return t.post("/webmail/mailboxes/empty/",s)},getMailboxEmails(e,s){const a={mailbox:e,...s};return t.get("/webmail/emails/",{params:a})},getEmailContent(e,s,a){const o={mailbox:e,mailid:s,...a};return t.get("/webmail/emails/content/",{params:o})},getEmailSource(e,s){const a={mailbox:e,mailid:s};return t.get("/webmail/emails/source/",{params:a})},getEmailAttachment(e,s,a){const o={mailbox:e,mailid:s,partnum:a};return t.get("/webmail/emails/attachment/",{params:o,responseType:"blob"})},deleteSelection(e,s){const a={mailbox:e,selection:s};return t.post("/webmail/emails/delete/",a)},markSelectionAsJunk(e,s){const a={mailbox:e,selection:s};return t.post("/webmail/emails/mark_as_junk/",a)},markSelectionAsNotJunk(e,s){const a={mailbox:e,selection:s};return t.post("/webmail/emails/mark_as_not_junk/",a)},flagSelection(e,s,a){const o={mailbox:e,selection:s,status:a};return t.post("/webmail/emails/flag/",o)},sendEmailFromComposeSession(e,s){return t.post(`/webmail/compose-sessions/${e}/send/`,s)},getComposeSession(e){return t.get(`/webmail/compose-sessions/${e}/`)},createComposeSession(){return t.post("/webmail/compose-sessions/")},getAllowedSenders(){return t.get("/webmail/compose-sessions/allowed_senders/")},uploadAttachment(e,s){return t.post(`/webmail/compose-sessions/${e}/attachments/`,s,{headers:{"Content-Type":"multipart/form-data"}})},removeAttachment(e,s){return t.delete(`/webmail/compose-sessions/${e}/attachments/${s}/`)}};export{r as a};
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" href="/favicon.ico" />
13
13
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
14
14
  <title>Welcome to Modoboa</title>
15
- <script type="module" crossorigin src="/assets/index-I1VDlN4g.js"></script>
15
+ <script type="module" crossorigin src="/assets/index-LhNzkzAh.js"></script>
16
16
  <link rel="stylesheet" crossorigin href="/assets/index-B1bJH8Ti.css">
17
17
  </head>
18
18
 
@@ -96,7 +96,7 @@ class Email:
96
96
  if self._headers is None:
97
97
  self._headers = []
98
98
 
99
- # don't break modoboa_webmail.lib.imapemail.ImapEmail, it
99
+ # don't break modoboa.webmail.lib.imapemail.ImapEmail, it
100
100
  # doesn't have self._msg it loads e-mails (and their headers)
101
101
  # from the IMAP server.
102
102
  if self._msg is not None:
@@ -334,7 +334,7 @@ def split_mailbox(mailbox, return_extension=False):
334
334
  return (local_part, domain, extension)
335
335
 
336
336
 
337
- def decode(value_bytes, encoding, append_to_error=""):
337
+ def decode(value_bytes: bytes, encoding: str, append_to_error: str = "") -> str:
338
338
  """Try to decode the given string."""
339
339
  assert isinstance(value_bytes, bytes), "value_bytes should be of type bytes"
340
340
  if len(value_bytes) == 0:
@@ -166,3 +166,10 @@ class CanCreateDomain(permissions.BasePermission):
166
166
 
167
167
  def has_permission(self, request, view):
168
168
  return request.user.has_perm("admin.add_domain")
169
+
170
+
171
+ class CanViewDomain(permissions.BasePermission):
172
+ """Permissions class to allow users with view_domain right."""
173
+
174
+ def has_permission(self, request, view):
175
+ return request.user.has_perm("admin.view_domain")
@@ -0,0 +1,29 @@
1
+ """Custom test runner."""
2
+
3
+ from django.apps import apps
4
+ from django.test.runner import DiscoverRunner
5
+
6
+
7
+ class UnManagedModelTestRunner(DiscoverRunner):
8
+ """
9
+ Test runner that automatically makes all unmanaged models in your Django
10
+ project managed for the duration of the test run.
11
+ Many thanks to the Caktus Group: http://bit.ly/1N8TcHW
12
+ """
13
+
14
+ unmanaged_models = []
15
+
16
+ def setup_test_environment(self, *args, **kwargs):
17
+ """Mark amavis models as managed during testing
18
+ During database setup migrations are only run for managed models"""
19
+ for m in apps.get_models():
20
+ if m._meta.app_label == "amavis":
21
+ self.unmanaged_models.append(m)
22
+ m._meta.managed = True
23
+ super().setup_test_environment(*args, **kwargs)
24
+
25
+ def teardown_test_environment(self, *args, **kwargs):
26
+ """Revert modoboa_amavis models to unmanaged"""
27
+ super().teardown_test_environment(*args, **kwargs)
28
+ for m in self.unmanaged_models:
29
+ m._meta.managed = False
@@ -189,12 +189,14 @@ class ParametersMixin:
189
189
  class SimpleModoTestCase(ParametersMixin, TestCase):
190
190
  """Simple class to add parameters editing."""
191
191
 
192
- pass
192
+ databases = "__all__"
193
193
 
194
194
 
195
195
  class ModoTestCase(ParametersMixin, TestCase):
196
196
  """All test cases must inherit from this one."""
197
197
 
198
+ databases = "__all__"
199
+
198
200
  @classmethod
199
201
  def setUpTestData(cls): # noqa
200
202
  """Create a default user."""
@@ -232,6 +234,8 @@ class ModoTestCase(ParametersMixin, TestCase):
232
234
  class ModoAPITestCase(ParametersMixin, APITestCase):
233
235
  """All test cases must inherit from this one."""
234
236
 
237
+ databases = "__all__"
238
+
235
239
  @classmethod
236
240
  def setUpTestData(cls): # noqa
237
241
  """Create a default user."""
@@ -9,7 +9,7 @@ msgid ""
9
9
  msgstr ""
10
10
  "Project-Id-Version: Modoboa\n"
11
11
  "Report-Msgid-Bugs-To: \n"
12
- "POT-Creation-Date: 2025-07-27 10:50+0200\n"
12
+ "POT-Creation-Date: 2025-08-28 09:41+0200\n"
13
13
  "PO-Revision-Date: 2020-05-06 11:16+0000\n"
14
14
  "Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
15
15
  "Language-Team: Breton (http://www.transifex.com/tonio/modoboa/language/br/)\n"
@@ -37,68 +37,69 @@ msgstr ""
37
37
  "Kota dre-ziouer e Mo arloet d'ar boestoù-postel. Un dalvoudegezh \"0\" a "
38
38
  "dalvez kota ebet."
39
39
 
40
- #: admin/api/v1/serializers.py:88
40
+ #: admin/api/v1/serializers.py:94
41
41
  #, fuzzy
42
42
  msgid "domain alias with this name already exists"
43
43
  msgstr "Un alias gant an anv-mañ zo anezhañ dija"
44
44
 
45
- #: admin/api/v1/serializers.py:98
45
+ #: admin/api/v1/serializers.py:104
46
46
  msgid "No authorized MX record found for this domain"
47
47
  msgstr "Enrolladenn MX aotreet ebet kavet evit an domani-mañ"
48
48
 
49
- #: admin/api/v1/serializers.py:116
49
+ #: admin/api/v1/serializers.py:122
50
50
  msgid "Cannot be greater than domain quota"
51
51
  msgstr "N'hall ket bezañ brasoc'h evit kota an domani"
52
52
 
53
- #: admin/api/v1/serializers.py:162 admin/api/v1/serializers.py:357
54
- #: admin/api/v2/serializers.py:548 admin/models/alias.py:44
53
+ #: admin/api/v1/serializers.py:168 admin/api/v1/serializers.py:364
54
+ #: admin/api/v2/serializers.py:564 admin/models/alias.py:44
55
55
  msgid "Permission denied."
56
56
  msgstr "Aotreadur nac'het"
57
57
 
58
- #: admin/api/v1/serializers.py:224 admin/api/v2/serializers.py:88
59
- #: admin/api/v2/serializers.py:470 core/api/v2/serializers.py:235
60
- #: core/api/v2/serializers.py:237 core/api/v2/serializers.py:246
58
+ #: admin/api/v1/serializers.py:231 admin/api/v2/serializers.py:90
59
+ #: admin/api/v2/serializers.py:486 core/api/v2/serializers.py:255
60
+ #: core/api/v2/serializers.py:257 core/api/v2/serializers.py:266
61
61
  #: transport/backends.py:40
62
62
  msgid "This field is required"
63
63
  msgstr "Rekis eo leuniañ ar vaezienn"
64
64
 
65
- #: admin/api/v1/serializers.py:236
65
+ #: admin/api/v1/serializers.py:243
66
66
  msgid ""
67
67
  "List of administered domains (resellers and domain administrators only)."
68
68
  msgstr "Listenn domanioù meret (eilgwerzherien ha merourien zomani hepken)."
69
69
 
70
- #: admin/api/v1/serializers.py:330 admin/api/v2/serializers.py:530
70
+ #: admin/api/v1/serializers.py:337 admin/api/v2/serializers.py:546
71
71
  msgid "Not allowed for this role."
72
72
  msgstr "Neket aotreet evit ar rol-mañ."
73
73
 
74
- #: admin/api/v1/serializers.py:348
74
+ #: admin/api/v1/serializers.py:355
75
75
  msgid "Must be equal to mailbox full_address"
76
76
  msgstr "Rankout a ra bezañ par ouzh boest-postell chomlec'h_klok"
77
77
 
78
- #: admin/api/v1/serializers.py:390 admin/api/v2/serializers.py:582
78
+ #: admin/api/v1/serializers.py:397 admin/api/v2/serializers.py:598
79
79
  #: calendars/serializers.py:175 calendars/serializers.py:177
80
+ #: pdfcredentials/api/v2/serializers.py:91
80
81
  msgid "This field is required."
81
82
  msgstr "Ar vaezienn-mañ a zo rekiset."
82
83
 
83
- #: admin/api/v1/serializers.py:402 admin/api/v2/serializers.py:599
84
+ #: admin/api/v1/serializers.py:409 admin/api/v2/serializers.py:615
84
85
  msgid "Local domain {} does not exist"
85
86
  msgstr "N'eus ket eus an domani lec'hel {}"
86
87
 
87
- #: admin/api/v1/serializers.py:492
88
+ #: admin/api/v1/serializers.py:499
88
89
  msgid "A list of recipient"
89
90
  msgstr "Ul listenn resevourien"
90
91
 
91
- #: admin/api/v1/serializers.py:508 admin/api/v2/viewsets.py:286
92
+ #: admin/api/v1/serializers.py:515 admin/api/v2/viewsets.py:286
92
93
  #, fuzzy
93
94
  #| msgid "User '%s' already exists"
94
95
  msgid "This alias already exists"
95
96
  msgstr "An implijer \"%s\" a zo anezhañ endeo"
96
97
 
97
- #: admin/api/v1/serializers.py:544
98
+ #: admin/api/v1/serializers.py:551
98
99
  msgid "You don't have access to this domain."
99
100
  msgstr "N'ho peus moned ebet d'an domani-mañ."
100
101
 
101
- #: admin/api/v1/serializers.py:553
102
+ #: admin/api/v1/serializers.py:560
102
103
  msgid "You don't have access to this mailbox."
103
104
  msgstr "N'ho peus moned ebet d'ar voest-posteloù-mañ."
104
105
 
@@ -106,58 +107,58 @@ msgstr "N'ho peus moned ebet d'ar voest-posteloù-mañ."
106
107
  msgid "Here is your new Modoboa password: {}"
107
108
  msgstr ""
108
109
 
109
- #: admin/api/v2/serializers.py:80
110
+ #: admin/api/v2/serializers.py:82
110
111
  msgid "DKIM keys storage directory not configured"
111
112
  msgstr "Kavlec'h stokiñ an alc'hwezioù DKIM chomet digefluniet"
112
113
 
113
- #: admin/api/v2/serializers.py:92
114
+ #: admin/api/v2/serializers.py:94
114
115
  msgid "This field is valid when type is relaydomain"
115
116
  msgstr ""
116
117
 
117
- #: admin/api/v2/serializers.py:99
118
+ #: admin/api/v2/serializers.py:101
118
119
  msgid "You can't define an unlimited quota."
119
120
  msgstr "N'hallit ket termeniñ ur c'hota divevenn"
120
121
 
121
- #: admin/api/v2/serializers.py:133
122
+ #: admin/api/v2/serializers.py:135
122
123
  #, python-format
123
124
  msgid "User '%s' already exists"
124
125
  msgstr "An implijer \"%s\" a zo anezhañ endeo"
125
126
 
126
- #: admin/api/v2/serializers.py:248 admin/api/v2/serializers.py:254
127
+ #: admin/api/v2/serializers.py:250 admin/api/v2/serializers.py:256
127
128
  msgid "Must be a positive integer"
128
129
  msgstr "Rankout a ra bezañ un anterin pozitivel"
129
130
 
130
- #: admin/api/v2/serializers.py:263
131
+ #: admin/api/v2/serializers.py:265
131
132
  msgid "openssl not found, please make sure it is installed."
132
133
  msgstr "n'heller ket kavout openssl, bezit asur emañ staliet."
133
134
 
134
- #: admin/api/v2/serializers.py:266 pdfcredentials/api/v2/serializers.py:79
135
+ #: admin/api/v2/serializers.py:268 pdfcredentials/api/v2/serializers.py:84
135
136
  msgid "Directory not found."
136
137
  msgstr "Neket bet kavet an domani."
137
138
 
138
- #: admin/api/v2/serializers.py:277
139
+ #: admin/api/v2/serializers.py:279
139
140
  msgid "This field only allows valid IP addresses (or networks)"
140
141
  msgstr ""
141
142
 
142
- #: admin/api/v2/serializers.py:290
143
+ #: admin/api/v2/serializers.py:292
143
144
  msgid "Please disable imap migration before disabling this option."
144
145
  msgstr ""
145
146
 
146
- #: admin/api/v2/serializers.py:303
147
+ #: admin/api/v2/serializers.py:305
147
148
  msgid "Define at least one authorized network / address"
148
149
  msgstr "Termeniñ da vihanañ ur rouedad / chomlec'h aotreet"
149
150
 
150
- #: admin/api/v2/serializers.py:565
151
+ #: admin/api/v2/serializers.py:581
151
152
  msgid "The left part of an email address can't be more than 64 characters."
152
153
  msgstr ""
153
154
 
154
- #: admin/api/v2/serializers.py:587
155
+ #: admin/api/v2/serializers.py:603
155
156
  #, fuzzy
156
157
  #| msgid "A mailbox is required"
157
158
  msgid "A mailbox is required to create aliases."
158
159
  msgstr "Ur voest-posteloù a zo rekiset"
159
160
 
160
- #: admin/api/v2/serializers.py:751
161
+ #: admin/api/v2/serializers.py:772
161
162
  #, fuzzy
162
163
  #| msgid "Unknown"
163
164
  msgid "Unknown status"
@@ -171,14 +172,6 @@ msgstr "N'ho peus moned ebet d'an domani-mañ"
171
172
  msgid "You can't delete your own domain"
172
173
  msgstr "N'hallit ket dilemel ho tomani deoc'h-c'hwi hoc'h-unan"
173
174
 
174
- #: admin/api/v2/viewsets.py:407
175
- msgid "No alarm ID provided"
176
- msgstr ""
177
-
178
- #: admin/api/v2/viewsets.py:411
179
- msgid "Received invalid alarm id(s)"
180
- msgstr ""
181
-
182
175
  #: admin/app_settings.py:19 limits/app_settings.py:38 limits/constants.py:13
183
176
  msgid "Domains"
184
177
  msgstr "Domanioù"
@@ -407,7 +400,7 @@ msgstr ""
407
400
  "Krouiñ un alias en ur implijout ar chomlec'h pa vez adanvet ar voest-"
408
401
  "posteloù."
409
402
 
410
- #: admin/app_settings.py:287 core/api/v2/viewsets.py:162
403
+ #: admin/app_settings.py:287 core/api/v2/viewsets.py:174
411
404
  msgid "Administration"
412
405
  msgstr "Melestradurezh"
413
406
 
@@ -438,7 +431,7 @@ msgstr "alias an domani"
438
431
  msgid "Account import failed (%s): domain does not exist"
439
432
  msgstr "Enporzhiadur kont c'hwitet (%s): n'eus ket eus an domani"
440
433
 
441
- #: admin/handlers.py:242 admin/models/mailbox.py:340
434
+ #: admin/handlers.py:242 admin/models/mailbox.py:342
442
435
  msgid "Mailbox {} already exists"
443
436
  msgstr "Boest-postel {} a zo anezhi endeo"
444
437
 
@@ -723,7 +716,7 @@ msgstr "Ur c'hota a zo rekiset"
723
716
  msgid "{}: domain quota exceeded"
724
717
  msgstr "Kota an domani dibaseet"
725
718
 
726
- #: admin/models/mailbox.py:308
719
+ #: admin/models/mailbox.py:310
727
720
  msgid "Domain does not exist"
728
721
  msgstr "N'eus ket eus an Domani"
729
722
 
@@ -900,7 +893,7 @@ msgid ""
900
893
  "Maximum size in bytes of imported ICS files (or KB, MB, GB if specified)"
901
894
  msgstr ""
902
895
 
903
- #: calendars/app_settings.py:89 core/api/v2/viewsets.py:172
896
+ #: calendars/app_settings.py:89 core/api/v2/viewsets.py:195
904
897
  msgid "Calendars"
905
898
  msgstr ""
906
899
 
@@ -936,7 +929,7 @@ msgstr "Frekañs sinkroneladur"
936
929
  msgid "Interval in seconds between 2 synchronization requests"
937
930
  msgstr "Padelezh en eilennoù etre 2 reked sinkroneladur"
938
931
 
939
- #: contacts/app_settings.py:51 core/api/v2/viewsets.py:179
932
+ #: contacts/app_settings.py:51 core/api/v2/viewsets.py:185
940
933
  #, fuzzy
941
934
  #| msgid "Domains"
942
935
  msgid "Contacts"
@@ -990,12 +983,12 @@ msgstr "Enrolladennoù MX eus {}"
990
983
  msgid "2FA is already enabled"
991
984
  msgstr ""
992
985
 
993
- #: core/api/v1/serializers.py:87
986
+ #: core/api/v1/serializers.py:86
994
987
  #, python-format
995
- msgid "Failed TFA settings editing attempt from '%s' as user '%s'"
988
+ msgid "Failed TFA settings editing attempt from '%(addr)s' as user '%(user)s'"
996
989
  msgstr ""
997
990
 
998
- #: core/api/v1/serializers.py:91 core/api/v2/serializers.py:425
991
+ #: core/api/v1/serializers.py:91 core/api/v2/serializers.py:445
999
992
  #, fuzzy
1000
993
  #| msgid "Old password"
1001
994
  msgid "Invalid password"
@@ -1009,44 +1002,44 @@ msgstr ""
1009
1002
  msgid "Local"
1010
1003
  msgstr "Lec'hel"
1011
1004
 
1012
- #: core/api/v2/serializers.py:175 core/app_settings.py:17
1005
+ #: core/api/v2/serializers.py:194 core/app_settings.py:17
1013
1006
  msgid "User profile"
1014
1007
  msgstr "Profil implijer"
1015
1008
 
1016
- #: core/api/v2/serializers.py:194 core/api/v2/serializers.py:201
1017
- #: core/api/v2/serializers.py:208
1009
+ #: core/api/v2/serializers.py:213 core/api/v2/serializers.py:221
1010
+ #: core/api/v2/serializers.py:228
1018
1011
  msgid "Invalid syntax"
1019
1012
  msgstr "Sintaks direizh"
1020
1013
 
1021
- #: core/api/v2/serializers.py:213
1014
+ #: core/api/v2/serializers.py:233
1022
1015
  msgid "Invalid rounds number"
1023
1016
  msgstr "Niveroù ront direizh"
1024
1017
 
1025
- #: core/api/v2/serializers.py:413 core/forms.py:81
1018
+ #: core/api/v2/serializers.py:433 core/forms.py:81
1026
1019
  msgid "This code is invalid"
1027
1020
  msgstr ""
1028
1021
 
1029
- #: core/api/v2/serializers.py:483 core/views/auth.py:194 core/views/auth.py:247
1022
+ #: core/api/v2/serializers.py:503 core/views/auth.py:194 core/views/auth.py:247
1030
1023
  msgid "Please use the following code to recover your Modoboa password: {}"
1031
1024
  msgstr ""
1032
1025
 
1033
- #: core/api/v2/viewsets.py:164
1026
+ #: core/api/v2/viewsets.py:176
1034
1027
  #, fuzzy
1035
1028
  #| msgid "Administration"
1036
1029
  msgid "Administration console"
1037
1030
  msgstr "Melestradurezh"
1038
1031
 
1039
- #: core/api/v2/viewsets.py:174
1040
- msgid "Calendar"
1041
- msgstr ""
1042
-
1043
- #: core/api/v2/viewsets.py:181
1032
+ #: core/api/v2/viewsets.py:187
1044
1033
  #, fuzzy
1045
1034
  #| msgid "Address"
1046
1035
  msgid "Address book"
1047
1036
  msgstr "Levr chomlec'hioù"
1048
1037
 
1049
- #: core/api/v2/viewsets.py:186 core/api/v2/viewsets.py:188
1038
+ #: core/api/v2/viewsets.py:197
1039
+ msgid "Calendar"
1040
+ msgstr ""
1041
+
1042
+ #: core/api/v2/viewsets.py:205 core/api/v2/viewsets.py:207
1050
1043
  #: webmail/app_settings.py:258 webmail/app_settings.py:265
1051
1044
  #, fuzzy
1052
1045
  #| msgid "E-mail"
@@ -1579,19 +1572,27 @@ msgstr "Oad enrollañ maksimom ar marilhoù"
1579
1572
  msgid "The maximum age in days of a log record"
1580
1573
  msgstr "Oad brasañ e devezhioù un enrollodenn renabl"
1581
1574
 
1582
- #: core/app_settings.py:726
1575
+ #: core/app_settings.py:727
1576
+ msgid "Retention time in message history"
1577
+ msgstr ""
1578
+
1579
+ #: core/app_settings.py:730
1580
+ msgid "Retention time (in days) of a message in the message history section"
1581
+ msgstr ""
1582
+
1583
+ #: core/app_settings.py:737
1583
1584
  msgid "Items per page"
1584
1585
  msgstr "Elfennoù dre bajenn"
1585
1586
 
1586
- #: core/app_settings.py:728
1587
+ #: core/app_settings.py:739
1587
1588
  msgid "Number of displayed items per page"
1588
1589
  msgstr "Niver a elfennoù diskouezet dre bajenn"
1589
1590
 
1590
- #: core/app_settings.py:735
1591
+ #: core/app_settings.py:746
1591
1592
  msgid "Default top redirection"
1592
1593
  msgstr "Adhenchañ pennañ dre-ziouer"
1593
1594
 
1594
- #: core/app_settings.py:737
1595
+ #: core/app_settings.py:748
1595
1596
  msgid "The default redirection used when no application is specified"
1596
1597
  msgstr "An adheñchañ dre-ziouer implijet pa n'eus arload ebet spisaet"
1597
1598
 
@@ -1625,8 +1626,8 @@ msgstr ""
1625
1626
 
1626
1627
  #: core/checks.py:34
1627
1628
  msgid ""
1628
- "Visit : https://modoboa.readthedocs.io/en/latest/manual_installation/dovecot."
1629
- "html#dovecot-oauth2"
1629
+ "Visit : https://modoboa.readthedocs.io/en/latest/manual_installation/"
1630
+ "dovecot.html#dovecot-oauth2"
1630
1631
  msgstr ""
1631
1632
 
1632
1633
  #: core/checks.py:41
@@ -2141,19 +2142,14 @@ msgstr ""
2141
2142
  #: imap_migration/app_settings.py:76
2142
2143
  msgid ""
2143
2144
  "A comma seperated list of folders to explicitly include in sync even if "
2144
- "filtered by the Folder Filter Exclusions. Example: debian.user, debian."
2145
- "personal "
2145
+ "filtered by the Folder Filter Exclusions. Example: debian.user, "
2146
+ "debian.personal "
2146
2147
  msgstr ""
2147
2148
 
2148
2149
  #: imap_migration/apps.py:20
2149
2150
  msgid "IMAP Migration"
2150
2151
  msgstr ""
2151
2152
 
2152
- #: imap_migration/auth_backends.py:49 webmail/lib/imaputils.py:240
2153
- #, python-brace-format
2154
- msgid "Connection to IMAP server failed: {error}"
2155
- msgstr ""
2156
-
2157
2153
  #: imap_migration/checks.py:12
2158
2154
  msgid ""
2159
2155
  "Automatic domain/mailbox creation is disabled which means IMAP "
@@ -2515,13 +2511,13 @@ msgstr "Kont"
2515
2511
  msgid "Personal account information"
2516
2512
  msgstr "Hizivaat ho titouroù personel"
2517
2513
 
2518
- #: pdfcredentials/api/v2/serializers.py:81
2514
+ #: pdfcredentials/api/v2/serializers.py:86
2519
2515
  #, fuzzy
2520
2516
  #| msgid "Directory not found."
2521
2517
  msgid "Directory is not writable"
2522
2518
  msgstr "Neket bet kavet an domani."
2523
2519
 
2524
- #: pdfcredentials/api/v2/serializers.py:102
2520
+ #: pdfcredentials/api/v2/serializers.py:114
2525
2521
  #, fuzzy
2526
2522
  #| msgid "No information available for this domain."
2527
2523
  msgid "No document available for this user"
@@ -3336,15 +3332,31 @@ msgstr ""
3336
3332
  msgid "User defined email signature"
3337
3333
  msgstr ""
3338
3334
 
3335
+ #: webmail/exceptions.py:18
3336
+ #, fuzzy
3337
+ #| msgid "Server address"
3338
+ msgid "Server response"
3339
+ msgstr "Chomlec'h ar servijer"
3340
+
3339
3341
  #: webmail/lib/attachments.py:112
3340
3342
  #, fuzzy
3341
3343
  msgid "Failed to remove attachment: "
3342
3344
  msgstr "N'heller ket adsevel lec'hiadur ar voest-posteloù (%s)"
3343
3345
 
3346
+ #: webmail/lib/imapemail.py:272
3347
+ msgid "wrote:"
3348
+ msgstr ""
3349
+
3344
3350
  #: webmail/lib/imapemail.py:306
3345
3351
  msgid "Date"
3346
3352
  msgstr "Deiziad"
3347
3353
 
3354
+ #: webmail/lib/imapemail.py:322 webmail/lib/imapemail.py:325
3355
+ #, fuzzy
3356
+ #| msgid "Message"
3357
+ msgid "Original message"
3358
+ msgstr "Kemennadenn"
3359
+
3348
3360
  #: webmail/lib/imaputils.py:221
3349
3361
  msgid "Failed to retrieve hierarchy delimiter"
3350
3362
  msgstr ""