Aller au contenu

Archivage des emails

🎯 Objectif

Je constate que de plus en plus d'utilisateurs se retrouvent avec des boites mails pesant plusieurs dizaines de Go (je fais également parti du lot). Cela pose plusieurs problèmes :

  • Espace disque : ce dernier n'est généralement pas illimité chez les fournisseurs.
  • Client lourd : Thunderbird et surtout Outlook peuvent vite se retrouver à la ramasse.
  • Recherche : que ce soit sur le webmail ou les clients lourds, la recherche peut devenir galère.

Afin d'alléger les boites mails, nous pouvons soit faire un ménage régulier, archiver manuellement en local ou bien utiliser un logiciel qui archive les mails automatiquement. Cette dernière solution est celle que j'ai bien évidemment retenue 😁 #team_partisan_du_moindre_effort.

Au début je pensais utiliser Paperless-NGX mais je trouvais ça trop lourd pour du simple archivage de mails. Heureusement quelques logiciels libres sont apparus depuis peu. J'ai testé deux solutions pour mes besoins personnels.

Je vais commencer par Mail Archiver pour cet article (non exhaustif) sur les solutions libres d'archivage des emails.

📥 Mail Archiver

👋 Présentation

Voici les fonctionnalités de affichées sur le dépôts Github :

📌 Fonctionnalités principales

  • Archivage automatique des e-mails entrants et sortants de plusieurs comptes
  • Stockage du contenu des e-mails et des pièces jointes avec synchronisation planifiée
  • Interface utilisateur responsive multilingue optimisée pour mobile et ordinateur avec mode sombre
  • OpenID Connect (OIDC) pour l'intégration de services d'authentification externes

🔍 Recherche et accès

  • Recherche avancée dans tous les e-mails archivés avec options de filtrage
  • Prévisualisation des e-mails avec liste des pièces jointes
  • Export de comptes de messagerie complets sous forme de fichiers mbox ou d'archives EML compressées
  • Export d'e-mails individuels sélectionnés ou par lots

👥 Gestion des utilisateurs

  • Prise en charge multi-utilisateurs avec autorisations spécifiques aux comptes
  • Tableau de bord avec statistiques, surveillance du stockage et analyse des expéditeurs
  • Journalisation complète des accès avec suivi détaillé des activités utilisateur (Accès, Export, Suppression, Restauration et bien plus)

🧩 Prise en charge des fournisseurs d'e-mails

  • IMAP : Comptes IMAP traditionnels avec capacités de synchronisation complètes
  • M365 : Comptes de messagerie Microsoft 365 via l'API Microsoft Graph
  • IMPORT : Comptes en import seul pour migrer des archives d'e-mails existantes

📥 Fonctions d'import et de restauration

  • Import MBox et import EML (fichiers ZIP avec prise en charge de la structure de dossiers)
  • Restauration d'e-mails sélectionnés ou de boîtes aux lettres complètes vers des boîtes de destination

🗑️ Politiques de rétention

  • Configuration de la suppression automatique des e-mails archivés du serveur de messagerie après un nombre de jours spécifié
  • Définition de la période de rétention par compte de messagerie (par exemple, 30, 90 ou 365 jours)
  • Rétention d'archive locale : Configuration d'une période de rétention distincte pour l'archive locale

⚖️ Licence : GPL-3.0 license

🧰 Installation

Dans mon cas, je fais tourner Mailarchiver dans une VM tournant sur Proxmox VE.

