Powershell: List all mailbox folder delegate access for a mailbox

Scenario: You want to determine all mailbox folder delegate access for a mailbox. You wish to not include the anonymous and default permissions.

Script:

$mbx = "steve"
$permissions = @()
$Folders = Get-MailboxFolderStatistics $mbx | % {$_.folderpath} | % {$_.replace(“/”,””)}
$list = ForEach ($F in $Folders)
   {
    $FolderKey = $mbx + ":" + $F
    $Permissions += Get-MailboxFolderPermission -identity $FolderKey -ErrorAction SilentlyContinue | Where-Object {$_.User -notlike “Default” -and $_.User -notlike “Anonymous” -and $_.AccessRights -notlike “None”}
   }
$permissions

EWS Script: Monitor EWS is working properly by querying for an email item on a timely basis

Scenario:  After your frontend client access gateway has crashed a couple of times, you would like to test that your frontend client access gateway continues to work properly for EWS. You would like an EWS script to validate that not only can it login to a mailbox, but it can query for a specific item in the mailbox.   If it cannot query for the email item in the mailbox, then you want to be notified.

Script:

  1. First create a mailbox that you will monitor.
  2. Send an email to that mailbox so you can query that email by the subject line.

Create your Variables:

#Mailbox Variables
$MailboxName = "EWSMonitor@Domain.com #Mailbox to Query
$Subject = "EWS Test" #Message to query


#Script Variables
$cred1 = get-credential  #This account has access to the mailbox
$Counter = 0 #If you want the counter to stop after # of loops
$sleep = 600 #10 minutes
$EndLoop = "Run Forever" #Set as value so it stops in a timely manor


#Email Variables
[string[]]$to = "steve@domain.com","billy@domain.com"
$smtp = "mail.domain.com"
$from = "EWS_Monitor@domain.com"
$subject1 = "EWS FAILURE" 


The Looping Script

#Loop#############################################
Do{
    $miMailItems = $null
    "Starting Loop"
    $Counter++
    #Connect to EWS
    Import-Module -Name "C:Program FilesMicrosoftExchange ServerV15BinMicrosoft.Exchange.WebServices.dll"
    $service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.Exchangeversion]::exchange2013)
    $service.Url = new-object System.Uri("https://email.domain.com/EWS/Exchange.asmx")
    $service.UseDefaultCredentials = $false
    $service.Credentials = $cred1.GetNetworkCredential()
    #Attach to Inbox
    $folderidInbox = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
    $InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderidInbox)
    #Search Filter
    $Sfsub = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, $Subject)
    $sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
    #Build your Search Collection
    $sfCollection.add($Sfsub)
    $view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000000)
    $miMailItems = $InboxFolder.FindItems($sfCollection,$view)
    "Found MailItem in StaciATest = $($MiMailItems.count)"
    If($MiMailItems.count -NE 1){      
        "MailItem Count -eq Null, Sending Message"
        send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject1 -Priority high
         }
   "Sleeping $Sleep"
    Sleep $sleep
}While($Counter -ne $EndLoop)
#####################################################################################

 

 

 

Remotely configure a certificate after importing the new certificate to your Exchange Servers

Scenario:  You imported a new certificate to your Exchange servers and you want to configure the certificate on each server remotely.  There is OWA/LYNC integration and the thumbprint of the older certificate needs to be updated with the thumbprint of the new certificate for the IMCertificateThumbprint property in each servers OWA web.config file.

Scriptlets:

Declare your variables for the Servers and for the thumbprints of the Old and New Cert.

#Declare Variables
$OldCert = "B8FE4323EEdAAB31258C2F44283001004EEACB23"
$NewCert = "A8E457DE801F7831317C2F5F5450007EA238DDE3"
$Servers = Get-exchangeserver Ex* | Select -ExpandProperty Name

We are going to backup the web.config file as well in the event of a mistake.

#Backup Web.Config and Save it locally
$Servers | %{
"Copying $_"
MD C:TempWebConfig$_
Copy-item "\$_c$Program FilesMicrosoftExchange ServerV15ClientAccessOwaweb.config" "C:TempWebConfig$_"
}

Because OWA/LYNC integrations exists, we need to modify the IMCertificateThumbprint OWA Web.Config file so it updates/overwrites the old thumbprint with the new thumbprint.

#Edit the Web.Config on each Server
$Servers | Sort | %{
"Editing WebConfig for $_"
$WebConfigFile = "\$_c$Program FilesMicrosoftExchange ServerV15ClientAccessOwaweb.config"
(Get-Content $webconfigfile).replace('$OldCert', 'NewCert') | Set-Content $Webconfigfile
}

