Installation HMAIL

Installation

Sur une machine virtuelle windows installer HMAIL :

Installer le serveur depuis
www.hmailserver.com

Installation du framework avec :

Microsoft .NET Framework 2.0 Service Pack 1 (x64)

ou avec Powershell :

Install-WindowsFeature Net-Framework-Core -Source D:\sources\sxs

Puis finaliser l'installation avec vpotre administrateur et mot de passe.

Configuration

Lors du début de la configuration dans l'onglet Domains ajouter votre domaine

ville.sportludique.fr

Ensuite dans Settings puis protocole:

Enfin dans l'onglet advanced du menu :

Ajouter une route permanante vers le LAN

route add -p <réseaux> mask <masque> <passerelle>

Dans le DNS

Externe

Créer un nouvelle enregistrement dans le fichier /etc/bind/db.tours.sportludique.fr.externe :

smtp    IN      A       183.44.37.1

        IN      MX      10      smtp.tours.sportludique.fr

Cet enregistrement permet d'associer smtp.tours.sportludique.fr avec l'adresse ip 183.44.37.1 et le MX c'est pour Mail eXchange.

Interne

Créer un nouvelle enregistrement dans le fichier /etc/bind/db.tours.sportludique.fr.interne :

mail    IN  A   192.168.37.6

    IN  MX  10  smtp.tours.sportludique.fr

smtp    IN  CNAME   mail
imap    IN  CNAME   mail

Cet enregistrement associe mail.tours.sportludique.fr à l'adresse 192.168.37.6 et il permet également à smtp et imap de pointer vers mail.

Lier les utilisateur de l'AD

On ajoute les utilisateurs de l'Active Directory grâce au script powershell suivant:

# Script de synchronisation Active Directory vers hMailServer
# Support AD distant avec authentification

# ========== CONFIGURATION ==========
# Configuration hMailServer
$hMailAdminPassword = ""
$defaultDomain = ""
$defaultPassword = "MotDePasse123!" # Mot de passe par défaut pour nouveaux comptes

# Configuration Active Directory DISTANT
$adServer = ""  # Nom ou IP du serveur AD
$adDomain = ""  # Domaine AD
$adUsername = ""  # Utilisateur avec droits de lecture AD
$adPassword = ""  # Mot de passe pour l'AD

# Construction du chemin LDAP
$ldapPath = "LDAP://$adServer/DC=,DC=,DC=,DC="

# Options
$createNewAccounts = $true
$updateExistingAccounts = $true
$accountMaxSize = 1024  # Taille max en MB
$enableAccountsByDefault = $true

Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Synchronisation AD -> hMailServer" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan

# ========== TEST CONNECTIVITÉ AD ==========
Write-Host "`n[Préparation] Test de connectivité AD..." -ForegroundColor Yellow

try {
    Write-Host "  → Test ping vers $adServer..." -ForegroundColor Gray
    $pingResult = Test-Connection -ComputerName $adServer -Count 1 -Quiet -ErrorAction SilentlyContinue

    if ($pingResult) {
        Write-Host "  ✓ Serveur AD accessible" -ForegroundColor Green
    } else {
        Write-Host "  ⚠ Serveur AD non pingable (peut être normal si ICMP bloqué)" -ForegroundColor Yellow
    }

    Write-Host "  → Test port LDAP 389..." -ForegroundColor Gray
    $tcpClient = New-Object System.Net.Sockets.TcpClient
    $asyncResult = $tcpClient.BeginConnect($adServer, 389, $null, $null)
    $wait = $asyncResult.AsyncWaitHandle.WaitOne(3000, $false)

    if ($wait) {
        $tcpClient.EndConnect($asyncResult)
        $tcpClient.Close()
        Write-Host "  ✓ Port LDAP 389 accessible" -ForegroundColor Green
    } else {
        Write-Host "  ✗ Port LDAP 389 non accessible" -ForegroundColor Red
        Write-Host "    Vérifiez le pare-feu et la connectivité réseau" -ForegroundColor Yellow
    }
}
catch {
    Write-Host "  ⚠ Erreur de test réseau: $_" -ForegroundColor Yellow
}

# ========== CONNEXION HMAILSERVER ==========
Write-Host "`n[1/4] Connexion à hMailServer..." -ForegroundColor Yellow

$hMailApp = $null
$domain = $null

