Skip to content

Commit 22f3cc9

Browse files
Merge pull request #4517 from MicrosoftDocs/main
[AutoPublish] main to live - 07/16 20:03 PDT | 07/17 08:33 IST
2 parents 6507617 + ed8ad02 commit 22f3cc9

File tree

1 file changed

+35
-74
lines changed

1 file changed

+35
-74
lines changed

defender-office-365/reports-mdo-email-collaboration-dashboard.md

Lines changed: 35 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ ms.collection:
1818
description: Admins can learn about the information on the Microsoft Defender for Office 365 Overview dashboard in the Microsoft Defender portal.
1919
ms.custom:
2020
ms.service: defender-office-365
21-
ms.date: 07/14/2025
21+
ms.date: 07/16/2025
2222
appliesto:
2323
- ✅ <a href="https://learn.microsoft.com/defender-office-365/mdo-about#defender-for-office-365-plan-1-vs-plan-2-cheat-sheet" target="_blank">Microsoft Defender for Office 365 Plan 1 and Plan 2</a>
2424
- ✅ <a href="https://learn.microsoft.com/defender-xdr/microsoft-365-defender" target="_blank">Microsoft Defender XDR</a>
@@ -56,8 +56,9 @@ The graph on the **Phish / Malware Efficacy** card visually represents the prote
5656