Enable the Services on the new Certificate

#Enable UM, IIS, SMTP, UMCallRouter on new Cert
$Servers | %{
Enable-ExchangeCertificate -Server $_ -thumbprint $NewCert -services IIS,SMTP,UM,UMCallRouter -force -confirm:$false
}

Finally, Restart IIS & UM Services on each server

#Restart IIS & UM Services
$Servers | %{
iisreset $_
get-service msexchangeUM* -computername $_ | Restart-service
}

 

PowerShell: Search Multiple servers to see if a specific program is installed

Scenario:  You want to quickly search multiple remote servers to see if a specific program is installed.

Script: The following script checks to see if Wireshark is installed on any of our Exchange servers.

#Declare Server Variable
$Ex2013 = Get-exchangeserver ex* | Select -expandproperty Name

#Perform the Query against each server
$Ex2013 | %{"Checking WireShark on $_";Invoke-Command -Computer $_ -ScriptBlock {

#Declare App
$appToMatch = '*Wireshark*'

#Determine Uninstall Directory
if ([IntPtr]::Size -eq 4) {
        $regpath = 'HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall*'
    } else {
        $regpath = @(
            'HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall*'
            'HKLM:SoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall*'
        )
    }

#Get all Programs Installed
$1 = Get-ItemProperty $regpath | .{process{if($_.DisplayName -and $_.UninstallString) { $_ } }} | Select DisplayName, Publisher, InstallDate, DisplayVersion, UninstallString |Sort DisplayName

#Filter based on program
$result = $1 | where {$_.DisplayName -like $appToMatch}

#Display the result if found
If($result -ne $null){
    Write-Host "
    The following matching $appToMatch are Installed on $($env:computername) " -ForegroundColor Yellow
    Write-Host "$($result.displayName)
    " -ForegroundColor Yellow
}
 }}

PowerShell Script-lets to install Prerequisites for Exchange 2016 Remotely

Scenario: You want a script to install the Prerequisites for Exchange 2016 on Windows Server 2016.  Here is a few of the PowerShell commands we ran remotely for each server.

 

Gather your Servers

#Collect Servers into a Variable
$strOU = "OU=Exchange2016,DC=XYZ,DC=COM"
$servers = get-adcomputer -searchbase $strOU -properties Name -Filter *|  where {$_.name -like "Ex16-*"} | Select -ExpandProperty Name

Turn off the Windows Firewall  (We kept our Firewall turned on with multiple rules, but incase you need to disable it this is how you do it)

#turn off Windows Firewall
$servers | %{"Turning Windows Firewall off on $_";Invoke-Command -Computer $_ -ScriptBlock {Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False}}

Place all Installer Files (C:sharesoftware) into a folder and copy them to each server under C:Software.

#MD
$servers | %{MD \$_c$software}

#Copy Files to a Server -  Put all Setup files you wish to install in this directory and copy to the server.
$servers | %{"Copying files to $_";Copy-Item C:sharesoftware* \$_C$software}

Disable User Account Control

#Disable UserAccountControl on a Server
$servers | %{"Disable UserAccountControl on $_"; Invoke-Command -Computer $_ -ScriptBlock {New-ItemProperty -Path HKLM:SoftwareMicrosoftWindowsCurrentVersionpoliciessystem -Name EnableLUA -PropertyType DWord -Value 0 -Force}}

Install Windows Features

#Install Windows Features
$servers | Sort | %{"Installing Windows Features on $_"; Invoke-Command -Computer $_ -ScriptBlock {Install-WindowsFeature NET-Framework-45-Features, RPC-over-HTTP-proxy, RSAT-Clustering, RSAT-Clustering-CmdInterface, RSAT-Clustering-Mgmt, RSAT-Clustering-PowerShell, Web-Mgmt-Console, WAS-Process-Model, Web-Asp-Net45, Web-Basic-Auth, Web-Client-Auth, Web-Digest-Auth, Web-Dir-Browsing, Web-Dyn-Compression, Web-Http-Errors, Web-Http-Logging, Web-Http-Redirect, Web-Http-Tracing, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Lgcy-Mgmt-Console, Web-Metabase, Web-Mgmt-Console, Web-Mgmt-Service, Web-Net-Ext45, Web-Request-Monitor, Web-Server, Web-Stat-Compression, Web-Static-Content, Web-Windows-Auth, Web-WMI, Windows-Identity-Foundation,RSAT-ADDS}}

