Check for Autodiscover ServiceBindingInformation during the installation of Exchange — This way you can be alerted when the property is configured, and we can $Null it out.

Scenario: We are installing Exchange On-Premises on some new servers, and we want to minimize the amount of Security Alerts that pop up on users Outlook connections. The Security Alerts pop up because we do not put the servername on the public certificates AND Exchange wants to configure the autodiscover record with https://<local server name>/autodiscover/autodiscover.xml — silly Microsoft.

Solution: During the Exchange Installation, run the following scriptlet to loop through and beep/display when it is there, so you can go in and null it out in ADSI edit (or Exchange if it allows you).


You can find the exact $AD property by locating the DN of the server by navigating through the ADSIEdit Configuration (working your way backwards from the AD property below) and copying it.

$s = "ExServer21"
$ad = "CN=$s,CN=Autodiscover,CN=Protocols,CN=$S,CN=Servers,CN=Exchange Administrative Group,CN=Administrative Groups,CN=Enterprise Exchange,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=com"

#Loop It

$1 = Get-ADObject $AD -properties * |Select -expandproperty ServiceBindingInformation
"Checking $s for Service Binding Information...."
If($1 -ne $null){ 
    "ServiceBindingInfomation: $1"}
Sleep 5
}While($C -ne "RunForever")

You could also run set-clientaccessserver <servername> -AutodiscoverServiceInternalUri $null


Scriptlets to check Recent Windows and Exchange updates/patches

Scenario: You have just updated your Exchange Servers (or Windows Servers) and you want to verify the successful install of the patches through logic.


#Pull a list of Servers
   $Servers = get-exchangeserver |sort name| Select -ExpandProperty Name 
   $servers = "ExServer1","ExServer2"
#Pull Updates
   $Ex_Updates = @(); $servers | %{$n = $_; "Checking Exchange File for $n"; $Ex_Updates+= Invoke-Command -ComputerName $n -ScriptBlock {GCM exsetup |%{$_.Fileversioninfo}}}
   $Win_Updates = @(); $servers | %{$n = $_; "Checking Windows Updates for $n"; $Win_Updates+= Get-HotFix -ComputerName $n |Where InstalledOn -ge (get-date).AddDays(-7) | Select @{Name="Server";Expression={$n}}, Description, HotFixID, InstalledOn }
#Display variables of updates

    #Note: You can group to make it easier to quickly identify everything looks right
    $Win_Updates |Group Hotfixid
    $Win_Updates |Group server 

Windows – Unable to join domain. “An account with the same name exists in Active Directory. Re-using the account was blocked by security policy”

Scenario: The error below was received when joining a new computer to a domain (the computer object was pre-staged in AD by creating the computer object and resetting it).

Error: “An account with the same name exists in Active Directory. Re-using the account was blocked by security policy”

Solution: Add the following Reg Key:

Reg add HKLM\System\CurrentControlSet\Control\Lsa /v NetJoinLegacyAccountReuse /t REG_DWORD /d 1 /f

Error: 450 4.4.317 Cannot connect to remote server – 451 5.7.3 STARTTLS is required to send mail

Scenario: When attempting to send email from Exchange Online to Exchange On-Premises via Hybrid connectors, Exchange Online receives the following error message with a Defer Event: LED=450 4.4.317 Cannot connect to remote server [Message=451 5.7.3 STARTTLS is required to send mail]

This error means is that a certificate that supports TLS is present on the receiving (Exchange On-Premises) server, EXCEPT it cannot build a TLS connection because of an invalid configuration.

Solution: In our case, a new certificate that was recently installed on the Exchange On-Premises Server had a different TLS Certificate Name than what was configured on the Receive Connector. Setting the ‘TLSCertificateName’ on the receive connector with the NEW Certificate fixed the issue.

#Pull the Certificate
$Cert = Get-ExchangeCertificate -Thumbprint "<Thumbprint of server with SMTP Service>"