try {
    Write-Host "  → Création de l'objet COM hMailServer.Application..." -ForegroundColor Gray
    $hMailApp = New-Object -ComObject hMailServer.Application

    if ($hMailApp -eq $null) {
        throw "L'objet hMailServer.Application est null"
    }

    Write-Host "  → Authentification..." -ForegroundColor Gray
    $authResult = $hMailApp.Authenticate("Administrator", $hMailAdminPassword)

    if (-not $authResult) {
        throw "Échec de l'authentification hMailServer. Vérifiez le mot de passe."
    }

    Write-Host "  → Récupération du domaine $defaultDomain..." -ForegroundColor Gray
    $domain = $hMailApp.Domains.ItemByName($defaultDomain)

    if ($domain -eq $null) {
        Write-Host "`n✗ Domaine '$defaultDomain' non trouvé!" -ForegroundColor Red
        Write-Host "`nDomaines disponibles:" -ForegroundColor Yellow
        for ($i = 0; $i -lt $hMailApp.Domains.Count; $i++) {
            $d = $hMailApp.Domains.Item($i)
            Write-Host "  - $($d.Name)" -ForegroundColor Cyan
        }
        exit
    }

    Write-Host "✓ Connecté à hMailServer - Domaine: $defaultDomain" -ForegroundColor Green
}
catch {
    Write-Host "`n✗ ERREUR de connexion hMailServer:" -ForegroundColor Red
    Write-Host $_.Exception.Message -ForegroundColor Red
    Write-Host "`nVérifications:" -ForegroundColor Yellow
    Write-Host "1. Service hMailServer démarré ?" -ForegroundColor White
    Write-Host "2. PowerShell exécuté en Administrateur ?" -ForegroundColor White
    Write-Host "3. Mot de passe administrateur correct ?" -ForegroundColor White
    exit
}

# ========== RÉCUPÉRATION DES COMPTES HMAILSERVER ==========
Write-Host "`n[2/4] Récupération des comptes hMailServer existants..." -ForegroundColor Yellow

$hmailAccounts = @{}
try {
    for ($i = 0; $i -lt $domain.Accounts.Count; $i++) {
        $account = $domain.Accounts.Item($i)
        $hmailAccounts[$account.Address.ToLower()] = $account
    }
    Write-Host "✓ $($hmailAccounts.Count) comptes trouvés" -ForegroundColor Green
}
catch {
    Write-Host "✗ Erreur: $_" -ForegroundColor Red
    exit
}

# ========== CONNEXION À L'AD DISTANT ==========
Write-Host "`n[3/4] Connexion à l'Active Directory distant..." -ForegroundColor Yellow
Write-Host "  Serveur: $adServer" -ForegroundColor Gray
Write-Host "  Chemin LDAP: $ldapPath" -ForegroundColor Gray

try {
    # Créer des credentials pour l'AD distant
    $secPassword = ConvertTo-SecureString $adPassword -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($adUsername, $secPassword)

    # Créer la connexion LDAP avec authentification
    Write-Host "  → Authentification sur l'AD..." -ForegroundColor Gray

    $directoryEntry = New-Object System.DirectoryServices.DirectoryEntry(
        $ldapPath,
        $adUsername,
        $adPassword,
        [System.DirectoryServices.AuthenticationTypes]::Secure
    )

    # Test de la connexion
    $testBind = $directoryEntry.Name
    if ([string]::IsNullOrEmpty($testBind) -and $directoryEntry.NativeObject -eq $null) {
        throw "Impossible de se connecter à l'AD. Vérifiez les credentials et le chemin LDAP."
    }

    Write-Host "  ✓ Authentifié sur l'AD" -ForegroundColor Green

    # Créer le searcher
    Write-Host "  → Recherche des utilisateurs..." -ForegroundColor Gray
    $searcher = New-Object System.DirectoryServices.DirectorySearcher
    $searcher.SearchRoot = $directoryEntry

    # Filtre pour les utilisateurs avec email
    $searcher.Filter = "(&(objectClass=user)(objectCategory=person)(mail=*))"

    # Propriétés à récupérer
    $searcher.PropertiesToLoad.AddRange(@(
        "sAMAccountName",
        "mail",
        "givenName",
        "sn",
        "displayName",
        "userAccountControl"
    ))

    $searcher.PageSize = 1000
    $searcher.SearchScope = [System.DirectoryServices.SearchScope]::Subtree

    $results = $searcher.FindAll()

    Write-Host "✓ $($results.Count) utilisateurs trouvés dans AD" -ForegroundColor Green
}
catch {
    Write-Host "`n✗ ERREUR de connexion AD:" -ForegroundColor Red
    Write-Host $_.Exception.Message -ForegroundColor Red
    Write-Host "`nVérifications:" -ForegroundColor Yellow
    Write-Host "1. Le serveur AD '$adServer' est-il accessible ?" -ForegroundColor White
    Write-Host "2. Les credentials AD sont-ils corrects ?" -ForegroundColor White
    Write-Host "   Username: $adUsername" -ForegroundColor Gray
    Write-Host "3. Le chemin LDAP est-il correct ?" -ForegroundColor White
    Write-Host "   $ldapPath" -ForegroundColor Gray
    Write-Host "4. Le port 389 (LDAP) est-il ouvert ?" -ForegroundColor White
    Write-Host "5. Essayez avec LDAPS (port 636) si disponible" -ForegroundColor White
    exit
}