Set the Page File Size to 32GB

#Setting Page File Size on Servers
    $servers | %{"Setting Page File Size on $_"; Invoke-Command -Computer $_ -ScriptBlock {
    [int]$InitialSize = 32778
    [int]$MaximumSize = 32778
    $ComputerSystem = $null
    $CurrentPageFile = $null
    $modify = $false
    $ComputerSystem = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges
    if ($ComputerSystem.AutomaticManagedPagefile) {$ComputerSystem.AutomaticManagedPagefile = $false; $ComputerSystem.Put()}
    $CurrentPageFile = Get-WmiObject -Class Win32_PageFileSetting
    if ($CurrentPageFile.InitialSize -ne $InitialSize) {$CurrentPageFile.InitialSize = $InitialSize;$modify = $true}
    if ($CurrentPageFile.MaximumSize -ne $MaximumSize) {$CurrentPageFile.MaximumSize = $MaximumSize;$modify = $true}
    if ($modify) { $CurrentPageFile.Put()}
    }}

Install Unified Communications Managed API Runtime. The installer was renamed to UCMA.exe.

    
#Install Unified Communications Managed API Runtime silently
$servers | %{"Installing UCMA on $_"; Invoke-Command -Computer $_ -ScriptBlock {
    #Set Variables
    $file = "C:softwareUcma.exe" 
    #check to see if its installed
    if (Get-ItemProperty "HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstallUCMA4" -ErrorAction SilentlyContinue) { 
        Write-host "Unified Communications Managed API 4.0 Runtime is already installed." -ForegroundColor Cyan 
        } else {
               #testing
               If (Test-Path $file){ 
                    Write-host "The installer file exists:$file"  -ForegroundColor Green
                     #Installing
                     Write-Host "Installing Microsoft UM API..." -ForegroundColor yellow 
                     $arg = "/quiet /norestart" 
                     $status = (Start-Process $file -ArgumentList $arg -Wait -PassThru).ExitCode 
                     if ($status -eq 0) { write-host "Successfully installed $file" -ForegroundColor Green } 
                     if ($status -ne 0) { write-host "Failed!" -ForegroundColor Red }                           
            } else {Write-host "$file does not exist" -ForegroundColor red}
}}}

Restart your Servers

#Restart Servers
$servers | %{"Restarting $_";Restart-computer $_ -force}

 

 

 

 

Install Microsoft Unified Communications Managed API 4.0 Remotely Via PowerShell

Scenario:  You want to install Microsoft’s Unified Communications Managed API 4.0 to multiple servers remotely

Script:

  1. Collect your Servers by Querying AD
Import-Module ActiveDirectory
$strOU = "OU=Exchange2016,DC=XYZ,DC=COM"
$servers = get-adcomputer -searchbase $strOU -properties Name -Filter *|  where {$_.name -like "Ex16-*"} | Select -ExpandProperty Name

2. Copy your Installer File to a folder on each server (or a single network share). We have copied it to C:softwareUCMA.exe on each Exchange Server.

3. Run the Installer by invoking the command on each server.

$servers | %{"Installing UCMA on $_"; Invoke-Command -Computer $_ -ScriptBlock {
    #Set Variables
    $file = "C:softwareUcma.exe" 
    #check to see if its installed
    if (Get-ItemProperty "HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstallUCMA4" -ErrorAction SilentlyContinue) { 
        Write-host "Unified Communications Managed API 4.0 Runtime is already installed." -ForegroundColor Cyan 
        } else {
               #testing
               If (Test-Path $file){ 
                    Write-host "The installer file exists:$file"  -ForegroundColor Green
                     #Installing
                     Write-Host "Installing Microsoft UM API..." -ForegroundColor yellow 
                     $arg = "/quiet /norestart" 
                     $status = (Start-Process $file -ArgumentList $arg -Wait -PassThru).ExitCode 
                     if ($status -eq 0) { write-host "Successfully installed $file" -ForegroundColor Green } 
                     if ($status -ne 0) { write-host "Failed!" -ForegroundColor Red }                           
            } else {Write-host "$file does not exist" -ForegroundColor red}
}
}}

 

 

 

 

Set the Paging File Size for all Exchange Servers remotely via PowerShell

Scenario:  You want a script to set the Paging File Size to 32GB on multiple servers remotely.

Solution:  Run this script from a computer that has the ActiveDirectory Module for PowerShell installed.

