#!/usr/bin/env php / */ require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../web/includes/db.php'; use ZBateson\MailMimeParser\MailMimeParser; $parser = new MailMimeParser(); $accounts = db()->query('SELECT * FROM accounts WHERE active = 1')->fetchAll(); foreach ($accounts as $account) { process_account($account, $parser); } function process_account(array $account, MailMimeParser $parser): void { $domain = cfg('domain'); $maildirNew = "/var/mail/vhosts/{$domain}/{$account['username']}/Maildir/new"; $destDir = $account['smb_path']; if (!is_dir($maildirNew)) return; $files = glob($maildirNew . '/*'); if (empty($files)) return; foreach ($files as $filePath) { if (!is_file($filePath)) continue; $fileName = basename($filePath); // Vérifie si déjà traité $st = db()->prepare('SELECT id FROM source_file WHERE file_name = ? AND account_id = ?'); $st->execute([$fileName, $account['id']]); if ($st->fetch()) { // Déjà traité, déplace quand même rename($filePath, "/var/mail/vhosts/{$domain}/{$account['username']}/Maildir/cur/{$fileName}:2,S"); continue; } $handle = fopen($filePath, 'r'); $message = $parser->parse($handle, false); fclose($handle); $subject = $message->getHeaderValue('Subject') ?? '(sans sujet)'; $from = ''; $fromHdr = $message->getHeader('From'); if ($fromHdr) { $from = method_exists($fromHdr, 'getEmail') ? $fromHdr->getEmail() : $fromHdr->getRawValue(); } // Insère l'email source $st = db()->prepare( 'INSERT INTO source_file (account_id, title, sender, file_name) VALUES (?, ?, ?, ?)' ); $st->execute([$account['id'], $subject, $from, $fileName]); $sourceId = (int)db()->lastInsertId(); // Extrait les pièces jointes $attachments = $message->getAllAttachmentParts(); if (!empty($attachments)) { if (!is_dir($destDir)) mkdir($destDir, 0750, true); foreach ($attachments as $att) { $attName = $att->getHeaderParameter('Content-Disposition', 'filename') ?? $att->getHeaderParameter('Content-Type', 'name') ?? 'attachment_' . time(); // Sécurise le nom de fichier $attName = preg_replace('/[^a-zA-Z0-9._\- ]/', '_', $attName); $destPath = $destDir . '/' . $attName; // Évite les collisions de nom if (file_exists($destPath)) { $ext = pathinfo($attName, PATHINFO_EXTENSION); $base = pathinfo($attName, PATHINFO_FILENAME); $destPath = $destDir . '/' . $base . '_' . time() . '.' . $ext; $attName = basename($destPath); } $att->saveContent($destPath); db()->prepare('INSERT INTO files (source_file_id, file_name, path) VALUES (?, ?, ?)') ->execute([$sourceId, $attName, $destPath]); } } // Déplace le mail vers cur/ (marque comme lu) rename($filePath, "/var/mail/vhosts/{$domain}/{$account['username']}/Maildir/cur/{$fileName}:2,S"); } }