MVP - Most Valuable Professional
rss

Just can't get enough of IT

This blog is about mostly anything in IT. But the primary focuses are Microsoft technologies like Exchange Server, Microsoft 365, Microsoft Teams, and Cloud Security.

Exchange Server 2007Exchange Server 2010Description

This scripts removes or updates users in legacy public folder ACLs. This reduces the likelihood of legacy public folder migration errors due to corrupted ACLs.

When you perform a migration from legacy public folders to modern public folders, you might see the following error as part of the migration reports.

A corrupted item was encountered: Folder ACL

Corrupted items count towards the bad item limit and will not be migrated.

When you take a closer look at the public folder ACLs, you'll see that there will be orphaned users and even users that have not been properly converted during past legacy replications.

In preparation for a modern public folder migration, you should clean up the public folder ACLs from so-called zombie users.

Tasks performed by the script:

  • Remove orphaned users listed with SIDs, e.g. NT User:S-1-*
  • Identify ACL user/group with notation NT User:DOMAIN\samAccountName
    • Remove user/group, if the object cannot be found in Active Directory
    • Replace user/group, if the object can be found in Active Directory

 

Examples

# EXAMPLE 1
# Validate ACLs on public folder \MYPF and all of it's child public folders on Exchange server EX200701
.\Clean-PublicFolderACL.ps1 -RootPublicFolder "\MYPF" -PublicFolderServer EX200701 -ValidateOnly

# EXAMPLE 2
# Clean ACLs on public folder \MYPF and all of it's child public folders on Exchange server EX200701
.\Clean-PublicFolderACL.ps1 -RootPublicFolder "\MYPF" -PublicFolderServer EX200701

 

Version History

  • 1.0, Initial community release
  • 1.1, Fixed group replacement logic
  • 1.2, Script optimization

 

Links

Last updated: 2016-12-01

 

Follow

 

Read More »
Last updated: 2020-02-29

 

This is the Modern Exchange Server version for 2013, 2016, and 2019. Find the PowerShell version for Exchange 2010 here.

 

Exchange Server 2013Exchange Server 2016Exchange Server 2019Description

This script removes orphaned mobile device partnerships from Exchange Server 2013+ user mailboxes. Run the script as a scheduled task to maintain your Exchange Server environment properly.

This script utilizes a settings.xml file to configure

  • SMTP settings for email reports
  • Threshold values for mobile devices
    • The default number of allowed devices per user: 5
    • The default number of aged devices to be removed: 1
    • The default threshold for unsynchronized devices: 150 days

Settings.xml (default)

<?xml version="1.0"?>
<Settings>
  <EmailSettings>	
    <SMTPServer>smtp.mcsmemail.de</SMTPServer>
    <SMTPPort>25</SMTPPort>
    <MailFrom>postmaster@mcsmemail.de</MailFrom>
    <MailTo>postmaster@mcsmemail.de</MailTo>
  </EmailSettings>
  <OtherSettings>
	<!-- MobileDeviceLimit defines the overall threshold of mobile devices for a single user to synchronize. Default is 5. -->
	<MobileDeviceLimit>5</MobileDeviceLimit>

	<!-- AgedDeviceLimit defines the threshold of allowed aged devices for a single user to be removed. Default is 1. -->
	<AgedDeviceLimit>1</AgedDeviceLimit>

	<!-- Time threshold in days to identify old mobile devices, Be default devices not synchronized for 150 days will be removed -->
    <LastSyncDays>150</LastSyncDays>
  </OtherSettings>
</Settings>

Steps being executed by the script:

  1. Fetch all user mailboxes hosted on Exchange Server 2013 or newer
  2. Iterate through each user mailbox and determine the number of mobile devices and the number of devices which have not synchronized for 150 days
  3. Remove mobile device registration, if a user has more than the allowed number of devices in total and a minimum of 1 device that has not synced within 150 days and the -ReportOnly switch has not been used
  4. Optionally, write a CSV export of identified mobile devices to disk | Use -ReportOnly switch
  5. Optionally, send an email report | Use -SendMail switch

 

Requirements

  • Exchange Server 2013, 2016, 2019
  • Windows Server 2012 R2 or newer
  • Exchange Management Shell

 

Examples