#Query AD for your Servers
Import-Module ActiveDirectory
$strOU = "OU=Exchange2016,DC=XYZ,DC=COM"
$servers = get-adcomputer -searchbase $strOU -properties Name -Filter *|  where {$_.name -like "Ex16-*"} | Select -ExpandProperty Name

#Loop through all Exchange Servers and set the Custom Paging size to 32GB 
$servers | Sort Name | %{"Setting Page File Size on $_"; Invoke-Command -Computer $_ -ScriptBlock {
[int]$InitialSize = 32778
[int]$MaximumSize = 32778
$ComputerSystem = $null
$CurrentPageFile = $null
$modify = $false
$ComputerSystem = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges
if ($ComputerSystem.AutomaticManagedPagefile) {$ComputerSystem.AutomaticManagedPagefile = $false; $ComputerSystem.Put()}
$CurrentPageFile = Get-WmiObject -Class Win32_PageFileSetting
if ($CurrentPageFile.InitialSize -ne $InitialSize) {$CurrentPageFile.InitialSize = $InitialSize;$modify = $true}
if ($CurrentPageFile.MaximumSize -ne $MaximumSize) {$CurrentPageFile.MaximumSize = $MaximumSize;$modify = $true}
if ($modify) { $CurrentPageFile.Put()}
}}

Find Exchange Recipients that do not have a specific EmailDomain as an Email Alias/Proxy Address

Scenario:  You want to query all Exchange recipients that do not have a email alias with the @XYZ.com domain.

Script: Use this command to export the recipients to a .csv.

get-recipient * -filter {emailaddresses -notlike ‘*@xyz.com’} -ResultSize unlimited | Export-csv C:tempxyz.csv

EWS Script for Searching the Dumpster and exporting message information

Scenario:  You want a logical way of exporting message information for all messages in a mailbox dumpster. In this scenario we are going to target the date of which items show  ‘deleted on’ in Outlook when in the ‘Recover Deleted Items’ folder.  The message property for this ‘Deleted On’ date is LastModifiedTime.

Script:  The following EWS script runs in 5 day increments as you are maxed out  when performing a filter/view against a dataset with EWS at a specific number.  The mailbox had a large number of recently deleted items. If you are able to, feel free to adjust the values for  $startdate.adddays(x) and $enddate.adddays(x) so you do not end up with 1000’s of files like me.

#Connect to Exchange Service
        Import-Module -Name "C:Program FilesMicrosoftExchange ServerV15BinMicrosoft.Exchange.WebServices.dll"
        $service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.Exchangeversion]::exchange2013)
        $service.Url = new-object System.Uri("https://ex2013svc1/EWS/Exchange.asmx")
   
 #Pick the Mailbox
        $mailboxname = "baduser@domain.com"
 
#Bind to the RootFolder
        $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::RecoverableItemsDeletions,$mailboxname) 
        $RecoverFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)

#starter Variables
        [datetime]$StartDate  = "1/1/2005"
        [datetime]$EndDate = "1/5/2005 23:59"
        $result = @() 
        $temp = @()
        $Today = Get-date

#loop it
Do{
        #Define Loop Variables
        $file_startdate = ($startdate).tostring("MMddyyyy")
        $file_enddate = ($enddate).tostring("MMddyyyy")
        $file_Datestring = $file_Startdate +"_"+$file_Enddate
        "Searching $file_DateString"
        #Create Collection and Query upon your Filter
        $sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
        $Sfgt = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThan([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $StartDate)
        $Sflt = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThan([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $EndDate)
        $sfCollection.add($Sfgt)
        $sfCollection.add($Sflt)
        $view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000000)
        $frFolderResult = $RecoverFolder.FindItems($sfCollection,$view) 
        $temp = @($frFolderResult)
        $result+= $frFolderResult
        "Current: $($temp.count)"
        "Total Count: $($result.count)"
        
#Export Results
        $temp |Select LastModifiedTime, LastModifiedName, Subject, From, DateTimeReceived  | Export-csv C:tempuser_$file_datestring.csv
        $StartDate = $StartDate.AddDays(5)
        $EndDate = $EndDate.AddDays(5)
        }While($StartDate -gt $today)

#View Results:
$result

Remove a users photo in Exchange

Scenario:  You need to remove a user’s photo in Exchange. You have verified that the thumbprintphoto attribute is <not set> in Active Directory, but the photo is still showing in Exchange.

Cause:  The mailbox stores a high-resolution photo in the mailbox in additional to the photo that is stored in AD.  You will need to remove it from the mailbox.

Solution:  Run the following PowerShell command to remove the photo for testuserA.

Remove-UserPhoto testuserA