- Add searchMailboxMessages, deleteMailboxMessage, moveToDeletedItems to MsGraphClient - POST /api/mimecast/mailbox-remediate: search, move, delete actions with permission error handling - DeliveredAnalysisDialog: Remove from mailbox panel with search → confirm → delete flow - Shows matching messages in mailbox with checkboxes, received time, read/unread status - Moves selected to Deleted Items (recoverable) via Graph API - Surfaces clear permission guidance if Mail.ReadWrite not yet granted
77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { getMsgraphClient, isMsgraphConfigured } from '@/lib/services/msgraph-factory';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
/**
|
|
* POST /api/mimecast/mailbox-remediate
|
|
* Body: { action: 'search' | 'delete' | 'move', userEmail, fromAddress?, subject?, messageIds? }
|
|
*
|
|
* Requires Mail.ReadWrite application permission on the Graph app registration.
|
|
*/
|
|
export async function POST(req: NextRequest) {
|
|
try {
|
|
if (!isMsgraphConfigured()) {
|
|
return NextResponse.json({ error: 'Microsoft Graph not configured' }, { status: 503 });
|
|
}
|
|
|
|
const { action, userEmail, fromAddress, subject, messageIds, hardDelete } = await req.json();
|
|
|
|
if (!userEmail) {
|
|
return NextResponse.json({ error: 'userEmail is required' }, { status: 400 });
|
|
}
|
|
|
|
const client = getMsgraphClient();
|
|
|
|
if (action === 'search') {
|
|
if (!fromAddress && !subject) {
|
|
return NextResponse.json({ error: 'fromAddress or subject required for search' }, { status: 400 });
|
|
}
|
|
const messages = await client.searchMailboxMessages({
|
|
userEmail,
|
|
fromAddress: fromAddress || undefined,
|
|
subject: subject || undefined,
|
|
maxResults: 100,
|
|
});
|
|
return NextResponse.json({ messages, total: messages.length });
|
|
}
|
|
|
|
if (action === 'delete' || action === 'move') {
|
|
if (!Array.isArray(messageIds) || messageIds.length === 0) {
|
|
return NextResponse.json({ error: 'messageIds array required' }, { status: 400 });
|
|
}
|
|
|
|
const results: { id: string; ok: boolean; error?: string }[] = [];
|
|
|
|
for (const id of messageIds) {
|
|
try {
|
|
if (action === 'delete' && hardDelete) {
|
|
await client.deleteMailboxMessage(userEmail, id);
|
|
} else {
|
|
await client.moveToDeletedItems(userEmail, id);
|
|
}
|
|
results.push({ id, ok: true });
|
|
} catch (err: any) {
|
|
results.push({ id, ok: false, error: err.message });
|
|
}
|
|
}
|
|
|
|
const succeeded = results.filter(r => r.ok).length;
|
|
const failed = results.filter(r => !r.ok).length;
|
|
return NextResponse.json({ results, succeeded, failed });
|
|
}
|
|
|
|
return NextResponse.json({ error: `Unknown action: ${action}` }, { status: 400 });
|
|
} catch (error: any) {
|
|
const isPermission = error.message?.includes('403') || error.message?.includes('AccessDenied') || error.message?.includes('Access is denied');
|
|
if (isPermission) {
|
|
return NextResponse.json({
|
|
error: 'Mail.ReadWrite permission not granted',
|
|
detail: 'Grant Mail.ReadWrite application permission to the Graph app in Azure Portal → App registrations → API permissions, then click Grant admin consent.',
|
|
permissionRequired: true,
|
|
}, { status: 403 });
|
|
}
|
|
console.error('[mailbox-remediate] error:', error);
|
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
}
|
|
}
|