# Example 1
# Remove old mobile device partnerships without sending a report email

 .\Remove-MobileDevicePartnership.ps1 

# Example 2
# Remove old mobile device partnerships and send a report email

.\Remove-MobileDevicePartnership.ps1 -SendMail

# Example 3
# Search for old mobile device partnerships and write results as CSV to disk

.\Remove-MobileDevicePartnership.ps1 -ReportOnly

# Example 4
# Remove old mobile device partnerships for a single mailbox and send a report email

 .\Remove-MobileDevicePartnership.ps1 -MailboxFilter USERALIAS -SendMail

 

Version History

  • 1.0, Initial community release
  • 1.1, ReportOnly switch added
  • 2.0, Updated script to support Exchange Server 2019, parameter MailboxFilter added

 

Links

 

Follow

 

 

Read More »

When you've enabled the Exchange scripting agent extension agents, it is required to copy the configuration file to each Exchange server. Paul Cunningham's script helps you to achive this goal pretty easily.

But if you have installed the Exchange 2013 Management Tools on additonal servers, these servers are not fetched using the Get-ExchangeServer cmdlet. But when you install a Cumulative Update the existence of the extension agent config file is checked. And this even on a server having only the Exchange Management Tools installed.

Therefore the following PowerShell code provides an easy and simple way to add additonal server having the Exchange 2013+ Management Tools installed (aka Admin Servers, Monitoring Servers, Job Servers, etc.). The script uses a filter to select Exchange 2013 servers only, as the script has been extended in an environment having still active Exchange 2007 servers.

The following PowerShell snippet displays only the changes, which need to be added to Paul's original script starting row 68.

# Original PowerShell code
# $exchangeservers = Get-ExchangeServer

# Select all Exchange 2013 servers only, restrict properties to Name and AdminDisplayName
$exchangeservers = Get-ExchangeServer | ?{$_.AdminDisplayVersion -like "Version 15.0*"} | Select Name, AdminDisplayVersion

# Add additional servers as needed

$manualServers = @()
# Copy and modify as needed
$manualServers += (New-Object PSObject -Property @{Name="EXSRV2010";AdminDisplayVersion="Version 14"})
$manualServers += (New-Object PSObject -Property @{Name="EXSRV2013-01";AdminDisplayVersion="Version 15"})
$manualServers += (New-Object PSObject -Property @{Name="EXSRV2013-02";AdminDisplayVersion="Version 15"})

# Combine arrays
$exchangeservers = $exchangeservers + $manualServers

# End Modification

$report = @()

[string]$date = Get-Date -F yyyyMMdd-HHmmss

Enjoy extending the Exchange PowerShell cmdlets.

Links

Questions? Just leave a comment.

Read More »
Last updated: 2016-12-20

Exchange Server 2013Exchange Server 2016Description

This scripts creates a new shared mailbox (aka team mailbox) and security groups for full access and and send-as delegation. The security groups are created using a naming convention. If required by your Active Directory team, you can add group prefixes or department abbreviations as well.

The script uses a Xml configuration file to simplify changes for variables unique for your environment.

High level steps executes by the script:

  1. Create a new shared mailbox
  2. Create a new mail enabled security group for full access delegation
  3. Assign full access security group for full access to the shared mailbox
  4. Create a new mail enabled security group for send-as delegation
  5. Assign send-as permissions to send-as security group

 

Examples

Xml settings file

<?xml version="1.0"?>
<Settings>
	<GroupSettings>
		<Prefix>pre_</Prefix>
		<SendAsSuffix>_SA</SendAsSuffix>
		<FullAccessSuffix>_FA</FullAccessSuffix>
		<CalendarBookingSuffix>_CB</CalendarBookingSuffix>
		<TargetOU>mcsmemail.de/IT/Groups/Mail</TargetOU>
		<Domain>mcsmemail.de</Domain>
		<Seperator>-</Seperator>
	</GroupSettings>
	<AccountSettings>
		<TargetOU>mcsmemail.de/IT/SharedMailboxes</TargetOU>
	</AccountSettings>
	<GeneralSettings>
		<Sleep>10</Sleep>
	</GeneralSettings>
</Settings>

The following example creates an empty shared mailbox for an internal Exchange Admin team with empty security groups.

