feat: add Delivered Mail tab with message-finder search, spam scoring, analysis dialog
- New POST /api/mimecast/delivered route using message-finder/search API - DeliveredMailTab: search by recipient, sender, subject, time range (6h–7d) - Results table with status badge, spam score, row tinting for high/moderate risk - Summary stats bar: total / high spam (≥10) / moderate (5-9) / clean counts - Sort by date or spam score; filter by status (accepted/held/rejected/bounced) - DeliveredAnalysisDialog: explains why high-score mail got through, envelope mismatch detection, actionable remediation steps (block domain, adjust policy threshold, report) - MimecastDeliveredMessage interface + searchDeliveredMessages() method in client
This commit is contained in:
parent
0df5c344b5
commit
8e28062d85
3 changed files with 552 additions and 2 deletions
|
|
@ -89,6 +89,23 @@ export interface MimecastHeldMessage {
|
|||
size: number;
|
||||
}
|
||||
|
||||
export interface MimecastDeliveredMessage {
|
||||
id: string;
|
||||
status: string;
|
||||
subject: string;
|
||||
from: string;
|
||||
fromEnv: string;
|
||||
to: string;
|
||||
toDisplay: string;
|
||||
received: string;
|
||||
senderIP: string;
|
||||
spamScore: number;
|
||||
detectionLevel: string;
|
||||
attachments: boolean;
|
||||
route: string;
|
||||
info: string;
|
||||
}
|
||||
|
||||
export interface MimecastCloudUser {
|
||||
emailAddress: string;
|
||||
domain: string;
|
||||
|
|
@ -526,6 +543,65 @@ export class MimecastClient {
|
|||
return { messages: all, totalCount };
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/message-finder/search
|
||||
* Search delivered/accepted inbound messages. Requires at least one of: to, from, subject, senderIP, url.
|
||||
*/
|
||||
async searchDeliveredMessages(options: {
|
||||
to?: string;
|
||||
from?: string;
|
||||
subject?: string;
|
||||
startHours?: number;
|
||||
start?: string;
|
||||
end?: string;
|
||||
route?: string;
|
||||
}): Promise<{ messages: MimecastDeliveredMessage[]; error?: string }> {
|
||||
const now = new Date();
|
||||
const startDate = options.start
|
||||
? options.start
|
||||
: new Date(now.getTime() - (options.startHours ?? 24) * 60 * 60 * 1000)
|
||||
.toISOString()
|
||||
.replace(/\.\d{3}Z$/, '+0000');
|
||||
const endDate = options.end ?? now.toISOString().replace(/\.\d{3}Z$/, '+0000');
|
||||
|
||||
const opts: Record<string, any> = {};
|
||||
if (options.to) opts.to = options.to;
|
||||
if (options.from) opts.from = options.from;
|
||||
if (options.subject) opts.subject = options.subject;
|
||||
if (options.route) opts.route = options.route;
|
||||
|
||||
try {
|
||||
const result = await this.request<any>('POST', '/api/message-finder/search', {
|
||||
data: [{
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
advancedTrackAndTraceOptions: opts,
|
||||
}],
|
||||
});
|
||||
const emails: any[] = result?.data?.[0]?.trackedEmails ?? [];
|
||||
return {
|
||||
messages: emails.map(e => ({
|
||||
id: e.id,
|
||||
status: e.status,
|
||||
subject: e.subject ?? '',
|
||||
from: e.fromHdr?.emailAddress ?? e.fromEnv?.emailAddress ?? '',
|
||||
fromEnv: e.fromEnv?.emailAddress ?? '',
|
||||
to: e.to?.[0]?.emailAddress ?? '',
|
||||
toDisplay: e.to?.[0]?.displayableName ?? '',
|
||||
received: e.received,
|
||||
senderIP: e.senderIP ?? '',
|
||||
spamScore: e.spamScore ?? 0,
|
||||
detectionLevel: e.detectionLevel ?? '',
|
||||
attachments: e.attachments ?? false,
|
||||
route: e.route ?? '',
|
||||
info: e.info ?? '',
|
||||
})),
|
||||
};
|
||||
} catch (err: any) {
|
||||
return { messages: [], error: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/gateway/hold-release
|
||||
* Releases a held message by ID. Returns true if released successfully.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue