- 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.
- 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.
- 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.
* ✨(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
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.
- 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
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.
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à".
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
- 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.
- 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>
- 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
- 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.
- 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.
- 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.
- 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.
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.
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.
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.
- 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
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)
This allows user creation, passwords reset and listing users from
Keycloak, plus a new MailDomainAccess model for admins.
* ✨(admin) add maildomainacess model, api route and backend tests
* ♻️(drf) simplify API code
* ✨(keycloack) add deployable keycloak to PaaS
* ✨(keycloak) add integration via API, upgrade to 26.x
* 🗑️(settings) remove invitation setting
* 🐛(tests) fix failing tests after rebase
* 🚨(all) fix lint
Avoid duplicate threads when importing the same file multiple times.
Changes:
- Moved duplicate message check to the start of deliver_inbound_message
- Maintains proper threading relationships while preventing duplicate threads
This ensures that:
- No duplicate threads are created when importing the same file multiple times
Test coverage:
- Updated existing import tests to check thread counts
- Verified that duplicate imports don't create new threads
This commit implements a complete label management system with the following features:
- Add CRUD operations for labels with hierarchical support (using slash-based naming)
- Implement label-thread associations (add/remove threads to/from labels)
- Add comprehensive permission checks (ADMIN/EDITOR roles required for management)
- Support hierarchical label structure with automatic parent creation
- Add color customization for labels
- Implement proper slug generation for label names
- Add extensive test coverage for all label operations
Technical details:
- New LabelViewSet with list, create, update, delete operations
- Custom actions for thread management (add-threads, remove-threads)
- Hierarchical label structure with parent-child relationships
- Automatic parent label creation when creating nested labels
- Proper permission handling based on mailbox access roles
- Comprehensive test suite covering all edge cases
- OpenAPI documentation for all endpoints
Enhance support for MBOX files from various email export tools by handling
both extensionless files and text/plain MIME type. This improves compatibility
with different export formats while maintaining security through proper
validation.
Changes:
- Add support for files named "mbox" without extension
- Allow text/plain MIME type for MBOX files (common in webmail exports)
- Keep application/mbox as the primary MIME type for MBOX files
- Update validation to check both MIME types and file extensions
- Add test cases for extensionless files and text/plain MIME type
- Update error messages to be more descriptive about supported formats
The validation now handles:
- Files with .mbox extension (application/mbox or text/plain MIME type)
- Files named "mbox" without extension
- Maintains strict validation to ensure text/plain is only accepted for MBOX files
This change improves compatibility with various email export tools and webmail
services while maintaining security through proper file validation.
The `accesses` property into the Thread object was not propertly typed so we
update the serializer to fix the type by using dedicated sub serializers then we
run `make api-update` to update schema and api client.
Improve the description of the blob api endpoint then regenerate
schema and client api through `make api-update`. Furthermore we
also update FetchApi interface to manage boundary multipart content type