/srv/docker/mailarchiver/compose.yaml
---
services:
  mailarchive-app:
    image: s1t5/mailarchiver:latest
    container_name: mailarchive-app
    restart: always
    environment:
      # Database Connection
      - ConnectionStrings__DefaultConnection=Host=postgres;Database=MailArchiver;Username=mailuser;Password=35322ad3b95d82d9c649b1e11c98030b4c7046848a886450f36bcdb97b3bce0a;

      # Authentication Settings
      - Authentication__Username=admin
      - Authentication__Password=<VOTRE_SUPER_PASSWORD>
      - Authentication__SessionTimeoutMinutes=60
      - Authentication__CookieName=MailArchiverAuth

      # MailSync Settings
      - MailSync__IntervalMinutes=15
      - MailSync__TimeoutMinutes=60
      - MailSync__ConnectionTimeoutSeconds=180
      - MailSync__CommandTimeoutSeconds=300
      - MailSync__AlwaysForceFullSync=false
      - MailSync__IgnoreSelfSignedCert=false

      # BatchRestore Settings
      - BatchRestore__AsyncThreshold=50
      - BatchRestore__MaxSyncEmails=150
      - BatchRestore__MaxAsyncEmails=50000
      - BatchRestore__SessionTimeoutMinutes=30
      - BatchRestore__DefaultBatchSize=50

      # BatchOperation Settings
      - BatchOperation__BatchSize=50
      - BatchOperation__PauseBetweenEmailsMs=50
      - BatchOperation__PauseBetweenBatchesMs=250

      # Selection Settings
      - Selection__MaxSelectableEmails=250

      # View Settings (Privacy & Display)
      - View__DefaultToPlainText=true
      - View__BlockExternalResources=false

      # Npgsql Settings
      - Npgsql__CommandTimeout=900

      # Upload Settings for MBox and EML files
      - Upload__MaxFileSizeGB=10
      - Upload__KeepAliveTimeoutHours=4
      - Upload__RequestHeadersTimeoutHours=2

      # TimeZone Settings
      - TimeZone__DisplayTimeZoneId=Europe/Paris

      # Database Maintenance Settings (Optional)
      - DatabaseMaintenance__Enabled=true
      - DatabaseMaintenance__DailyExecutionTime=02:00
      - DatabaseMaintenance__TimeoutMinutes=30

      # Logging Settings (Optional - defaults to Information level)
      - Logging__LogLevel__Default=Warning
      - Logging__LogLevel__Microsoft_AspNetCore=Error
      - Logging__LogLevel__Microsoft_EntityFrameworkCore_Database_Command=Error

      # Security Settings
      #- AllowedHosts=mailarchiver.example.com;www.mailarchiver.example.com

    ports:
      - "5000:5000"
    networks:
      - postgres
    volumes:
      - ./data-protection-keys:/app/DataProtection-Keys
    depends_on:
      postgres:
        condition: service_healthy

  postgres:
    image: postgres:17-alpine
    container_name: mailarchive-pgsql
    restart: always
    environment:
      POSTGRES_DB: MailArchiver
      POSTGRES_USER: mailuser
      # Commande pour générer le password : openssl rand -hex 32
      POSTGRES_PASSWORD: 35322ad3b95d82d9c649b1e11c98030b4c7046848a886450f36bcdb97b3bce0a
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    networks:
      - postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mailuser -d MailArchiver"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

networks:
  postgres:

J'ai laissé les valeurs par défaut fournies par la documentation (https://github.com/s1t5/mail-archiver/blob/2602.1/doc/Setup.md)

🛠️ Prise en main

Une fois le conteneur instancié, connectez-vous sur l'URL http://IP_SERVEUR:5000. Je suis sur un PoC, on mettra bien évidemment en production un reverse-proxy devant avec chiffrement de la connexion.

Mire de connexion

Entrez le nom d'utilisateur et le mot de passe associé (ici admin et le mot de passe configurés précédemment dans le compose.yml).

Lors de la première connexion, il vous sera demandé de changer le mot de passe défini dans le compose.yml.

Changement du mot de passe par défaut de l'admin

Arrivé une fois sur le tableau de bord, nous allons créer une premier utilisateur possédant un compte de messagerie ayant l'option IMAP.