#Build the TLSCert String that will be used to compare and set
$TLSCert = (‘<I>’+$cert.issuer+'<S>’+$cert.subject)

#Check and compare the TLSCertificateName on the Receive Connector with $TLSCert
Get-ReceiveConnector "<Servername>\Default Frontend <Servername>" | Select TLSCertificateName

#If the CertName is different, set the Receive Connector with $TLSCert
Get-ReceiveConnector "<Servername>\Default Frontend <Servername>" | Set-ReceiveConnector -TlsCertificateName $TLSCert

Renewing Certificate in a Hybrid Exchange On-Premises Environment (Concern of the SMTP Service)

Scenario: The third-party certificate is expiring and needs to be renewed on multiple Exchange On-Premises server that hosts IIS, SMTP, POP, and IMAP. There is concern about the hybrid components for successful SMTP Routing between Exchange On-Premises and Exchange Online since we are moving the SMTP Service to a different certificate.

Solution: The components below will walk you through creating the renewal and the components to look at:

1. Create a Cert request off of the expiring Cert Req (and then hand off to third party cert provider)

$ExpiringCert = "<thumbprint of cert>"
$Req = "\\ExServer\c$\temp\cert\CertRenewal.req"
$Server = "ExServer"

#Run the command to get the .req
$txtrequest = Get-ExchangeCertificate -Thumbprint $ExpiringCert -server $Server | New-ExchangeCertificate -GenerateRequest -privatekeyexportable:$true

[System.IO.File]::WriteAllBytes($req, [System.Text.Encoding]::Unicode.GetBytes($txtrequest))

2. Complete the Pending Exchange Server Request (After downloading the cert from the third party vendor)

$server = "ExServer"
$Renewed_Cert = "\\ExServer\c$\temp\cert\NewCert.crt"
Import-ExchangeCertificate -FileData ([System.IO.File]::ReadAllBytes($Renewed_Cert))  -Server $Server  -privatekeyexportable:$true 

3. Export the new cert (pfx) package so it contains the private and public key/components

$c = "<new cert thumbprint"
$Password = "Batman"
$PFX =  "\\ExServer\c$\temp\cert\NewCert.pfx"
$server = "ExServer"

$cert = Export-ExchangeCertificate -Thumbprint $c -BinaryEncoded -Password (ConvertTo-SecureString -String $Password -AsPlainText -Force) -server $server
[System.IO.File]::WriteAllBytes($PFX, $cert.FileData)

4. Import the Certificate onto multiple servers

$ExchangeServers = get-exchangeserver
$Password = "Batman"
$ | %{
"Running on $_"
Import-ExchangeCertificate -FileData ([System.IO.File]::ReadAllBytes($PFX)) -Password (ConvertTo-SecureString -String $Password -AsPlainText -Force) -server $_

5. Moving Services

      $New_Thumbprint = "<new cert thumbprint>"
      $ExchangeServers = Get-exchangeserver

 #Enable the IMAP,POP,IIS,and SMTP Services to the new cert
 $ | %{
     "Enabling Services on $_"
     Enable-Exchangecertificate -thumbprint $New_Thumbprint -server $_ -services IMAP,POP,IIS,SMTP -confirm:$false -force

6. Restarting Each Service

$ExchangeServers = Get-exchangeserver      

#Restart the Services for IIS, IMAP, POP, and SMTP 
$ | %{
   "Restarting IIS on $_"
   iisreset $_

   "Restarting MSExchangeTransport on $_"
   Get-Service msexchangetransport -ComputerName $_ | Restart-service

   "Restarting IMAP and POP on $_"
   Get-Service msexchangeimap* -ComputerName $_ | Restart-service
   Get-Service msexchangepop* -ComputerName $_ | Restart-service

7. Check Outbound Connector in Exchange Online

#Notes: Our Subjectname didnt change, so we didnt have to do anything here

#Validate "Outbound_To_OnPremises" is configured with the subjectname in the Certificate/SAN

#Log into EAC --> Mail Flow --> Connectors --> Select the "<Outbound_To_OnPremises>" connector --> Edit "Security Restrictions" section if necessary.  The value should reflect a domain name or another identifiable piece of info in the new cert'.

8. Check Exchange On-Premises Receive Connectors

#Notes: We had to fix this one because the new $TLSCert was different than the TLSCertificateName on each Receive Connector; each connector still referenced the original cert.  Fixed by:  Set-ReceiveConnector "$_\Default Frontend $_" -tlsCertificateName $TLSCert

$New_Thumbprint = "<new cert thumbprint>"
$New_Cert = Get-ExchangeCertificate -Thumbprint $New_Thumbprint -server "ExServer"
$TLSCert = (‘<I>’+$cert.issuer+'<S>’+$cert.subject)
$ReceiveConnectors = @()

#Check the TLSCertificateName on all Receive Connectors and compare to $TLSCert
$ | %{$ReceiveConnectors += Get-ReceiveConnector "$_\Default Frontend $_" | Select Identity, TLSCertificateName}

#To fix:    
$ | %{Set-ReceiveConnector "$_\Default Frontend $_" -tlsCertificateName $TLSCert}

9. Check the Exchange On-Premises Transport Service

#Notes: This should be done automatically

$ExchangeServers = Get-exchangeserver   
$TransportService_Cert = @()

#$ | %{$TransportService_Cert +=  get-transportservice $_  |Select Name,InternalTransportCertificateThumbprint}; $TransportService_Cert

10. Check the Exchange On-Premises Hybrid Send Connector “<Outbound to Office 365>”

#Notes: You may need to set this

$SC = "Outbound to Office 365"
$New_Thumbprint = "new cert thumbprint"
$New_Cert = Get-ExchangeCertificate -Thumbprint $New_Thumbprint -server "ExServer"
$New_TLSCertificateName = (‘<I>’+$New_Cert.issuer+'<S>’+$New_cert.subject)

#Verify the TLSCertificateName on the SendConnector
$SendConnector_TLSCertificateName = Get-SendConnector -identity  $SC | Select TLSCertificateName

#Does the $SendConnector_TLSCertificateName match the NEW_TLSCertificateName? If Not, you may need to run the following:
Set-SendConnector "Outbound to Office 365"  -TlsCertificateName $New_TLSCertificateName

11. Check the ExOnline Inbound Connector “Inbound from …”

#Notes: We did need to fix this

$New_Thumbprint = "<thumbprint of new cert>"
$New_Cert = Get-ExchangeCertificate -Thumbprint $New_Thumbprint -server "ExServer"
$New_TLSCertificateName = (‘<I>’+$New_Cert.issuer+'<S>’+$New_cert.subject)

#Set the Inbound Connector with the $New_TLSCertificateName value of the new Cert
  #Connect to Exchange Online PowerShell or the EAC GUI
  #If PowerSHell:
        $ExOnline_TLSSenderCertificateName = Get-InboundConnector "Inbound from ..." | Select TLSSenderCertificateName

#If GUI: Log into EAC --> Mail Flow --> Connectors --> Select the "Inbound from ..." connector --> Edit the "How to identify email sent from your email server" section. 

#To Fix:
#PowerShell: set-InboundConnector "Inbound from ..." -TlsSenderCertificateName $New_TLSCertificateName
#EAC:  Edit the "How to identify email sent from your email server" section with the #New_TLSCertificateNameValue

Purge emails from a mailbox that are protected by a Organizational Hold

Scenario: You need to remove messages from a mailbox, but the mailbox is protected under an Organizational Hold (but it could also be a LitHold or a InPlaceHold). Since the message is currently protected, it will not purge out of the mailbox until the hold is expired, or ever, depending on what type of hold is on the mailbox.


1. Disable the Hold:
You need to remove the mailbox from the Hold. If its an Organizational hold, add them to the exclusion. If its a LitHold or InPlace Hold, disable the hold.

get-mailbox steveman | Select *hold*
get-organizationconfig | Select *Hold*

2. Get the message to the Purges Folder:
Move the email items into the Purges folder. You can do this by any one of the following:

Manual Purging: Deleting the message from the mailbox within the client, then ‘deleting ‘purge’ the message from the Recoverable Deleted Items (Deletions folder).

Search Mailbox – You could use search-mailbox with -deletecontent -force.

New-ComplianceSearch & New-ComplianceSearchAction : You could use a new-compliancesearch with a new-compliancesearchaction -purge -purgetype HardDelete.

MFCMAPI: You could use MFCMAPI to move the message directly to the purges folder.

3. Disable SingleItemRecovery and RetainDeletedItemsFor:
Run the following:
set-mailbox steveman -singleitemrecoveryenabled:$false – retaindeleteditemsfor 0.00:00:00

4. Start the Mailbox Folder Assistant:
start-mailboxfolderassistant steveman

Note: For steps 3 and 4, give time in between the steps for Replication and settings to go into effect.

Error: Couldn’t find unique request with the provided information when get-mailboxexportrequest

Scenario: When running a get-mailboxexportrequest (or get-mailboximportrequest, remove-mailboxexportrequest, or remove-mailboximportrequest) you get the following error:

Couldn’t find a unique request with the provided information.

This is a result of running two separate mailbox export requests on the same mailbox, and Exchange didn’t create a unique name for each of the export request jobs. Therefore it creates a duplicate entry and Exchange hates you — just kidding.

Solution: If you need to cancel a duplicate export or import request, you can use the RequestGUID and RequestQueue to help identify the unique entry of a duplicate request, a true oxymoron.

get-mailboxexportrequest | Select Identity, name, RequestGuid, RequestQueue

Remove-mailboxexportrequest -RequestGuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -RequestQueue DBxxxx

Configure a Distribution Group to send a reply message every time (Not an Out-of-Office Message)

Scenario: You need a distribution group to send a ‘specific’ reply message back to the sender, every time a sender sends to it. An Out-of-Office message will not do because it will only send a reply one time.

Note: Distribution Groups do not have this functionality, however there is a work around with using a shared mailbox.

1. Create a Shared Mailbox that will host sending the reply messages. We will call it:

2. Log into an Outlook client as the shared mailbox and create the following inbox rule:

“Apply this rule after the message arrives
have server reply using “blah blah blah

3. Even though this is a Inbox Rule, set your Distribution Group so it allows sending Out-of-Office (OOF) messages which is turned off by default. This is required for return messages:

Set-DistributionGroup -SendOofMessageToOriginatorEnabled:$true

4. Create a Transport Rule OR add that shared mailbox to your distribution list. I chose the Transport Rule because it is cleaner to the end users — they wont start asking questions about this new account. We are using the AnyOfToCCHeader to trigger the rule if it the Distribution list is sent to.

New-TransportRule -name “BCC_Reply” -AnyOfToCCHeader -blindcopyto

Mailbox Dumpster (aka TotalDeletedItemSize aka RecoverableItems) hit the 100GB size quota due to a bloated recurring meeting

Scenario: You have a mailbox that is similar to the following scenario:

-On a Hold: A mailbox is protected by a hold such as a Litigation Hold, eDiscovery/In-Place Hold, SCC Compliance Hold, etc.

-Hit the Quota: The mailbox has either already hit, or is approaching, the mailbox dumpster 100GB quota

-Item Count to Size Ratio doesnt make sense, at first: When you run the following command you notice that there are very few items in the folder that is at or near the quota — it would seem that the item count and folder size doesn’t make sense for 200 items to equal 99GB. Command: get-mailboxfolderstatistics <name> -folderscope recoverable | Select Name, ItemsInFolder, FolderSize

-Symptoms experienced by the user: Users have a issue deleting email items OR may experience issues with calendaring events.

Investigation: We discovered that there is a long-lasting recurring meeting that the impacted user/mailbox was an attendee for. The organizer of the meeting would edit single occurrences of the meeting series to post meeting agendas and attachments (this is where the size bloat comes from). It appears there is a conflict with this user being on a hold, and retaining a collective buildup of all edited occurrences of the meeting series. There was around 200 individual meeting ocurrences of thise meeting series, and each item is now ballooned in size to just under 200MB each. This contributes to the size of the dumpster folder, and the overall dumpster quota.

Solution: There is a command that we can run that will cleanup all the duplicate calendar items in the dumpster, even when a mailbox is on a Hold:

start-managedfolderassistant <name> -holdcleanup.

However, in our scenario the email items lived in the Purges recoverable items folder and the command did not work in that folder. Using MFCMapi we had to do a Move (in MFCMapi language a Copy –> Paste with the move option selected) and put all those items into the Versions folder. When the messages were moved into the Versions folder, the command worked and within the hour all the duplicate messages that were ballooned in size were now gone AND the dumpster was well under quota.

Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send

Scenario:  You receive the following error when you attempt to Invoke-WebRequest from PowerShell:
Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.

Solution: Run the following in PowerShell to make sure it uses TLS1.2

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12