Files
Fociz/api/mail.php
T
2026-09-14 09:21:19 +02:00

232 lines
8.8 KiB
PHP

<?php
/**
* Fociz Microsoft Outlook 365 E-mail API Endpoint
* Verwerkt ophalen van inbox, detailberichten, beantwoorden, doorsturen en 1-klik inplannen.
*/
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/integrations/microsoft.php';
$user = require_auth();
$userId = (int)$user['id'];
$db = get_db_connection();
// Geef het PHP sessieslot direct vrij zodat paginanavigatie nooit geblokkeerd wordt
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
header('Content-Type: application/json; charset=utf-8');
$action = $_GET['action'] ?? ($_POST['action'] ?? '');
try {
// 1. Inbox berichten ophalen
if ($action === 'get_inbox') {
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 25;
$unreadOnly = !empty($_GET['unread_only']) && $_GET['unread_only'] === '1';
$forceRefresh = !empty($_GET['refresh']) && $_GET['refresh'] === '1';
$res = microsoft_fetch_inbox_messages($userId, $limit, $unreadOnly, $forceRefresh);
echo json_encode($res);
exit;
}
// 2. Enkel bericht detail ophalen
if ($action === 'get_message') {
$messageId = trim($_GET['id'] ?? ($_POST['id'] ?? ''));
if (empty($messageId)) {
echo json_encode(['success' => false, 'error' => 'Geen bericht-ID opgegeven.']);
exit;
}
$detail = microsoft_fetch_message_detail($userId, $messageId);
if (!$detail) {
echo json_encode(['success' => false, 'error' => 'Bericht niet gevonden of geen toegang.']);
exit;
}
echo json_encode(['success' => true, 'message' => $detail]);
exit;
}
// 3. Markeer als gelezen of ongelezen
if ($action === 'mark_read') {
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
$messageId = trim($input['id'] ?? '');
$isRead = isset($input['is_read']) ? (bool)$input['is_read'] : true;
if (empty($messageId)) {
echo json_encode(['success' => false, 'error' => 'Geen bericht-ID opgegeven.']);
exit;
}
$ok = microsoft_mark_message_read($userId, $messageId, $isRead);
echo json_encode(['success' => $ok]);
exit;
}
// 4. E-mail beantwoorden
if ($action === 'reply') {
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
$messageId = trim($input['id'] ?? '');
$comment = trim($input['comment'] ?? '');
$replyAll = !empty($input['reply_all']);
if (empty($messageId) || empty($comment)) {
echo json_encode(['success' => false, 'error' => 'Bericht-ID en reactietekst zijn verplicht.']);
exit;
}
$res = microsoft_reply_message($userId, $messageId, $comment, $replyAll);
echo json_encode($res);
exit;
}
// 5. E-mail doorsturen
if ($action === 'forward') {
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
$messageId = trim($input['id'] ?? '');
$toInput = $input['to'] ?? '';
$comment = trim($input['comment'] ?? '');
if (empty($messageId) || empty($toInput)) {
echo json_encode(['success' => false, 'error' => 'Bericht-ID en minimaal één geadresseerde zijn verplicht.']);
exit;
}
$recipients = [];
if (is_array($toInput)) {
$recipients = $toInput;
} else {
$parts = explode(',', (string)$toInput);
foreach ($parts as $p) {
$p = trim($p);
if (filter_var($p, FILTER_VALIDATE_EMAIL)) {
$recipients[] = ['address' => $p, 'name' => $p];
}
}
}
if (empty($recipients)) {
echo json_encode(['success' => false, 'error' => 'Geen geldige e-mailadressen ingevoerd.']);
exit;
}
$res = microsoft_forward_message($userId, $messageId, $recipients, $comment);
echo json_encode($res);
exit;
}
// 6. E-mail direct inplannen in Fociz dagplanning
if ($action === 'plan_email') {
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
$messageId = trim($input['message_id'] ?? $input['mail_id'] ?? '');
$subject = trim($input['title'] ?? $input['subject'] ?? 'E-mail actiepunt');
$planDate = trim($input['plan_date'] ?? $input['date'] ?? date('Y-m-d'));
$timeBlockStart = !empty($input['time_block_start']) ? trim($input['time_block_start']) : null;
$durationMinutes = (int)($input['duration_minutes'] ?? 30);
$priority = in_array($input['priority'] ?? '', ['P1', 'P2', 'P3']) ? $input['priority'] : 'P2';
$webLink = trim($input['web_link'] ?? 'https://outlook.office.com/mail/');
$sender = trim($input['sender'] ?? $input['sender_name'] ?? '');
if (empty($subject)) {
echo json_encode(['success' => false, 'error' => 'Onderwerp is verplicht.']);
exit;
}
if ($durationMinutes <= 0) $durationMinutes = 30;
$timeBlockEnd = !empty($input['time_block_end']) ? trim($input['time_block_end']) : null;
if (!empty($timeBlockStart) && empty($timeBlockEnd)) {
try {
$dtEnd = new DateTime("{$planDate} {$timeBlockStart}:00", new DateTimeZone('Europe/Amsterdam'));
$dtEnd->modify("+{$durationMinutes} minutes");
$timeBlockEnd = $dtEnd->format('H:i');
} catch (Throwable $t) {}
}
// Zorg dat daily_plan bestaat
$stmtPlan = $db->prepare("
INSERT INTO daily_plans (user_id, plan_date)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)
");
$stmtPlan->execute([$userId, $planDate]);
$planId = (int)$db->lastInsertId();
// Als er een custom titel is ingevoerd, gebruik die direct, anders maak een nette titel
$taskTitle = $subject;
if (isset($input['subject']) && !isset($input['title'])) {
$taskTitle = "✉️ " . $subject;
if (!empty($sender) && strpos($taskTitle, $sender) === false) {
$taskTitle .= " (van " . $sender . ")";
}
}
$source = 'OUTLOOK_MAIL';
$externalId = $messageId;
$externalUrl = $webLink;
$outlookSyncMsg = null;
// Automatisch synchroniseren naar Microsoft Outlook agenda
if (function_exists('microsoft_create_event')) {
try {
$syncStartTime = !empty($timeBlockStart) ? $timeBlockStart : '09:00';
$msResult = microsoft_create_event($userId, [
'subject' => $taskTitle,
'description' => "E-mail actiepunt gepland via Fociz ({$priority})\n\nAfzender: {$sender}\nWeblink: {$webLink}",
'date' => $planDate,
'start_time' => $syncStartTime,
'end_time' => $timeBlockEnd,
'duration_minutes' => $durationMinutes,
]);
if (!empty($msResult['success']) && !empty($msResult['event_id'])) {
$source = 'OUTLOOK';
$externalId = $msResult['event_id'];
$externalUrl = $msResult['web_link'] ?? ($webLink ?: 'https://outlook.office.com');
$timeBlockStart = $msResult['start_time'] ?? $syncStartTime;
$timeBlockEnd = $msResult['end_time'] ?? $timeBlockEnd;
$outlookSyncMsg = 'Gesynchroniseerd naar Microsoft Outlook.';
}
} catch (Throwable $t) {
error_log("Fout bij auto-sync Mail naar Outlook: " . $t->getMessage());
}
}
$stmtTask = $db->prepare("
INSERT INTO tasks (user_id, daily_plan_id, title, priority, time_block_start, time_block_end, duration_minutes, source, external_id, external_url)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
");
$stmtTask->execute([
$userId,
$planId,
$taskTitle,
$priority,
$timeBlockStart,
$timeBlockEnd,
$durationMinutes,
$source,
$externalId,
$externalUrl
]);
$taskId = (int)$db->lastInsertId();
echo json_encode([
'success' => true,
'task_id' => $taskId,
'plan_date' => $planDate,
'outlook_synced' => ($source === 'OUTLOOK'),
'message' => "E-mail succesvol ingepland voor {$planDate}." . ($outlookSyncMsg ? " ({$outlookSyncMsg})" : "")
]);
exit;
}
echo json_encode(['success' => false, 'error' => 'Onbekende e-mailactie.']);
} catch (Throwable $e) {
http_response_code(500);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}