Dans le cas d'un usage personnel, nous pourrions directement configuré nos comptes de messagerie. Dans le cadre d'un usage professionnel, je ne veux pas connaître le mot de passe du compte de messagerie des utilisateurs. Je vais donc cocher Auto-Gestionnaire (au moins le temps de la configuration de la boite de l'utilisateur).

Création d'un utilisateur Auto-Gestionnaire

Connectez-vous avec l'utilisateur créé, cliquez sur Comptes de messagerie > Ajouter un compte, puis renseignez les paramètres du compte IMAP.

J'en ai profité pour indiquer de supprimer les mails de plus d'un an de la boite mail. Cela permettra de vider la boite mail courante tout en les conservant dans l'archive.

Ajout d'un compte de messagerie

Une fois le compte de messagerie configuré, il faut se reconnecter en tant qu'admin afin de décocher la case "Auto-Gestionnaire" de l'utilisateur créé précédemment. Il faudra penser également à lancer manuellement la première synchronisation du compte de messagerie depuis le compte admin car un compte non auto-gestionnaire ne peut que consulter les mails archivés mais il ne peut pas lancer de synchronisation manuelle.

Une fois la synchoranisation réalisée, l'utilisateur obtient un tableau de bord contenant différentes mesures (nombre d'emails, nombre de mails reçus par mois...)

Tableau de bord et stats

Il peut également faire des recherches dans les mails archivés :

Recherche

🏁 Conclusion

Ce premier outil est relativement simple à mettre en place et la documentation très claire.

🟢 Avantages

  • Application intuitive (admin et utilisateurs).
  • Application bien documentée sur la partie admin.
  • La fonctionnalité de retention des mails permet d'éviter de saturer la boite mail.
  • On peut également sortir des dossiers que l'on ne souhaite pas archiver (Draft/Brouillons par exemple).
  • L'outil permet également de restaurer des mails.
  • Export de l'archive.

🔴 Inconvénients

  • On ne peut pas configurer une boite mail pour un utilisateur en tant qu'administrateur sans renseigner le mot de passe de la messagerie en question. J'aurai bien aimé configuré une boite mail sans mot de passe, l'affecter à un utilisateur et lui laisser renseigner ce dernier. Cela demande actuellement quelques manipulation si l'on ne veut pas saisir le mot de passe que l'on ne doit pas connaître (activer/désactiver l'option Auto-Gestionnaire).
  • Pas d'import PST possible (c'est embêtant si l'utilisateur utilise un compte POP3 avec Outlook par exemple)
  • Pas de rececherche possible sur les pièces jointes.
  • En cas de "rogue admin", l'utilisateur ne voit pas ce que l'admin a opéré sur son archive.

💸 Sponsor (si vous souhaitez soutenir ce projet même si c'est quelques euros) :

📥 OpenArchiver

👋 Présentation

📌 Fonctionnalités principales

Sur le papier c'est prometteur :

  • Ingestion universelle : Connexion à n'importe quel fournisseur de messagerie pour effectuer des imports initiaux en masse et maintenir une synchronisation continue en temps réel. Les sources d'ingestion incluent :
    • Connexion IMAP
    • Google Workspace
    • Microsoft 365
    • Fichiers PST
    • Fichiers .eml compressés
    • Fichiers Mbox
  • Stockage sécurisé et efficace : Les emails sont stockés au format standard .eml. Le système utilise la déduplication et la compression pour réduire les coûts de stockage. Tous les fichiers sont chiffrés au repos.
  • Backends de stockage modulaires : Support du stockage sur système de fichiers local et du stockage objet compatible S3 (comme AWS S3 ou MinIO).
  • Recherche et découverte électronique puissantes : Un moteur de recherche haute performance indexe le texte intégral des emails et des pièces jointes (PDF, DOCX, etc.).
  • Découverte de fils de discussion : La capacité de découvrir si un email appartient à un fil de discussion/une conversation et de présenter le contexte.
  • Conformité et rétention (Pas encore disponible) : Définition de politiques de rétention granulaires pour gérer automatiquement le cycle de vie de vos données. Application de conservations légales sur les communications pour empêcher leur suppression pendant les litiges.
  • Hachage et chiffrement des fichiers : Les valeurs de hachage des emails et des pièces jointes sont stockées dans la base de métadonnées lors de l'ingestion, ce qui signifie que toute tentative de modification du contenu des fichiers sera identifiée, garantissant la conformité légale et réglementaire. Chaque email archivé est accompagné d'une fonctionnalité de « Rapport d'intégrité » qui indique si les fichiers sont originaux.
  • Audit exhaustif (Pas encore disponible) : Une piste d'audit immuable enregistre toutes les activités du système, garantissant un historique clair de qui a accédé à quoi et quand.

⚖️ Licence : AGPL-3.0 license

🧰 Installation

Comme pour Mail Archiver, je fais tourner Openarchiver dans une VM tournant sur Proxmox VE.

Préparation
cd /srv/docker
git clone https://github.com/LogicLabs-OU/OpenArchiver.git
cd OpenArchiver
sudo mkdir -p /var/data/open-archiver
sudo chown -R $(id -u):$(id -g) /var/data/open-archiver
cp .env.example.docker .env
Fichier .env
# --- Application Settings ---
# Set to 'production' for production environments
NODE_ENV=production
PORT_BACKEND=4000
PORT_FRONTEND=3000
# The public-facing URL of your application. This is used by the backend to configure CORS.
APP_URL=http://<IP_SERVEUR>:3000
# This is used by the SvelteKit Node adapter to determine the server's public-facing URL.
# It should always be set to the value of APP_URL.
ORIGIN=$APP_URL
# The frequency of continuous email syncing. Default is every minutes, but you can change it to another value based on your needs.
SYNC_FREQUENCY='* * * * *' 
# Set to 'true' to include Junk and Trash folders in the email archive. Defaults to false.
ALL_INCLUSIVE_ARCHIVE=false

# --- Docker Compose Service Configuration ---
# These variables are used by docker-compose.yml to configure the services. Leave them unchanged if you use Docker services for Postgresql, Valkey (Redis) and Meilisearch. If you decide to use your own instances of these services, you can substitute them with your own connection credentials.

# PostgreSQL
POSTGRES_DB=open_archive
POSTGRES_USER=admin
# Password : openssl rand -hex 32
POSTGRES_PASSWORD=2bcf5176c7da0b176a1f0fe5afee26c21f71dc25b6582638ed5fc78d5838535b
DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}"