.\New-TeamMailbox.ps1 -TeamMailboxName "TM-Exchange Admins" ` 
  -TeamMailboxDisplayName "Exchange Admins" `
  -TeamMailboxAlias "TM-ExchangeAdmins" `
  -TeamMailboxSmtpAddress "ExchangeAdmins@mcsmemail.de" `
  -DepartmentPrefix "IT"

The following Create-TeamMailbox.ps1 script simplifies the process of creating a team mailbox even more.

$teamMailboxName = 'TM-Exchange Admin'
$teamMailboxDisplayName = 'Exchange Admins'
$teamMailboxAlias = 'TM-ExchangeAdmin'
$teamMailboxSmtpAddress = 'ExchangeAdmins@mcsmemails.de'
$departmentPrefix = 'IT'
$groupFullAccessMembers = @('exAdmin1','exAdmin2')
$groupSendAsMember = @('exAdmin1','exAdmin2')

.\New-TeamMailbox.ps1 -TeamMailboxName $teamMailboxName ` 
  -TeamMailboxDisplayName $teamMailboxDisplayName `
  -TeamMailboxAlias $teamMailboxAlias `
  -TeamMailboxSmtpAddress $teamMailboxSmtpAddress `
  -DepartmentPrefix $departmentPrefix `
  -GroupFullAccessMembers $groupFullAccessMembers `
  -GroupSendAsMember $groupSendAsMember -Verbose

Version History

  • 1.0, Initial community release
  • 1.1, Prefix seperator added, PowerShell hygiene

Links

Follow

Read More »

Description

This script helps you to monitor message flow in a NoSpamProxy environment using a PRTG custom PowerShell sensor.

This custom sensor contains the following five channels:

  • In/Out Success
    Total of inbound/outbound successfully delivered messages over the last X minutes
  • Inbound Success
    Number of inbound successfully delivered messages over the last X minutes
  • Outbound Success
    Number of outbound successfully delivered messages over the last X minutes
  • Inbound PermanentlyBlocked
    Number of inbound blocked messages over the last X minutes
  • Outbound DeliveryPending
    Number of outbound messages with pending delivery over the last X minutes

The default interval is five minutes. But you might want to change the interval as needed for your environment.

These channels can easily be modified and additional channels can be added as well.

NoSpamProxy is a powerful anti-spam gateway solution providing additonal functionality like centralized S/MIME and PGP encryption for on-premises and Exchange Online deployments.

PRTG is a industry standard system monitoring solution.

Examples

The script itself does not take any additional attributes and is called by PRTG probe.

To verify your setup, you easily execute the PowerShell script. It returns a Xml result.

PS C:\Scripts> .\Get-NoSpamProxyPrtgData.ps1
<prtg>
  <result>
    <channel>In/Out Success</channel>
    <value>0</value>
    <unit>Count</unit>
  </result>
  <result>
    <channel>Inbound Success</channel>
    <value>0</value>
    <unit>Count</unit>
  </result>
  <result>
    <channel>Outbound Success</channel>
    <value>0</value>
    <unit>Count</unit>
  </result>
  <result>
    <channel>Inbound PermanentlyBlocked</channel>
    <value>0</value>
    <unit>Count</unit>
  </result>
  <result>
    <channel>Inbound DeliveryPending</channel>
    <value>0</value>
    <unit>Count</unit>
    <limitmaxwarning>10</limitmaxwarning>
    <limitmode>1</limitmode>
  </result>
</prtg>

The PRTG channel configuration

PRTG channel using a custom sensor

The following screenshot shows PRTG example graphs.

NoSpamProxy monitored using a PRTG custom sensor

Notes

The custom PowerShell script must be saved to the following location of the PRTG probe:

[INSTALLPATH]\PRTG Network Monitor\Custom Sensors\EXEXML

Ensure to have the PowerShell execution policy set correctly. Otherwise the PRTG service won't be able to execute the PowerShell script.

Ensure that the service account used by the PRTG probe has access to the script and is a member of the NoSpamProxy Monitoring Administrators security group.

Version History

  • 1.0, Initial community release

Links

Additional Credits

Additional credits go to Brian Addicks, https://github.com/brianaddicks/prtgshell

Follow

Read More »