Files
2026-09-16 12:39:06 +02:00

289 lines
12 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';
require_once __DIR__ . '/../includes/boards.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 {
// 0. Mail mappen ophalen
if ($action === 'get_folders') {
$forceRefresh = !empty($_GET['refresh']) && $_GET['refresh'] === '1';
$res = microsoft_fetch_mail_folders($userId, $forceRefresh);
echo json_encode($res);
exit;
}
// 0b. Uitgeschakelde mappen opslaan
if ($action === 'save_disabled_folders') {
$input = file_get_contents('php://input');
$data = json_decode($input, true);
$folders = $data['disabled_folders'] ?? ($_POST['disabled_folders'] ?? []);
if (is_string($folders)) {
$folders = json_decode($folders, true) ?: [];
}
if (!is_array($folders)) {
$folders = [];
}
$ok = microsoft_save_disabled_folders($userId, $folders);
echo json_encode(['success' => $ok, 'disabled_folders' => $folders]);
exit;
}
// 1. Inbox of specifieke map berichten ophalen
if ($action === 'get_folder_messages' || $action === 'get_inbox') {
$folderId = trim($_GET['folder_id'] ?? ($_POST['folder_id'] ?? 'inbox'));
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 30;
$unreadOnly = !empty($_GET['unread_only']) && $_GET['unread_only'] === '1';
$forceRefresh = !empty($_GET['refresh']) && $_GET['refresh'] === '1';
$res = microsoft_fetch_folder_messages($userId, $folderId, $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();
// Optioneel toevoegen aan Bord en Tijdlijn
$boardSyncResult = null;
$addToBoard = !empty($input['add_to_board']) && !empty($input['board_id']);
if ($addToBoard) {
$boardId = (int)$input['board_id'];
$laneId = (int)($input['lane_id'] ?? 0);
$scheduleOnTimeline = !empty($input['schedule_on_timeline']);
$timelineStartDate = !empty($input['timeline_start_date']) ? trim($input['timeline_start_date']) : $planDate;
$timelineEndDate = !empty($input['timeline_end_date']) ? trim($input['timeline_end_date']) : $timelineStartDate;
$mailDesc = "Afzender: " . ($sender ?: 'Onbekend');
if (!empty($webLink)) {
$mailDesc .= "\nWeblink: " . $webLink;
}
$boardSyncResult = fociz_add_item_to_board_and_timeline($db, $userId, (($user['role'] ?? '') === 'ADMIN'), [
'board_id' => $boardId,
'lane_id' => $laneId,
'title' => $taskTitle,
'description' => $mailDesc,
'priority' => $priority,
'color' => !empty($input['board_color']) ? $input['board_color'] : 'blue',
'schedule_on_timeline' => $scheduleOnTimeline,
'start_date' => $timelineStartDate,
'end_date' => $timelineEndDate,
'start_time' => $timeBlockStart ?: '09:00',
'end_time' => $timeBlockEnd ?: '10:00',
]);
}
echo json_encode([
'success' => true,
'task_id' => $taskId,
'plan_date' => $planDate,
'outlook_synced' => ($source === 'OUTLOOK'),
'board_sync' => $boardSyncResult,
'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()]);
}