# Meilisearch
# MASTER_KEY : openssl rand -hex 32
MEILI_MASTER_KEY=9a6927999c1890a988d4040a5f20af330ca336b94f4da76f96c5f8393c04b6eb
MEILI_HOST=http://meilisearch:7700
# The number of emails to batch together for indexing. Defaults to 500.
MEILI_INDEXING_BATCH=500


# Redis (We use Valkey, which is Redis-compatible and open source)
REDIS_HOST=valkey
REDIS_PORT=6379
# Password : openssl rand -hex 32
REDIS_PASSWORD=68e05813bfc2731553cdc4bec09001749d873a3e401aea54282d6f46c1656cbd
# If you run Valkey service from Docker Compose, set the REDIS_TLS_ENABLED variable to false.
REDIS_TLS_ENABLED=false


# --- Storage Settings ---
# Choose your storage backend. Valid options are 'local' or 's3'.
STORAGE_TYPE=local
# The maximum request body size to accept in bytes including while streaming. The body size can also be specified with a unit suffix for kilobytes (K), megabytes (M), or gigabytes (G). For example, 512K or 1M. Defaults to 512kb. Or the value of  Infinity if you don't want any upload limit.
BODY_SIZE_LIMIT=100M

# --- Local Storage Settings ---
# The path inside the container where files will be stored.
# This is mapped to a Docker volume for persistence.
# This is not an optional variable, it is where the Open Archiver service stores application data. Set this even if you are using S3 storage.
# Make sure the user that runs the Open Archiver service has read and write access to this path.
# Important: It is recommended to create this path manually before installation, otherwise you may face permission and ownership problems.
STORAGE_LOCAL_ROOT_PATH=/var/data/open-archiver

# --- S3-Compatible Storage Settings ---
# These are only used if STORAGE_TYPE is 's3'.
STORAGE_S3_ENDPOINT=
STORAGE_S3_BUCKET=
STORAGE_S3_ACCESS_KEY_ID=
STORAGE_S3_SECRET_ACCESS_KEY=
STORAGE_S3_REGION=
# Set to 'true' for MinIO and other non-AWS S3 services
STORAGE_S3_FORCE_PATH_STYLE=false

