Commit Graph
149 Commits
Author SHA1 Message Date
Stanislas BruhièreandGitHub 02bce211ea ✨(frontend) add a button and modal to create maildomains (#313)
* ✨(feat) create modal, serializer and add button

* ✨(frontend) refetch on domain creation

* 🚨(frontend) fix linter

* ✅(backend) add domain creation test

* ✨(frontend) add toaster for domain creation

* 💬(frontend) add translation and fix small typo

* ✨(front+back) add custom_attributes on domain creation

* 💄(frontend) add style for create domain modal

* 💬(frontend) add missing translations + add end of file line breaks

* 🎨(frontend) move toaster to admin layout

* 🦺(frontend) validate domain name in frontend

* 💄(frontend) remove unused css

* ✅(backend) add more tests

* 🎨(backend) improve maildomain structure

* 🎨(frontend) follow nitpicks
2025-09-02 20:13:11 +02:00
Sylvain Zimmer 1e2f30e046 🐛(admin) use autocomplete fields instead of full dropdowns
This makes the admin usable with thousands of records in the DB
2025-08-28 00:14:29 +02:00
Sabrina Demagny 67a7c4e9c0 ✨(api) add placeholders endpoint
This endpoint will be used for Signature and other message templates.
Update Dockerfile to include gettext for i18n compilation
2025-08-20 12:10:16 +02:00
Fabian ArfireandJean-Baptiste PENRATH cdb4e207e5 ✨(backend) add auto labelling ai feature
When a message is received, if the auto labelling feature is enabled,
we try to add all relevant labels that are flagged for auto labelling to this
message.

Co-authored-by: jbpenrath <jb.penrath@gmail.com>
2025-08-19 23:48:03 +02:00
jbpenrath 2a3f8b748b 🚸(front) improve labels UX
Allow to drag'n'drop labels to reorder them.
Add an option to create a new label in the thread labels widget.
2025-08-14 17:22:37 +02:00
jbpenrath cf66702adc ✨(front) paginate maildomain and mailboxes views
Add pagination on maildomain and mailboxes data grid to allow navigation
in large list of items
2025-08-12 14:04:38 +02:00
jbpenrath 53110862d6 ✨(front) manage abilities
Improve openapi schema to pass abilities to frontend properly.
Then through the useAbility hook, hide/disable actions.
It concerns actions to send messages, write messages, share
thread access, crud labels, crud maildomain mailboxes.
2025-08-07 10:39:23 +02:00
jbpenrath d0b2a66f08 🐛(frontend) draftBody can be null
There was an error in the openapi schema and we are not aware that
message.draftBody could be null so when it was the case, the frontend
throws an error when rendering the `MessageForm` component.
2025-08-06 10:12:36 +02:00
jbpenrath 4a311e5b3c ✨(backend) define custom_attributes through env vars json schema string
User and MailDomain have both `custom_attributes` json field. Those fields
aims to store extra data about those models specific to an instance. In order
to fulfill those fields with consistency and without requiring to fork the
project, we add two new settings `SCHEMA_CUSTOM_ATTRIBUTES_*`.
Those 2 settings expects a JSON Schema string defined through env vars.
Then on model save, those schema are used to validate data saved into
custom attributes.
2025-08-06 10:12:36 +02:00
Sylvain ZimmerandGitHub 5b9de7c4eb ♻️(services) refactor Services into a single directory (#304)
* 🐛(scalingo) add an env var to disable Celery beat scheduling

Deployments on fresh PaaS databases would fail because of this, without
giving the user the ability to create the database through a manual
run command.

* 🐛(nginx) fix error when no env vars configured

* ♻️(services) refactor Services into a single directory

I haven't done AI yet because there are pending patches but once done we'll also have core/services/ai/*.py
I used importer as a name to avoid using a Python keyword

* 🚨(lint) move imports to the top
2025-08-05 14:45:18 +02:00
jbpenrath 7c07711489 👽️(openapi) improve user definition with or without abilities
The OpenAPI Schema does not embedded abilities property.
We fix that and make two serializers for User model in order to get proper
openapi definition for User instance with abilities and without abilities.
2025-07-31 17:19:23 +02:00
jbpenrath a56ca6b113 ✨(backend) add settings to configure drive external service
We want to add ability to Messages to interop with our Drive application.
First, we want to be able to set the Drive base url through environment
variable then pass down Drive configuration to frontend through the config
api endpoint.

https://github.com/suitenumerique/drive
2025-07-30 13:57:04 +02:00
Sabrina Demagny c7fb77b737 ✨(frontend) remove max_messages and folder fields on imap import
Run 'make api-update'
2025-07-28 11:18:28 +02:00
Sabrina Demagny 6d6bbea0d9 ✨(imap) improve IMAP import code, load folders for GMAIL and ORANGE
- Load folders for GMAIL and ORANGE
- Fix read issue with Gmail IMAP import (all messages were marked as read)
- Fix IMAP encoding for Gmail import
- Refactor monolithic import_imap_messages_task into smaller, focused functions
- Add IMAPConnectionManager context manager for better resource management
- Extract helper functions with single responsibilities

This refactoring improves code maintainability, readability, and testability
while maintaining backward compatibility with existing API.
2025-07-28 11:18:28 +02:00
Sabrina Demagny 03cd72f0fb 🐛(labels) support identical label slugs across different mailboxes
- Replace single label lookup with multiple labels filter in ThreadViewSet
- Allow filtering threads by label_slug across multiple mailboxes when user has access
- Expect empty results instead of 403 errors for inaccessible labels
- Add comprehensive tests for identical labels in different mailboxes scenarios

This change enables users with access to multiple mailboxes to filter threads
by label slug across all accessible mailboxes, while maintaining proper
permission checks and supporting mailbox-specific filtering.
2025-07-24 12:47:27 +02:00
Mathis ROUGETandJean-Baptiste PENRATH e32862e4b3 ✨(ai) add thread summary 2025-07-24 11:45:07 +02:00
Mathis ROUGETandJean-Baptiste PENRATH e08acda852 ✨(ai) setup ai service 2025-07-24 11:45:07 +02:00
Sabrina Demagny 65af318fb5 ✨(backend) add get_abilities for Mailbox
- Add pre-calculation of user access roles in MailboxViewSet list/retrieve methods
- Implement get_abilities method on Mailbox model for permission checking
- Add AbilitiesModelSerializer to MailboxSerializer for consistent abilities field
- Optimize database queries by reducing N+1 access lookups
- Add comprehensive test coverage for abilities and optimized queries

This optimization significantly reduces database queries when listing
mailboxes by pre-calculating user roles instead of querying for each
mailbox individually.
2025-07-22 09:34:09 +02:00
Sylvain ZimmerandGitHub 9b4ba9ba09 ✨(dns) add admin page for DNS records (#283)
* ✨(dns) add admin page for DNS records. Fixes #177

* 👷(dockerflow) add a flag to disable Dockerflow

* 💚(ghactions) fix check-api-update that was missing Orval

* 💚(ci) fix tests that depended on Keycloak

* ♻️(admin) refactor CopyableInput into a separate component

* 🎨(dns) improve code style
2025-07-21 14:41:08 +02:00
Sylvain ZimmerandGitHub cc858e75e4 ✨(admin) improve Admin mailbox management page (#284)
This fixes a few small anoyances and adds a new field Mailbox.is_identity
to the models so that we can save what type of mailbox the admin created.
2025-07-21 10:47:06 +02:00
Sylvain ZimmerandSabrina Demagny 4545f4ff48 ✨(roles) implement MailboxAccessRole.SENDER 2025-07-18 14:11:29 +02:00
Sylvain Zimmer cfb417d80b 🐛(admin) add the ability to add mailbox accesses by email
This fixes the admin panel where users searched among the same
maildomain could correctly be added by their uuid, but when entering
an arbitrary email, the email and not the uuid gets sent in the POST
mailbox access. This might get replaced later when we have a proper
invitation system for external emails.
2025-07-18 00:00:00 +02:00
Sabrina Demagny 73d0f7476d 🐛(labels) implement cascading label rename with hierarchical tree fix
- Add cascading rename functionality to Label model save method
- Update all child labels when parent label is renamed
- Clean up orphaned parent labels that are no longer referenced
- Fix hierarchical tree construction in LabelViewSet list method
- Handle orphaned child labels by treating them as root labels
- Add comprehensive test for parent label rename scenarios

This ensures that when a parent label is renamed, all its children
are automatically updated to maintain the hierarchy, and the API
correctly displays all labels even when some parents are missing.
Fix #278
2025-07-17 17:17:49 +02:00
jbpenrath 0c79a169aa 🔊(front) setup posthog
Setup posthog and create a feedback button that is displayed
if a posthog survey id is provided through envvars
2025-07-16 22:22:25 +02:00
jbpenrath 7bd5a42e38 🏷️(openapi) types properly the ConfigViewset
Decorate ConfigViewset to be typed properly then regenerate
openapi schema and client.
2025-07-16 22:22:25 +02:00
jbpenrath 97c55bd7f0 🏷️(global) fix openapi schema and typescript types
Enhance the `IntegerChoicesField` to be well interpreted by drf
spectacular to generate a clean OpenAPI Schema then fix Typescript
issues once the api types have been fixed.
2025-07-16 15:04:26 +02:00
Sabrina Demagny ffa361f5f9 🐛(draft) handle MessageRecipient constraint error in draft API
Prevents 400 Bad Request error when there are simultaneous updating draft
Fixes the constraint error "Un objet Message recipient avec ces champs Message, Contact et Type existe déjà".
2025-07-16 01:34:55 +02:00
Sylvain Zimmer f29ba226e6 🐛(drafts) fix concurrent updates of drafts with blob delete 2025-07-15 23:13:07 +02:00
Sylvain ZimmerandGitHub f1a89a5bdb ✨(all) refactor several areas before 0.1 release (#265)
We are going to release a 0.1 version soon, along with our first production deployment. Starting from there, migrations and a consistent developer experience will be officially supported. To make that easier, this large patch cleans up several areas:
 * Reset migrations one last time
 * Update models for storage efficiency (move textchoices to integerchoices on high-volume tables)
 * Use Blobs for mail mime data and draft bodies. Having them in a separate PG table is a first step, we will later start offloading them to object storage.
 * Add default ZSTD compression to blobs
 * Add per-domain DKIM Keys
 * Add DNS check and provisioning, with a first Scaleway provider
 * Fix Keycloak user provisioning
 * Fix Attachment storage, they are now stored individually only at the drafting stage. Afterwards they are extracted from the main blob. This may be optimized later but at least we only store once. For JMAP compatibility, this requires using fake IDs in the blob API route.
 * Add a management command and recurring task to retry unsent messages
 * Improve the local developer experience with new ports and make commands
 * Repackage MTA-in and MTA-out to be closer to Backend: Poetry, multi-step Dockerfile, move compose and makefile to the root
 * Migrate to OpenSearch
 * Improve overall documentation and add a self-hosting page

Contributes to #177 and #185
2025-07-15 10:41:55 +02:00
Sabrina Demagny e1940295dc ✨(api) add dynamic abilities field to MailDomain API
- Add get_abilities() method to MailDomain model for permission-based abilities
- Update MailDomainAdminSerializer to inherit from AbilitiesModelSerializer
- Add RetrieveModelMixin to MailDomainAdminViewSet for detail endpoints
- Optimize queries with JOIN and annotation for regular users
- Add prefetch_related for superusers to avoid N+1 queries
- Add comprehensive tests for abilities functionality and query optimization
- Add new test file for MailDomain model abilities

The abilities field dynamically controls user permissions based on their role
in the mail domain, with optimized database queries to maintain performance.
2025-07-11 12:36:20 +02:00
jbpenrath 3c8bb9f6a3 👽️(api) update openapi schema and api client
Run `make api-update`
2025-07-10 18:05:00 +02:00
jbpenrathandSylvain Zimmer 0c44e7803a ✨(backend) complete admin maildomain api
- Create user (if needed) and mailbox access on mailbox creation
- If identify provider is keycloak, generate a one time password
at mailbox creation
- At nested endpoint to search users related to a maildomain

Co-authored-by: Sylvain Zimmer <sylvain@sylvainzimmer.com>
2025-07-10 18:05:00 +02:00
Sabrina Demagny b1daf05da6 ✨(api) add AbilitiesModelSerializer with exclude_abilities option
- Create AbilitiesModelSerializer base class that dynamically controls abilities field inclusion
- Refactor UserSerializer to inherit from AbilitiesModelSerializer
- Add exclude_abilities parameter to prevent abilities serialization in nested contexts
- Update MailboxAccessReadSerializer and MailboxAccessNestedUserSerializer to exclude abilities when nested
- Remove abilities from UserSerializer Meta fields as it's now handled dynamically
2025-07-10 17:18:55 +02:00
Sabrina Demagny f3b5cccf5d ✨(api) Allow superuser+staff to view all mail domains in admin API
- Add condition in MailDomainAdminViewSet.get_queryset() to return all domains
  when user is both superuser and staff
- Add comprehensive tests covering all user permission combinations:
  * superuser + staff: can see all domains
  * superuser only: cannot see all domains (empty list)
  * staff only: cannot see all domains (empty list)
  * staff with domain access: can only see accessible domains
- Maintain existing behavior for regular users and domain admins

This change ensures that superusers with staff privileges have full
administrative access to all mail domains through the admin API,
while maintaining proper access control for other user types.
2025-07-10 15:45:44 +02:00
Sabrina Demagny d3df815d1f ✨(backend) add user abilities system for mail domain permissions
- Add get_abilities() method to User model to determine user permissions
- Add abilities field to UserSerializer to expose permissions via API
- Implement permission logic for create_maildomains and view_maildomains
- Add comprehensive tests for User model abilities method
- Add integration tests for abilities field in users/me endpoint
- Support superuser+staff, mail domain access, and regular user scenarios

The abilities system provides granular permission control for mail domain
operations, allowing the frontend to adapt UI based on user capabilities.
2025-07-10 14:34:49 +02:00
Sabrina Demagny 260b27f6e0 ✨(api) add multi-word search on contact name and email
- Add ability to search contacts by multiple keywords (AND logic)
  on name and email, in contacts endpoint.
- Adapt and enrich tests to cover multi-word search,
  case sensitivity, and name/email combination.
2025-07-08 12:23:17 +02:00
Sabrina Demagny 604f7121a2 🐛(api) correct alphabetical sorting of labels with accented characters
- Change label sorting from name-based to slug-based ordering in list view
- Use slug ordering for initial queryset to ensure consistent sorting
- Maintain name-based sorting in create method for consistency
- Fixes issue where "État civil et cimetière" appeared at the end

The slug-based sorting provides more predictable alphabetical ordering
since slugs are normalized versions of names without accents.
2025-06-24 17:31:57 +02:00
Sabrina Demagny 1688ef70f7 💚(lint) run make lint 2025-06-23 11:44:23 +02:00
jbpenrath 6beac632b6 ✨(front) list labels in left panel and allow to edit them
Load and display labels in left panel. Add also a modal to
create/edit/delete labels.
2025-06-20 00:58:11 +02:00
Sabrina Demagny b2b71cc405 🐛(api) fix partial update of label 2025-06-20 00:15:35 +02:00
jbpenrath 95f78e4a02 ✨(front) upload mailbox archive as blob
To import old messages from an archive we must now upload the archive file
as a blob then provide the blobId to endpoint to import messages.
2025-06-20 00:13:50 +02:00
Sabrina DemagnyandJean-Baptiste PENRATH eee7afa65c ✨(backend) upload blob for eml and mbox import 2025-06-20 00:13:50 +02:00
Sabrina Demagny ce945259c8 💚(lint) run make lint
A `make lint` run was forgotten in the last commit
2025-06-19 13:45:09 +02:00
jbpenrath e263c56450 ♻️(frontend) update thread stats and thread panel after api refactoring
We recently refactor the way we process thread stats and the filters to list
threads. We have to update the front to work with this new behavior.
2025-06-19 02:05:41 +02:00
jbpenrath 0d4e4f3536 💄(front) clean a little bit label badges
We recently display label badges into thread-item. We revamp that
a little bit to improve code structure and prepare the layout
for further improvements.
2025-06-19 02:05:41 +02:00
Sylvain ZimmerandJean-Baptiste PENRATH 6fd271bed8 ♻️(flags) refactor Thread flags and stats
Migrate from counters to simple flags, because the frontend needs
counts of threads, not sums of counts of messages. Also prepare
for spam and archive features.
2025-06-19 02:05:41 +02:00
Sabrina Demagny e18732bb47 ♻️(labels) move parent labels creation logic
Put the logic into Label model's save() method to guarantee the invariant always holds,
even when using the admin interfacee uses, the shell, bulk operations, or any code path.
2025-06-18 11:21:03 +02:00
Sabrina Demagny a500eadde8 💚(api): ensure consistent thread ordering in list endpoint
- Add secondary ordering by created_at to prevent flaky test results
- When threads have the same messaged_at value, order by newest created_at first
- Ensures deterministic API responses for better test reliability
2025-06-17 19:47:53 +02:00
Sabrina Demagny ad179ee258 ✨(api) allow to list threads by label
Add the ability to filter threads by label slug in the thread list endpoint. This feature
enables users to view all threads associated with a specific label.

Changes:
- Add label_slug query parameter to ThreadViewSet list endpoint
- Implement label-based filtering with proper permission checks
- Add OpenAPI documentation for the new label_id parameter
- Add comprehensive test suite for label filtering

Technical details:
- Filter threads by label while ensuring user has access to the label's mailbox
- Support combining label filter with existing filters (mailbox, search, etc.)
- Add proper error handling for invalid or inaccessible labels
- Add test coverage for various filtering scenarios:
  - Single label filtering
  - Combined label and mailbox filtering
  - Invalid label handling
  - Permission checks
  - Combined filters (label + unread/starred status)
2025-06-16 15:54:41 +02:00
Sabrina Demagny 6d11b9fef5 🐛(backend) fix task response returned
Ensure consistent state reporting across import task updates
2025-06-16 14:35:27 +02:00