-
Notifications
You must be signed in to change notification settings - Fork 344
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
174b16e
commit ece9a17
Showing
4 changed files
with
74 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,130 +2,129 @@ | |
|
||
Download the latest release: [ResendFailedMail.ps1](https://github.com/microsoft/CSS-Exchange/releases/latest/download/ResendFailedMail.ps1) | ||
|
||
### Need to be included #### | ||
Use this script to find inconsistencies or redundancies in user membership and policy application of Microsoft Defender for Office 365 and Exchange Online Protection threat policies that lead to missed or unexpected coverage of users by the policy. If issues are found, the script provides guidance on how to resolve them. | ||
Use this script to identify and resend failed emails from Exchange Online. It leverages the Microsoft Exchange Online and Graph Powershell modules to retrieve message IDs, message bodies, and attachments, and resend them using PowerShell. It provides filtering options like sender, recipient, subject, and message ID so you can target only the failed emails you want to resend. | ||
|
||
The script also helps you identify which threat policies cover a particular user, including anti-malware, anti-phishing, inbound and outbound anti-spam, as well as Safe Attachments and Safe Links policies in case these are licensed for your tenant. | ||
The script can help in this type of scenario: | ||
|
||
The script can help with such questions as: | ||
- Your entire tenant has been blocked due to exceeding sending threshold limits, and you have legitimate email that still needs to go out. | ||
|
||
- Are there confusing policies with conditions that lead to unexpected coverage or coverage gaps? | ||
- A user has exceeded the sending limits for Exchange Online, for example, and becomes blocked from sending. | ||
|
||
- Which threat policies apply to a recipient, **or should have applied** but did not? **No actual detection or Network Message ID needed.** | ||
- After the problem is mitigated and the sender or tenant is unblocked, you need to resend some legitimate outbound or internal emails. | ||
|
||
- Which actions would be taken on an email for each policy matched? | ||
- Exchange Online will not do this automatically nor has any tools to do it that do not require scripting. This script will help you do that easily. | ||
|
||
The script runs only in Read mode from Exchange Online and Microsoft Graph PowerShell. It does not modify any policies, and only provides actionable guidance for administrators for remediation. | ||
> [!IMPORTANT] | ||
> The script can only be used to send email that is currently in a mailbox to the originally intended recipients, and it cannot be used to redirect email to a different recipient. | ||
## Prerequisites | ||
The script uses Powershell cmdlets from the Exchange Online module and from the Microsoft.Graph.Authentication, Microsoft.Graph.Groups, and Microsoft.Graph.Users modules. | ||
Before running this script, ensure you meet the following prerequisites: | ||
|
||
To run the Graph cmdlets used in this script, you only need the following modules from the Microsoft.Graph PowerShell SDK: | ||
1. The Exchange Online Powershell module must be installed to retrieve the failed message IDs. | ||
|
||
- Microsoft.Graph.Groups: for managing groups, including `Get-MgGroup` and `Get-MgGroupMember`. | ||
2. The `Microsoft.Graph.Authentication`, `Microsoft.Graph.Mail`, and `Microsoft.Graph.Users.Actions` modules must be installed to read and send emails. | ||
|
||
- Microsoft.Graph.Users: for managing users, such as `Get-MgUser`. | ||
|
||
- Microsoft.Graph.Authentication: for authentication purposes and to run any cmdlet that interacts with Microsoft Graph. | ||
|
||
You can find the Microsoft Graph modules in the following link:<br> | ||
https://www.powershellgallery.com/packages/Microsoft.Graph/<br> | ||
|
||
https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0#installation | ||
|
||
|
||
Here's how you can install the required submodules for the PowerShell Graph SDK cmdlets: | ||
- Here's how you can install the required modules/submodules: | ||
|
||
```powershell | ||
Install-Module -Name Microsoft.Graph.Authentication -Scope CurrentUser | ||
Install-Module -Name Microsoft.Graph.Groups -Scope CurrentUser | ||
Install-Module -Name Microsoft.Graph.Users -Scope CurrentUser | ||
Install-Module -Name ExchangeOnlineManagement | ||
Install-Module -Name Microsoft.Graph.Authentication | ||
Install-Module -Name Microsoft.Graph.Users.Actions | ||
Install-Module -Name Microsoft.Graph.Mail | ||
``` | ||
|
||
!!! warning "NOTE" | ||
3. An App must be registered in Azure Active Directory to interact with the Microsoft Graph API specifically to run this script. | ||
|
||
Remember to run these commands in a PowerShell session with the appropriate permissions. The -Scope CurrentUser parameter installs the modules for the current user only, which doesn't require administrative privileges. | ||
- You can register a Microsoft Azure app in your tenant here: <br>https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade | ||
|
||
- Click **New registration**. | ||
- Provide a name and account type. | ||
- **Redirect URI** can be left blank. | ||
|
||
In the Graph connection, you will need the following scopes 'Group.Read.All','User.Read.All'<br> | ||
```powershell | ||
Connect-MgGraph -Scopes 'Group.Read.All','User.Read.All' | ||
``` | ||
<br><br> | ||
You also need an Exchange Online session.<br> | ||
```powershell | ||
Connect-ExchangeOnline | ||
``` | ||
- Assign permissions: | ||
- Under **Manage | API permissions** for the app, click **Add a permission**. | ||
- Select **Microsoft Graph**. | ||
- Select the **Application permission** type. | ||
- Search for and select the following permissions: | ||
- **Mail.Read** (Application) | ||
- **Mail.Send** (Application) | ||
- Grant admin consent for your tenant for both the permissions. | ||
|
||
You can find the Exchange module and information in the following links:<br> | ||
https://learn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps<br> | ||
https://www.powershellgallery.com/packages/ExchangeOnlineManagement | ||
- When created, the API permissions should look like this:<br> | ||
|
||
!['No Logical inconsistencies found'](img/API-perms.png) | ||
|
||
## Parameters and Use Cases: | ||
Run the script without any parameters to review all threat protection policies and to find inconsistencies with user inclusion and/or exclusion conditions: | ||
- Create a new client secret for the app under `Manage | Certificates & secrets`. | ||
|
||
> [!IMPORTANT] | ||
> Save the Value field of the secret **immediately** after creating it; you can't retrieve it later. | ||
!['No Logical inconsistencies found'](img/No-Logical-Inconsistencies.png) | ||
> [!TIP] | ||
> Customize the duration of the secret to expire soon if you don't expect to use the app for an extended period. | ||
**Script Output 1: No logical inconsistencies found** message if the policies are configured correctly, and no further corrections are required. | ||
- Use the `client_id`, `tenant_id`, and `client_secret` obtained during app registration to authenticate with Microsoft Graph in the script (connection instructions below). | ||
|
||
![Potentially illogical inclusions found.](img/Logical-Inconsistency-Found.png) | ||
<br><br> | ||
4. After completion of the above steps, and before running the script, connect to Exchange Online and Graph API with Powershell, as follows - make sure to insert your values into the connection string for Graph: | ||
|
||
**Script Output 2: Logical inconsistencies found**. Inconsistencies found in the antispam policy named 'Custom antispam policy', and consequent recommendations shown -- illogical inclusions as both users and groups are specified. This policy will only apply to the users who are also members of the specified group. | ||
```powershell | ||
Connect-ExchangeOnline -ShowBanner:$false | ||
- IncludeMDOPolicies | ||
Connect-MgGraph -TenantId "[YOUR TENANT ID HERE]" -ClientSecretCredential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "[YOUR APP ID HERE]", (ConvertTo-SecureString -String "[VALUE FIELD OF YOUR SECRET HERE]" -AsPlainText -Force)) -NoWelcome | ||
``` | ||
|
||
Add the parameter -IncludeMDOPolicies to view Microsoft Defender for Office 365 Safe Links and Safe Attachments policies: | ||
You can find the Microsoft Graph modules in the following link:<br> | ||
https://www.powershellgallery.com/packages/Microsoft.Graph/<br> | ||
|
||
![Policies, including MDO.](img/Show-Policies-Including-MDO.png) | ||
https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0#installation | ||
|
||
**Script Output 3: Parameters -EmailAddress and -IncludeMDOPoliciesEOP** specified to validate Microsoft Defender for Office 365 Safe Attachments and Safe Links policies, on top of Exchange Online Protection policies. | ||
|
||
- ShowDetailedPolicies | ||
You can find the Exchange module and information in the following links:<br> | ||
https://learn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps<br> | ||
https://www.powershellgallery.com/packages/ExchangeOnlineManagement | ||
<br><br> | ||
|
||
To see policy details, run the script with the -ShowDetailedPolicies parameter: | ||
## Parameters and Use Cases: | ||
Run the script with the Days parameter to specify the number of days in the past to retrieve email with a **Failed** status as well as with the Sender parameter. You will be prompted before executing this command. | ||
|
||
![Show policy actions.](img/Show-Detailed-Policies-1.png) | ||
> [!IMPORTANT] | ||
> Make sure the original cause of the failed sending is fixed, or the script will also fail to send it. | ||
![Show policy actions.](img/Show-Detailed-Policies-2.png) | ||
!['No Logical inconsistencies found'](img/ResendFailedMail-4Days+Sender.png) | ||
|
||
![Show policy actions.](img/Show-Detailed-Policies-3.png) | ||
**Script Output 1: Resending Last 4 Days of Failed Email from Specific Sender** | ||
|
||
![Show policy actions.](img/Show-Detailed-Policies-4.png) | ||
<br><br> | ||
Run the script with no parameters to resend all Failed email from the past day. | ||
|
||
**Script Output 4: Policy actions**. Use -ShowDetailedPolicies to see the details and actions for each policy. | ||
!['No Logical inconsistencies found'](img/ResendFailedMail-No_Params.png) | ||
|
||
## Additional examples | ||
**Script Output 2: Default Execution of Script with No Parameters** | ||
|
||
To provide multiple email addresses by command line and see only EOP policies, run the following:<br> | ||
```powershell | ||
.\MDOThreatPolicyChecker.ps1 -EmailAddress [email protected],[email protected] | ||
``` | ||
|
||
To provide a CSV input file with email addresses and see both EOP and MDO policies, run the following:<br> | ||
```powershell | ||
.\MDOThreatPolicyChecker.ps1 -CsvFilePath [Path\filename.csv] -IncludeMDOPolicies | ||
``` | ||
## Additional examples | ||
|
||
To provide an email address and see only MDO (Safe Attachment and Safe Links) policies, run the following:<br> | ||
To resend email from specific sender, recipient, and number of days, run the following:<br> | ||
```powershell | ||
.\MDOThreatPolicyChecker.ps1 -EmailAddress user1@contoso.com -OnlyMDOPolicies | ||
.\ResendFailedMail.ps1 -Sender gary@contoso.com -Recipient [email protected] -Days 7 | ||
``` | ||
|
||
To get all mailboxes in your tenant and print out their EOP and MDO policies, run the following:<br> | ||
To resend email from a specific sender for the past 5 days without a confirmation prompt, run the following:<br> | ||
```powershell | ||
.\MDOThreatPolicyChecker.ps1 -IncludeMDOPolicies -EmailAddress @(Get-ExOMailbox -ResultSize unlimited | Select-Object -ExpandProperty PrimarySmtpAddress) | ||
.\ResendFailedMail.ps1 -Force -Sender [email protected] -Days 5 | ||
``` | ||
|
||
## Parameters | ||
## Parameters - all parameters are optional | ||
|
||
Parameter | Description | | ||
----------|-------------| | ||
CsvFilePath | Allows you to specify a CSV file with a list of email addresses to check. Csv file must include a first line with header Email. | ||
EmailAddress | Allows you to specify email address or multiple addresses separated by commas. | ||
IncludeMDOPolicies | Checks both EOP and MDO (Safe Attachment and Safe Links) policies for user(s) specified in the CSV file or EmailAddress parameter. | ||
OnlyMDOPolicies | Checks only MDO (Safe Attachment and Safe Links) policies for user(s) specified in the CSV file or EmailAddress parameter. | ||
ShowDetailedPolicies | In addition to the policy applied, show any policy details that are set to True, On, or not blank. | ||
Sender | Filter emails based on the sender's address. | ||
Recipient | Filter emails based on the recipient's address. | ||
Subject | Filter emails based on the email Subject. | ||
MessageId | Filter emails based on the MessageId address. **You must put the MessageId in double quotes** | ||
Days | Resend emails that failed within the past X number of days. Default is 1 day. | ||
Force | Sends emails without confirmation prompt. | ||
IncludeDuplicate | Will resend all emails with the same Message Id. | ||
SkipConnectionCheck | Skips connection check for Graph and Exchange Online. | ||
SkipVersionCheck | Skips the version check of the script. | ||
ScriptUpdateOnly | Just updates script version to latest one. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.