Determine when a user can start sending email again after hitting the 10,000 Recipient Rate Limit in Exchange Online

Scenario: Recently we had a user who hit the 10K Recipient Rate Limit in a 24 hour period within Exchange Online. This user was performing two types of emailing from their ExOnline mailbox: 1. Sending mass mailings from their Mailbox using their from address and 2. Sending mass mailings from their Mailbox and setting another From Address (Delegated Send-as Permissions for a Service Account). Both types of sending impacted the recipient rate limit for the persons mailbox.

BTW – Do not mass mail directly to recipients from an ExOnline mailbox. Instead use distribution groups or other third party mailing systems to send mass communications.

Scriptlet: Here is a scriptlet to help determine when the user should be able to send from their mailbox again. The results provide hourly recipient counts for the sender which may help in determine the timeframe when a user should no longer be impacted by the 24 hour period:

Edit the Variables in the scriptlet and paste it into Exchange Online PowerShell.

#Edit these variables
$sender= “SteveTheMassMailer@domain.com”
$start = “1/7/2021”
$end = “1/9/2021”
$pageSize = 1000
$P = 1
$messages = $null
$report = @()
$totalRecipients = 0

#Loop for All Messages
do
{
Write-Host “Message Trace – Page $P…”
$temp_Messages = Get-MessageTrace -senderaddress $sender -startdate $start -enddate $end -PageSize $pagesize -Page $P
$P++
$Messages += $temp_Messages
}until ($temp_Messages -eq $null)

#Display messages or Message Count
#$Messages
$Messages.count

#Build the Loop Parameters
$Loop_start = get-date($messages | Sort Received | Select -expandproperty Received -First 1) -format “MM/dd/yyyy HH:00:00”
$Loop_end = get-date($messages | Sort Received | Select -expandproperty Received -last 1) -format “MM/dd/yyyy HH:00:00”
$1Hour_end = get-date($Loop_start)
$1Hour_end = $1Hour_end.AddHours(1)
$1Hour_end = get-date($1Hour_end) -format “MM/dd/yyyy HH:00:00”


#Now Loop It!
“Starting Loop for $sender”
Do{
“Checking $Loop_Start and $1Hour_end”
$RecipientCount = $messages | Where {($_.Received -gt $loop_start) -and ($_.Received -lt $1hour_end)} | Select RecipientAddress
$totalrecipients = $totalRecipients + $recipientCount.count
$recipientCount = $RecipientCount.count

#Report it
$obj = New-Object PSObject
$obj | Add-Member NoteProperty -Name StartTime -Value $Loop_Start
$obj | Add-Member NoteProperty -Name EndTime -Value $1hour_End
$obj | Add-Member NoteProperty -Name RecipientCount -Value $RecipientCount
$Report += $obj

#New Variables
$Loop_Start = $1hour_end
$1Hour_end = get-date($Loop_start)
$1Hour_end = $1Hour_end.AddHours(1)
$1Hour_end = get-date($1Hour_end) -format “MM/dd/yyyy HH:00:00”
}While( (get-date($Loop_start)) -lt (Get-date($Loop_End)))

#Summary
$report
“#Summary######################################################”
“-Results are reported in GMT”
“- Total Recipient Count for $Sender between $start – $end : $TotalRecipients”





Microsoft Example of the 24 hour Recipient Rate Limit:
After the recipient rate limit is reached, messages can’t be sent from the mailbox until the number of recipients that were sent messages in the past 24 hours drops below the limit. For example, a user sends an email message to 5000 recipients at 09:00 AM, then sends another message to 2500 recipients at 10:00 AM, and then sends another message to 2500 recipients at 11:00 AM, hitting the limit of 10,000 messages. The user won’t be able to send messages again until 09:00 AM the next day. 






Determine if “Delay Delivery” was used for a message sent

Scenario: You want to determine if a message that you received was sent using “Delay delivery”

Indicators: Below are some indicators to determine if the message was sent using Delay Delivery:

Message Header: (located on any message received by the sender)
Deferred-Delivery – Check for t his property in the Message Header similar to Deferred-Delivery: Mon, 4 Jan 2021 15:36:00 +0000

Email Item Properties: (located only on the sender’s email item located in the sent items)

Outlook Column View: Defer Until, Received, and Sent


MFCMAPI: PR_Message_Delivery_Time, PR_Deferred_Delievery_Time, PR_Deferred_Send_Time


Note: The properties of the test message above show that the message was created at 10:34am EST but delayed delivery until 10:36am EST.

Exchange Online OWA “500 Something went wrong. Repeating redirects detected”

Scenario: When attempting to access Outlook on the Web (OWA), you receive the following error:


Solution: This was a Microsoft issue. Their frontend servers within the Exchange Online environment were erroring out. In our case we were impacted well before the global Microsoft incident/advisory was issued (Ex231181). We did notice that it was the same frontend server being reported in the error details amongst all impacted clients, it just took a while for Microsoft to acknowledge the issue. I did see other articles suggesting it could be Microsoft Admin rights and roles assigned to the user, but in our case these were just normal users that were being impacted.



Windows Security – Select a Certificate window opens when connecting to an Exchange IIS Virtual Directory

Scenario: You notice that when you attempt to connect to a Exchange Servers virtual directory, such as https://<my_exchange_namespace>/autodiscover/autodiscover.xml ,
you receive a prompt similar to this:

Select a Certificate
Site <domain name or server name> needs your credentials>
<Certificates listed to select>


In our case, Autodiscover was not working correctly via DNS lookups, but the SCP record was pulling settings just fine.

Cause: Check the SSL Settings on the Virtual Directory in the Internet Information Services (IIS) Manager. Example: Expand Server –> Sites –> Default Web Site –> select Autodiscover (or whatever the virtual directory giving you an issue is). In the IIS area, select SSL Settings and make sure your certificate is setup to Ignore. You may want to go a hierarchical level higher and make sure the SSL settings are set correctly on the Default Web Site.

Your message wasn’t delivered to anyone because there are too many recipients.

Scenario: A user with a Exchange Online receives the following error: “Your message wasn’t delivered to anyone because there are too many recipients. The limit is 0. Your message has 1 recipients.

Investigation:

In Exchange Online, check the RecipientLimits on the mailbox: get-mailbox steveman | Select RecipientLimits

Fix: If not set correctly, run the following: set-mailbox -recipientlimits 500

———————————————————–

If Hybrid, also check the remote mailbox in Exchange On-Premises: get-remotemailbox steveman | Select RecipientLimits

Fix: If not set correctly, run the following (AD PowerShell):
Set-ADUser steveman -Replace @{msexchRecipLimit=”500″}

Note: There is no set-remotemailbox -recipientlimits, this is why you need to perform this using AD PowerShell

Delegate Permissions to an AD Organizational Unit via PowerShell

Scenario: You want to give Full Control delegate access to a AD Group to a specific AD Organizational Unit and its sub objects.

Scriptlet:

#Add Rights Indiviudally
 $ou = "AD:\OU=New,DC=Domain,DC=Com" 
 $group = Get-ADGroup "Exchange Admins" 
 $sid = new-object System.Security.Principal.SecurityIdentifier $group.SID 
 $acl = get-acl $ou 
 $identity = [System.Security.Principal.IdentityReference] $SID
 $adRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll"
 $type = [System.Security.AccessControl.AccessControlType] "Allow"
 $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All"
 $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType
 $ace = new-object System.DirectoryServices.ActiveDirectoryAccessRule $sid,"GenericAll","Allow","All"
 $acl.AddAccessRule($ace) 
 set-acl -AclObject $acl $ou 

Active Directory: Identify Delegated Permissions for AD Organizational Units

Scenario: You want to pull a report of all delegated permissions to AD Organizational Units.

Scriptlet:

$sourceOU = "OU=NEW,DC=Domain,DC=Com" 
 $OUs = Get-ADOrganizationalUnit -SearchBase $sourceOU -filter * | Select -ExpandProperty DistinguishedName | Sort {$_.length}
 $output = "C:\temp\ace.csv"
 $OUs | %{
     $ou = "AD:\"+$_
     "Checking $OU"
     $acl = get-acl $ou 
     $ace = $acl.access | Where IsInherited -eq $false 
     $ace | Select @{Name="OU";Expression={"$ou"}},ActiveDirectoryRights, InheritanceType,ObjectType,InheritedObjectType,ObjectFlags,AccessControlType,IdentityReference,IsInherited,InheritanceFlags,PropagationFlags | Export-csv $output -append
 }

Active Directory: Copy OU hierarchy from one OU to another OU

Scenario: You want to copy the Sub OU structure/hierarchy from one Parent OU to another Parent OU.

Scriptlet:

#Create OU's
 #Import Module
 import-module activedirectory 
 
#Variables
 $sourceOU = "OU=Old,DC=Domain,DC=com"  
 $destinationOU = "OU=New,DC=Domain,DC=com"  
 $adPath= "LDAP://" + $destinationOU  
 $objDomain=New-Object System.DirectoryServices.DirectoryEntry($adPath)  
 $ObjSearch=New-Object System.DirectoryServices.DirectorySearcher($ObjDomain)  
 [array] $OUs = @() 
 
 #Query for OUs and Exclude an OU if needed
 $OUs = Get-ADOrganizationalUnit -SearchBase $sourceOU -filter * | Where Distinguishedname -notlike "Service" | Select -ExpandProperty DistinguishedName | Sort {$_.length}
 

 #Loop to build the OU Structure
 for ($k=0; $k -le $OUs.Count -1; $k++) 
 { 
     $OriginalOU = $OUs[$k]
     $OriginalOU = "AD:\"+$OriginalOU
    $OUtoCreate = ($OUs[$k] -replace $sourceOU,$destinationOU).ToString()  
     $OUSearch = ($OUtoCreate -replace '"',"").ToString()  
    $ObjSearch.Filter = "(&(objectCategory=organizationalUnit)(distinguishedName="+ $OUSearch + "))"  
    $allSearchResult = $ObjSearch.FindAll()  

    $FinalOU = "AD:\"+$OUtoCreate 

    if ($allSearchResult.Count -eq 1)  
   {      
       "No changes were done on = " + $OUtoCreate  
    }  
    else
    {
      dsadd ou $OUtoCreate
      "OU Creation = " + $OUtoCreate  
    } 
 } 

Perform an action only on the the first email in a email conversation

Scenario: You want to create an action, such as an alert, only when someone sends the first email in a email conversation/thread. However, you DO NOT want to perform that action when someone replies to the initial email.

Scriptlet: You can use an Exchange Transport Rule to detect the first email in a email conversation when the email initiated from within Exchange. Here is the Transport Rule code that will alert another recipient (specifically a page to my cell phone) when someone emails a specific email address. We will use Regex to detect the 32 character value in the Thread-Index header that ends with “==”, which identifies the first email in a conversation thread.

New-TransportRule -name “Perform_Action_On_First_Email” -Enabled $true -HeaderMatchesMessageHeader “Thread-Index” -HeaderMatchesPatterns “^.{30}==$” -RecipientAddressContainsWords servicedesk@domain.com -blindcopyto Page-Steves-Phone@domain.com

Exchange Online: Cached Mode or Online Mode from their Outlook Client

Scenario: Can we identify users that are using Cached Mode or Online Mode from their Outlook client when connecting to their Exchange Online Mailbox via Microsoft Online tools or reporting?

Answer: No – At least not as of today, 11/17/2020.

Microsoft Online currently does not provide this level of detail of connection data for Outlook MAPI connections. In Exchange On-Premises, you had this information stored in RPC logs that could be parsed through. In Exchange Online, we do not have the access.

In order to determine if Cached Mode is enabled for the Outlook client connections, you would need to perform logic on the client initiating the connection.