# ========== SYNCHRONISATION ==========
Write-Host "`n[4/4] Synchronisation en cours..." -ForegroundColor Yellow
Write-Host "────────────────────────────────────────" -ForegroundColor Gray

$stats = @{
    Created = 0
    Updated = 0
    Skipped = 0
    Errors = 0
}

foreach ($result in $results) {
    $props = $result.Properties

    # Récupérer les informations
    $samAccount = if ($props["samaccountname"].Count -gt 0) { $props["samaccountname"][0] } else { "Inconnu" }
    $email = if ($props["mail"].Count -gt 0) { $props["mail"][0] } else { $null }
    $firstName = if ($props["givenname"].Count -gt 0) { $props["givenname"][0] } else { "" }
    $lastName = if ($props["sn"].Count -gt 0) { $props["sn"][0] } else { "" }
    $displayName = if ($props["displayname"].Count -gt 0) { $props["displayname"][0] } else { $samAccount }

    # Vérifier si le compte est actif dans AD
    $userAccountControl = if ($props["useraccountcontrol"].Count -gt 0) { $props["useraccountcontrol"][0] } else { 0 }
    $isEnabled = -not ($userAccountControl -band 0x2)  # 0x2 = ACCOUNTDISABLE

    # Vérifier l'adresse email
    if ([string]::IsNullOrWhiteSpace($email)) {
        Write-Host "⊘ $displayName - Pas d'email" -ForegroundColor DarkGray
        $stats.Skipped++
        continue
    }

    # Forcer le domaine mail si l'email AD ne correspond pas
    if (-not $email.EndsWith("@$defaultDomain")) {
        $emailParts = $email.Split('@')
        $email = "$($emailParts[0])@$defaultDomain"
        Write-Host "ℹ $displayName - Email modifié: $email" -ForegroundColor Cyan
    }

    $emailLower = $email.ToLower()

    try {
        # Vérifier si le compte existe dans hMailServer
        if ($hmailAccounts.ContainsKey($emailLower)) {
            # MISE À JOUR
            if ($updateExistingAccounts) {
                $account = $hmailAccounts[$emailLower]

                $account.PersonFirstName = $firstName
                $account.PersonLastName = $lastName
                $account.Active = $isEnabled
                $account.Save()

                Write-Host "↻ $email - Mis à jour" -ForegroundColor Cyan
                $stats.Updated++
            }
            else {
                Write-Host "→ $email - Existe déjà" -ForegroundColor Gray
                $stats.Skipped++
            }
        }
        else {
            # CRÉATION
            if ($createNewAccounts) {
                $newAccount = $domain.Accounts.Add()
                $newAccount.Address = $email
                $newAccount.Password = $defaultPassword
                $newAccount.Active = if ($enableAccountsByDefault) { $isEnabled } else { $false }
                $newAccount.PersonFirstName = $firstName
                $newAccount.PersonLastName = $lastName
                $newAccount.MaxSize = $accountMaxSize
                $newAccount.Save()

                Write-Host "✓ $email - Créé" -ForegroundColor Green
                $stats.Created++
            }
            else {
                Write-Host "⊘ $email - Nouveau (création désactivée)" -ForegroundColor DarkGray
                $stats.Skipped++
            }
        }
    }
    catch {
        Write-Host "✗ $email - ERREUR: $_" -ForegroundColor Red
        $stats.Errors++
    }
}

# ========== RÉSULTATS ==========
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "RÉSUMÉ DE LA SYNCHRONISATION" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Comptes créés    : $($stats.Created)" -ForegroundColor Green
Write-Host "Comptes mis à jour: $($stats.Updated)" -ForegroundColor Cyan
Write-Host "Comptes ignorés  : $($stats.Skipped)" -ForegroundColor Gray
Write-Host "Erreurs          : $($stats.Errors)" -ForegroundColor Red
Write-Host "────────────────────────────────────────" -ForegroundColor Gray
Write-Host "Total hMailServer: $($domain.Accounts.Count) comptes" -ForegroundColor White
Write-Host "========================================`n" -ForegroundColor Cyan

# ========== NETTOYAGE ==========
if ($results) { $results.Dispose() }
if ($searcher) { $searcher.Dispose() }
if ($directoryEntry) { $directoryEntry.Dispose() }
if ($domain -ne $null) {
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($domain) | Out-Null
}
if ($hMailApp -ne $null) {
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($hMailApp) | Out-Null
}
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Write-Host "Synchronisation terminée!" -ForegroundColor Green

Création des utilisateurs sur Thunderbird

Créer l'utilisateur avec son nom complet, son adresse mail et son mot de passe par default:

Vérifier si les serveur et les port sont correctement configuré:

Le port 143 pour imap et le port 25 pour smtp