# --- Storage Encryption ---
# IMPORTANT: Generate a secure, random 32-byte hex string for this key.
# You can use `openssl rand -hex 32` to generate a key.
# This key is used for AES-256 encryption of files at rest.
# This is an optional variable, if not set, files will not be encrypted.
# ENCRYPTION_KEY : openssl rand -hex 32
STORAGE_ENCRYPTION_KEY=dcd4daf7447c1b3cc6778adcaa9df19c9e6180f40227146472a8ccc0f5e8a8b1

# --- Security & Authentication ---

# Enable or disable deletion of emails and ingestion sources. Defaults to false.
ENABLE_DELETION=true

# Rate Limiting
# The window in milliseconds for which API requests are checked. Defaults to 60000 (1 minute).
RATE_LIMIT_WINDOW_MS=60000
# The maximum number of API requests allowed from an IP within the window. Defaults to 100.
RATE_LIMIT_MAX_REQUESTS=100



# JWT
# IMPORTANT: Change this to a long, random, and secret string in your .env file
# Secret : openssl rand -hex 32
JWT_SECRET=5bac359571cd1d9f642cfc01900a12eb1403a63636c2027bfe3b0dc58310e36d
JWT_EXPIRES_IN="7d"


# Master Encryption Key for sensitive data (Such as Ingestion source credentials and passwords)
# IMPORTANT: Generate a secure, random 32-byte hex string for this
# You can use `openssl rand -hex 32` to generate a key.
# Key : openssl rand -hex 32
ENCRYPTION_KEY=5a428e0f41c66aa658f761da68ecd0d73b7a123304861e955ec99f1dbc4ab219

# Apache Tika Integration
# ONLY active if TIKA_URL is set
TIKA_URL=http://tika:9998
docker-compose.yaml
---
services:
    open-archiver:
        image: logiclabshq/open-archiver:latest
        container_name: open-archiver
        restart: unless-stopped
        ports:
            - '3000:3000' # Frontend
        env_file:
            - .env
        volumes:
            - ${STORAGE_LOCAL_ROOT_PATH}:${STORAGE_LOCAL_ROOT_PATH}
        depends_on:
            - postgres
            - valkey
            - meilisearch
        networks:
            - open-archiver-net

    postgres:
        image: postgres:17-alpine
        container_name: postgres
        restart: unless-stopped
        environment:
            POSTGRES_DB: ${POSTGRES_DB:-open_archive}
            POSTGRES_USER: ${POSTGRES_USER:-admin}
            POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
        volumes:
            - ./pgdata:/var/lib/postgresql/data
        networks:
            - open-archiver-net

    valkey:
        image: valkey/valkey:8-alpine
        container_name: valkey
        restart: unless-stopped
        command: valkey-server --requirepass ${REDIS_PASSWORD}
        volumes:
            - ./valkeydata:/data
        networks:
            - open-archiver-net

    meilisearch:
        image: getmeili/meilisearch:v1.15
        container_name: meilisearch
        restart: unless-stopped
        environment:
            MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-aSampleMasterKey}
        volumes:
            - ./meilidata:/meili_data
        networks:
            - open-archiver-net

    tika:
        image: apache/tika:3.2.2.0-full
        container_name: tika
        restart: always
        networks:
            - open-archiver-net

networks:
    open-archiver-net:
        driver: bridge

🛠️ Prise en main

Une fois le conteneur instancié, connectez-vous sur l'URL http://IP_SERVEUR:3000. Rappel : je suis sur un PoC, on mettra bien évidemment en production un reverse-proxy devant avec chiffrement de la connexion.

Renseignez les informations demandées afin de créer un premier utilisateur qui sera l'admin par défaut.

Mire de connexion Openarchiver

Vous arriverez ensuite sur la tableau de bord vous invitant à configuer une première boite mail.

Tableau de bord invitant à la création d'une ingestion

Vous pouvez passer l'interface en français depuis Settings > System

Langage

Avant de créer un utilisateur, il faut d'abord créer un rôle qui lui sera affecter lors de sa création.

Création rôle

Création rôle

Et là il faut renseigner un tableau d’objets JSON... Pour rappel, le projet est encore jeune. Je me suis basé cet exemple (https://docs.openarchiver.com/services/iam-service/iam-policy#end-user)[https://docs.openarchiver.com/services/iam-service/iam-policy#end-user] pour créer deux profils : un profil utlisateur et un profil auto-gestionnaire, l'idée étant de laisser l'utilisateur auto-gestionnaire le temps qu'il paramètre son compte mail puis de le basculer dans le rôle "Utilisateur" une fois son ingestion créée.

Role auto-gestionnaire
[
  {
    "action": "read",
    "subject": "dashboard"
  },
  {
    "action": "create",
    "subject": "ingestion"
  },
  {
    "action": "manage",
    "subject": "ingestion",
    "conditions": {
      "userId": "${user.id}"
    }
  },
  {
    "action": "manage",
    "subject": "archive",
    "conditions": {
      "ingestionSource.userId": "${user.id}"
    }
  }
]
Role utlisateur
[
  {
    "action": "read",
    "subject": "dashboard"
  },
  {
    "action": "read",
    "subject": "ingestion",
    "conditions": {
      "userId": "${user.id}"
    }
  },
  {
    "action": "manage",
    "subject": "archive",
    "conditions": {
      "ingestionSource.userId": "${user.id}"
    }
  }
]

Les rôles maintenant créé, j'accède à Admin > Utilisateurs et j'ajoute un utilisateur auquel j'affecte le rôle d'Auto-gestionnaire.

Une fois connecté avec l'utilisateur, j'ajoute une source d'ingestion.

Source d'ingestion

Si vous renseignez 993 comme port, vous devez cocher la case TLS. Si vous mettez 143 comme port, le starttls est pris en charge et vous devez décocher la case TLS. Ce n'est pas très clair comme configuration et j'ai du vérifier les logs de mon serveur mail pour être sûr que le TLS était bien activé avec le port 143. Et c'était le cas.

Synchronisez et allons voir les emails en se rendant dans Archive > Emails archivés.

L'interface est plutôt sobre et réactive.

Interface

Quand on ouvre un mail, celui-ci s'affiche au format HTML directement sans pouvoir l'afficher en mode texte brut.

Interface

On peut télécharger l'email ou le supprimer. Le rapport d'intégrité indique si l'email a été altéré ou pas. Par contre pas de possibilité d'exporter l'ensemble des mails mais c'est normal étant donné que le fonctionnalité n'a pas encore été développée. On peut suivre le projet ici https://github.com/orgs/LogicLabs-OU/projects/4

Niveau recherche, on commence à avoir quelque chose qui fait la différence avec Mail Archiver. Outre le fait que nous pouvons faire des recherches classiques sur un email (adresse mail, objet, contenu...), nous pouvons également rechercher des mots clés contenus dans les pièces jointes (PDF, docx...).

Test avec un PDF (une facture d'un fournisseur d'outillage en ligne). Dans cet exemple, je constate que le mot clé a bien été trouvé dans le PDF.

Recherche PDF

Avec un fichier .docx : Recherche docx

🏁 Conclusion

Open Archiver est également simple à mettre en place mais un peu plus compliqué à prendre en main que Mail Archiver.

🟢 Avantages

  • Application intuitive pour les utilisateurs.
  • Recherche de mots clés possible dans les pièces jointes.
  • Ingestion des mails avec différentes sources dont les fichiers PST.

🔴 Inconvénients

  • Projet encore très jeune.
  • Gestion des rôles complexe.
  • Pas de politique de rétention possible.
  • Pas d'export encore possible.

Comme je l'ai indiqué, le projet est très jeune mais si les devs se tiennent à leur feuille de route, je pense que l'application peut être très prometteuse. À suivre...

💸 Sponsor (si vous souhaitez soutenir ce projet même si c'est quelques euros) : https://github.com/sponsors/wayneshn

Conclusion

Il m'est difficile de départager les deux solutions. Mail Archiver est très abouti mais Open Archiver peut rechercher des mots clés dans les pièces jointes et d'importer des PST... Pour le moment j'ai décidé de faire tourner les deux solutions et voir l'évolution de chacun avant de prendre une décision finale.