5757
- **Pre-delivery**: Items detected before they reach the recipient's mailbox.
5858
- **Post-delivery**: Items removed after the item was delivered to the recipient's mailbox via [zero-hour auto purge (ZAP)](zero-hour-auto-purge.md).
59-
- **Uncaught**: Delivered items that ZAP identified but didn't remove due to them already being remediated. For example:
59+
- **Uncaught**: Delivered items that ZAP identified but failed to remove. For example:
6060
- Admin deletions or remediations.
61+
- ZAP being disabled for the specific mailboxes.
6162
- [Admin submissions](submissions-admin.md) to Microsoft identifying the message as malware or phishing.
6263
- User deletions.
6364
- Non-Microsoft security provider deletions.
@@ -256,87 +257,47 @@ Organizations with Defender for Office 365 Plan 2 can use the following query in
256257
> The numbers might differ slightly due to the different refresh rates for advanced hunting vs. reporting data.
257258
258259
```kusto
259-
// This query by default will take the last 30 days of data.
260-
// The query and calculation can be tweaked to meet individual needs, and will update over time to get incrementally more accurate.
261-
// Ben Harris - Microsoft Defender for Office 365 PM.
262260
let _startTime = ago(30d);
263261
let _endTime = now();
264-
// Get all mailflow detected as clean at time of delivery
265-
let EmailEventsClean = materialize(
262+
let PreDelivery = toscalar(
266263
EmailEvents
267-
| where Timestamp between (_startTime .. _endTime) and EmailDirection == "Inbound"
268-
| where ThreatTypes !contains "Phish" and ThreatTypes !contains "Malware"
269-
| project NetworkMessageId,ThreatTypes
270-
);
271-
// Get all mailflow detected as phish or malware at time of delivery
272-
let EmailEventsThreats = materialize(
273-
EmailEvents
274-
| where Timestamp between (_startTime .. _endTime) and EmailDirection == "Inbound"
275-
| where ThreatTypes contains "Phish" or ThreatTypes contains "Malware"
264+
| where Timestamp between (_startTime .. _endTime)
265+
and EmailDirection == "Inbound"
266+
and DeliveryLocation in ("Junk folder", "Quarantine")
267+
and (ThreatTypes contains "Phish" or ThreatTypes contains "Malware")
276268
| extend MDO_detection = parse_json(DetectionMethods)
277269
| extend FirstDetection = iif(isempty(MDO_detection), "Clean", tostring(bag_keys(MDO_detection)[0]))
278270
| extend FirstSubcategory = iif(FirstDetection != "Clean" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, ": ", tostring(MDO_detection[FirstDetection][0])), "No Detection (clean)")
279-
| project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes
271+
| summarize PreDelivery = count()
280272
);
281-
// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each
282-
let EmailPostDeliveryFiltered = materialize(
273+
let PostDelivery = toscalar(
283274
EmailPostDeliveryEvents
284-
| where Timestamp between (_startTime .. datetime_add('day', 7, _endTime))
285-
| where ActionType in ("Malware ZAP","Phish ZAP","Redelivery")
286-
| extend Key = strcat(NetworkMessageId , "-", RecipientEmailAddress)
287-
| summarize arg_max(Timestamp, *) by Key
288-
| project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId
289-
);
290-
// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket.
291-
let CloudAppEventsFiltered = materialize(
292-
CloudAppEvents
293-
| where Timestamp between (_startTime .. datetime_add('day', 7, _endTime))
294-
| where ActionType == "AdminSubmissionSubmitted"
295-
| extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType)
296-
| extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId)
297-
| where SubmissionType in ("1", "2")
298-
| project SubmissionType,NetworkMessageId
299-
);
300-
// get the number of threats caught in mailflow
301-
let Mal_Phish_Mailflow = toscalar(
302-
EmailEventsThreats
303-
| summarize count()
275+
| where Timestamp between (_startTime .. _endTime)
276+
and ActionType in ("Malware ZAP","Phish ZAP")
277+
and ActionResult in ("Success","UserTriaged")
278+
| summarize PostDelivery = count()
304279
);
305-
// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation
306-
let FP_ZAP = toscalar(
307-
EmailPostDeliveryFiltered
308-
| where ThreatTypes !contains "Phish" and ThreatTypes !contains "Malware" and ActionType == "Redelivery"
309-
| join kind=leftsemi (EmailEventsThreats) on NetworkMessageId
310-
| summarize count()
311-
);
312-
// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action
313-
let FN_ZAP_Successful = toscalar(
314-
EmailPostDeliveryFiltered
315-
| where ActionType in ("Malware ZAP","Phish ZAP") and ActionResult in ("Success","AdminPolicy")
316-
| join kind=leftsemi (EmailEventsClean) on NetworkMessageId
317-
| summarize count()
318-
);
319-
// get the number of threats unsuccessfully cleaned up post delivery.
320-
let FN_ZAP_Unsuccessful = toscalar(
321-
EmailPostDeliveryFiltered
322-
| where ActionType in ("Malware ZAP","Phish ZAP") and ActionResult !in ("Success","AdminPolicy")
323-
| join kind=leftsemi (EmailEventsClean) on NetworkMessageId
324-
| summarize count()
280+
let Uncaught = toscalar(
281+
EmailPostDeliveryEvents
282+
| where Timestamp between (_startTime .. _endTime)
283+
and ActionType in ("Malware ZAP","Phish ZAP")
284+
and ActionResult !in ("Success", "UserTriaged")
285+
| summarize Uncaught = count()
325286
);
326-
// join the administrative submissions to clean mailflow to find the additional miss
327-
let FN_Admin_Submissions = toscalar(
328-
CloudAppEventsFiltered
329-
| join kind=rightsemi (EmailEventsClean) on NetworkMessageId
330-
| summarize count()
331-
);
332-
// print each result, and run the calculation to work out effectiveness at time of delivery and post delivery.
333-
union withsource=Table
334-
(print StatisticName="Mal/Phish Mailflow totals - Minus FPs", Value=toreal(Mal_Phish_Mailflow) - toreal(FP_ZAP)),
335-
(print StatisticName="Admin Mal/Phish FNs Submitted", Value=toreal(FN_Admin_Submissions)),
336-
(print StatisticName="Mal/Phish FPs Reverse Zapped", Value=toreal(FP_ZAP)),
337-
(print StatisticName="Mal / Phish Successfully Zapped", Value=toreal(FN_ZAP_Successful)),
338-
(print StatisticName="Mal / Phish UN-Successfully Zapped", Value=toreal(FN_ZAP_Unsuccessful)),
339-
(print StatisticName="Effectiveness Post Delivery", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))),
340-
(print StatisticName="Effectiveness Pre-Delivery", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_ZAP_Successful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2)))
287+
let PreDeliveryReal = toreal(PreDelivery);
288+
let PostDeliveryReal = toreal(PostDelivery);
289+
let UncaughtReal = toreal(Uncaught);
290+
let Effectiveness = round(
291+
iif(
292+
(PreDeliveryReal + PostDeliveryReal + UncaughtReal) == 0,
293+
0.0,
294+
((PreDeliveryReal + PostDeliveryReal) / (PreDeliveryReal + PostDeliveryReal + UncaughtReal)) * 100.0
295+
), 2
296+
);
297+
union
298+
(print StatisticName = "Pre-Delivery Catch", Value = PreDeliveryReal),
299+
(print StatisticName = "Post-Delivery Catch", Value = PostDeliveryReal),
300+
(print StatisticName = "Failed ZAP / Miss or Uncaught", Value = UncaughtReal),
301+
(print StatisticName = "Phish / Malware Efficacy", Value = Effectiveness)
341302
| project StatisticName, Value
342303
```

0 commit comments

Comments
 (0)