Showing posts with label Exchange. Show all posts
Showing posts with label Exchange. Show all posts

Tuesday, 2 November 2021

Microsoft Exchange - 451 4.7.0 Temporary server error. Please try again later. PRX5 - FIX

I encountered this error on my on-premise/Hybrid exchange server today after noticing that internal mail relay was not working. When attempting to send a test email via telnet, I got the error 451 4.7.0 Temporary server error. Please try again later. PRX5

After rebooting the server, the error still persisted - so a quick bit of searching quickly lead to me adjusting the Exchange servers DNS settings.

From within Exchange Control Panel (ECP) - go to Servers (left hand menu) and double click your Exchange server to open it's properties



Select DNS Lookups from the left menu.

By default, the option for External and Internal DNS lookups is usually All network adapters (All available IPv4). I changed this to Microsoft Hyper-V Network Adapter and the problem was immediately resolved.

Tuesday, 4 May 2021

Reading Emails from O365 Mailbox with Powershell

Here is a script you can use to connect to an Office 365 (O365) mailbox to read/parse email messages. After the message has been read it is then moved to a specific folder within the mailbox. The full script is included first, and I will then break it down section by section afterwards

#Enable Exchange/O365 cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue
Import-Module MSOnline -ErrorAction SilentlyContinue

#Credentials
$email = email@domain.com
$password = "password"
$emaildomain = domain.com

#Connect to Mailbox
[void][Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll")
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$s.Credentials = New-Object Net.NetworkCredential($email, $password, $emaildomain)
$s.Url = new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx");
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#Setup folder and folder view (to move completed messages to)
$fv = new-object Microsoft.Exchange.WebServices.Data.FolderView(30)
$fv.Traversal = "Deep"
$folders = $s.findFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$fv)
$processedfolder = $folders | where {$_.displayname -eq "ProcessedEmails"}

#Get unread messages
$msgs = $null
$iv = new-object Microsoft.Exchange.WebServices.Data.ItemView(50)
$inboxfilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$ifisread = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead,$false)
$inboxfilter.add($ifisread)
$msgs = $s.FindItems($inbox.Id, $inboxfilter, $iv)

#If unread message(s) found, do stuff
if ($msgs.totalcount -ne 0)
    {
    $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
    $psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
    $s.LoadPropertiesForItems($msgs,$psPropertySet)
    $msgs = $msgs.items
    }

#Move Message to Processed Folder
$msg.Move($processedfolder.Id)


The #Enable Exchange/O365 Cmdlets section as the comment suggests is to enable the Microsoft Exchange & Office 365 cmdlets

add-pssnapin *exchange* -erroraction SilentlyContinue
Import-Module MSOnline -ErrorAction SilentlyContinue

The #Credentials section is where you enter the details (username, password and email domain) used to connect to the mailbox

#Credentials
$email = email@domain.com
$password = "password"
$emaildomain = domain.com

Next, we will connect to the mailbox (and look at the Inbox folder specifically), using the credentials specified above and Microsoft Exchange Web Services. If you don't already have the Exchange Web Services files installed you will need to install them

#Connect to Mailbox
[void][Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll")
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$s.Credentials = New-Object Net.NetworkCredential($email, $password, $emaildomain)
$s.Url = new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx");
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

Now, a folder view is setup to obtain the list of all the folders in the mailbox. All the list of available folders are stored in the $folders variable. We then look for a folder called "ProcessedTickets" and set this folder to be the $processedfolder variable. We use this variable (folder) later on to move processed emails into. You can of course change this folder name to be anything you like.

#Setup folder and folder view (to move completed messages to)
$fv = new-object Microsoft.Exchange.WebServices.Data.FolderView(30)
$fv.Traversal = "Deep"
$folders = $s.findFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$fv)
$processedfolder = $folders | where {$_.displayname -eq "ProcessedEmails"}

Now we will retrieve any unread messages within the mailbox - filters are set using the $inboxfilter and $ifisread variables. All messages matching the search criteria are stored in the $msgs variable

#Get unread messages
$msgs = $null
$iv = new-object Microsoft.Exchange.WebServices.Data.ItemView(50)
$inboxfilter = new-object
Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$ifisread = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead,$false)
$inboxfilter.add($ifisread)
$msgs = $s.FindItems($inbox.Id, $inboxfilter, $iv)

If messages are found in the $msgs variable, the properties for those messages are then loaded back into the $msgs variable

#If unread message(s) found, do stuff
if ($msgs.totalcount -ne 0)
    {
    $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
    $psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
    $s.LoadPropertiesForItems($msgs,$psPropertySet)
    $msgs = $msgs.items
    }

If you look at the $msgs variable at this point, it should contain the properties of all mail messages found in the inbox that are unread. You can then use a foreach loop to cycle through each message and action accordingly.

Properties such as subject, body text, from address are all available and can be used to further filter entries

Once you've actioned the email and done what you need, you can then move the email into the processedfolders folder we previously specified

#Move Message to Processed Folder
$msg.Move($processedfolder.Id)


Monday, 24 October 2016

Outlook - Mailbox Full Message after storage quota increased (or removed)

I recently experienced an issue where multiple users for a mailbox were getting a "mailbox full" message in Outlook. When the message first appeared, I removed the storage quota on the mailbox, but after a server restart (and of course restarting the outlook clients), they were still getting prompted with the same message.

The solution ended up being to remove the .ost file for this particular mailbox (default location is %localappdata\Microsoft\Outlook) and then restarting the Outlook client (you will need to close Outlook before it will let you delete the .ost file)

The .ost file will automatically be re-created when Outlook is opened, and mail will then be downloaded back into the .ost file from the server.

Thursday, 6 October 2016

IIS - Make OWA the Default Website Page

After installing Microsoft Exchange, a "virtual directory" for Outlook Web Access (OWA) is created that is generally accessible via the URL https://mail.yourdomain.com/owa

In some scenarios it may be preferable to configure https://mail.yourdomain.com to redirect automatically to the OWA virtual directory (as users may forget to include this part if they are manually typing the URL). This means as soon as they try to access the root domain website, they are automatically presented with a login page for OWA.

It is very easy to configure, as per the steps below;

  1. Open Internet Information Services (IIS) Manager (from Control Panel > Administrative Tools)
  2. Expand the tree from the left hand side and highlight/select Default Web Site

  3. Double click the HTTP Redirect icon from the main window

  4. Select the option to Redirect requests to this destination and enter /owa into the text box below
    Select the option to Only redirect requests to content in this directory (not subdirectories). Ensure the status code is set to Found (302)

  5. Click Apply in the top right corner to apply the changes
  6. Try accessing the base URL again and you should be automatically redirected to the OWA login page



Friday, 16 September 2016

Export/Audit All Exchange ActiveSync Devices using Powershell

Below are a couple of commands we can use in Windows Powershell to run a report on all mobile devices that have been synced with mailboxes within your exchange environment.

First step is to gather a list of users that have an ActiveSync Device partnership

$userlist = gt-casmailbox -filter {hasactivesyncdevicepartnership -eq $true -and -not displayname -like "CAS_{*"} | Get-Mailbox

This list of users is then used against the Get-ActiveSyncDeviceStatistics cmdlet to retrieve the associated ActiveSync devices with each users mailbox. We then select certain fields to reduce the amount of data and present it in the $report variable.

$report = $UserList | foreach { Get-ActiveSyncDeviceStatistics -Mailbox $_} | select Identity, LastSuccessSync, DeviceType, Status

You can also add the export-csv component onto the end of the command to export the $report contents to a .csv file

$report = $UserList | foreach { Get-ActiveSyncDeviceStatistics -Mailbox $_} | select Identity, LastSuccessSync, DeviceType, Status | export-csv -path "C:\ActiveSyncDevices.csv" -notype

Thursday, 15 September 2016

View and Change Exchange Mailbox Calendar Permissions with Powershell

Permissions for mailbox calendars are managed separately to the actual mailbox permissions. You can use the below cmdlets in powershell to view and add/edit the permissions on a users mailbox.

To view current calendar permissions on a mailbox

get-mailboxfolderpermission -identity "name:\Calendar" | ft

To add new calendar permissions on a mailbox

add-mailboxpermission -identity "name:\Calendar" -User "usertogetaccess" -AccessRights "Accesslevel"


To modify an existing calendar permissions entry on a mailbox

set-mailboxfolderpermission -identity "name:\Calendar" -User "usertogetaccess" -AccessRights "Accesslevel"

To remove an existing calendar permissions entry on a mailbox

remove-mailboxpermission -identity "name:\Calendar" -User "usertogetaccess" -AccessRights "Accesslevel"

Name = the display name alias or email address you are setting the calendar permissions ON
Usertogetaccess = the display name, alias or email address you are granting calendar permissions TO
Accesslevel = the level of access to be granted. The available options are:
  • Owner
  • Publishing Editor
  • Editor
  • Publishing Author
  • Author
  • Nonediting Author
  • Review
  • Contributor
  • Free/Busy Time
  • None

Wednesday, 14 September 2016

Check which Exchange Mailboxes a User has Full Access or Send As Permissions On using Powershell

As an exchange administrator, you may occassionally need to know which mailboxes a particular user has Full Mailbox Access or Send As permissions to. This may be required as part of an audit, or to simply copy an existing users permissions for a new user you are setting up/creating.

The script below helps to accomplish this, as there is no in-built/easy way to view which mailboxes a particular user has access to - ie. Full Mailbox Access, or Send As permissions

First you need to specify the user whose existing access we are checking, using the $user variable. We use the wildcard "*" to essentially match any name that contains what is between the *'s - the users first name, last name or alias should work.

$user = "*peter*"

Next we run the get-mailbox cmdlet against all mailboxes in exchange, to query the permissions on each mailbox to see if this user exists in the respective permissions list.

There are two separate commands to do this - one to check for Full Access permissions, and the other to check for Send As permissions

get-mailbox -resultsize unlimited | get-mailboxpermission | where {$_.user -like $user} | select Identity, AccessRights

get-mailbox -resultsize unlimited | get-adpermission | where {($_.user -like $user) -and ($_.ExtendedRights -like "*Send-As*")} | select Identity, ExtendedRights

If any matches are found, the results will be displayed showing their Identity (ie. name) and the Access Rights level they have

Tuesday, 13 September 2016

Export All Exchange Mailbox Sizes with Powershell

Here is a script you can run on your exchange server to export a list of all mailboxes on the server and the size of each mailbox. This is useful for checking/monitoring mailbox size and usage.

First of all we need to get the name of the mailbox database to query

$mbdb = get-mailboxdatabase | select Name

Next, we use this database name in the get-mailboxstatistics cmdlet to query all mailboxes within the database and export the size from the TotalItemSize field. The list is then sorted alphabetically by display name and exported to a .csv file so it's easier to view

get-mailboxstatistics -database "$($dbname.name)" | select DisplayName, TotalItemSize | sort DisplayName | export-csv "C:\1GB-MailboxList.csv" -notype

You can also implement a "filter" of sorts so that you only export mailboxes that are bigger than a certain size. For example, you may want to know how many mailboxes you have that are larger than 1GB. To do this, we add a filter using the "where {$_.totalitemsize -ge $size}" where $size is the size value you need, in bytes.

So for the example of 1GB, the $size variable would be set to 1073741824 which is 1GB in bytes.

There is a handy utility you can use by following the link below to quickly convert the size you require from GB to bytes

http://www.convertunits.com/from/GB/to/byte

$size = "1073741824"

get-mailboxstatistics -database "$($dbname.name)" | where {$_.totalitemsize -ge $size} | select DisplayName, TotalItemSize | sort DisplayName | export-csv "C:\1GB-MailboxList.csv" -notype

Friday, 9 September 2016

Get ActiveSync Enabled Accounts/Mailboxes using Powershell

Here is a short/simple script you can use to obtain a list of all mailboxes within your Exchange environment that have the ActiveSync service enabled on them.

#Add Exchange Cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue

get-casmailbox -resultsize unlimited | where {$_.ActiveSyncEnabled -eq $true}

The output will now be displayed showing all mailboxes in your environment that have ActiveSync functionality enabled on them.

You can export your results to a .csv by adding a bit more to the end of the command as per below. You can of course change the output path as required

get-casmailbox -resultsize unlimited | where {$_.ActiveSyncEnabled -eq $true} | select Name, ActiveSyncEnabled | export-csv "C:\activesyncusers.csv" -notype

Thursday, 8 September 2016

Exchange 2010 New Install - Nothing Showing Under Microsoft Exchange On-Premises

After installing Microsoft Exchange Server 2010 onto a Windows Server 2012 R2, nothing was showing under the Exchange Management Console after expanding "Microsoft Exchange On-Premises".

Everything under "Exchange 2010 Organizational Health" was showing as "Unavailable"



When selecting the option to "Collect Organizational Health Data", the below error occurs stating "MMC has detected an error in a snap-in and will unload it"



To resolve this issue you need to install the latest Service Pack (SP3) for Microsoft Exchange Server 2010 - available from the following URL:

https://www.microsoft.com/en-us/download/details.aspx?id=36768

You can then install Update Rollup 14 for Microsoft Exchange Server 2010 SP3 from the following URL:

http://go.microsoft.com/fwlink/p/?LinkId=820579

As you can see below, once SP3 has been installed, the Configuration options are now available/showing under "Microsoft Exchange On-Premises" after the updates are installed

Friday, 3 May 2013

Adding Multiple Users to 'Accept Messages Only From' - Exchange 2007

Exchange 2007 has a feature that allows restrictions to be placed on a distribution group (I call them "distribution lists", or "DL's") that control who is allowed/permitted to send messages to them.

The Exchange Management Console enables you to search and add individual users to this list, but I found the process can be very slow and tedious, especially if you want to add a large number of users to this list, or want to add users to multiple DL's.

For this reason, I created the below script. Others who may have tried this using a simple "Set-DistributionGroup" command would have found that every time they tried to add a user it replaced any users who were already in the list. This script queries the already existing users and appends/adds the new user onto the already existing list. You will need to provide a list of users either within the script, or by importing a simple .txt file with a list of users you wish to add. For this example, I will use a .txt file.

The .txt file contains a simple list of users with a single name on each line;

firstname.lastname@domain.com
test.user1@domain.com
example.user2@domain.com

And here is the script:

#Name of Distribution Group/List to add user(s) to
$TargetDL = "DL_Test"

#Domain Controller Name - must be used to ensure each user is appended and not replaced. 
$DC = "domaincontrollername"

#Import List of Users to add from .txt file
$UserListFile = "C:\UserList.txt"
$UserList = Get-Content $UserListFile

#Cycle through list of users and add them to 'Accept Messages Only From' list for DL
ForEach ($User in $UserList)
     {
     Set-DistributionGroup "$TargetDL" -AcceptMessagesOnlyFrom ((Get-DistributionGroup -DomainController "$DC" -identity "$TargetDL").AcceptMessagesOnlyFrom + "$User") -DomainController "$DC"
     Write-Host "$User granted permission to send to $TargetDL"
     }


Replace the $TargetDL, $DC, and $UserListFile variables with the relevant information for your Exchange environment

Friday, 8 February 2013

Querying Exchange Mailboxes with Powershell Pt 2

In my previous blog post, I outlined some methods to query Exchange mailboxes using the get-mailbox cmdlet. Whilst the information obtained using this cmdlet is very useful, it does not contain all the information that is available for an Exchange mailbox.

There is another cmdlet available called Get-MailboxStatistics. It is used/applied in the same way as the Get-Mailbox cmdlet, but contains different fields or properties, and therefore, different information relating to the mailbox.

If you run the command Get-MailboxStatistics -identity "MailboxName" | fl it will display the mailbox statistics for that particular mailbox.

This information includes;

  • Associated item count (ie. number of items within the mailbox)
  • Deleted item count
  • Last logon/logoff time
  • Total size of items
  • Total size of deleted items
So, for a practical example that you could potentially use to query this information. Let's say you want to query all your mailboxes to identify those that have more than 20,000 items within them. You could run the following command;

Get-Mailboxstatistics | Where {$_.ItemCount -gt "20000"} | Select DisplayName

You could replace $_.ItemCount with any of the other properties that are contained within the Get-MailboxStatistics cmdlet.

If you want the query to return more than just the DisplayName field for objects that match your query, you can add them after DisplayName and separate them with a comma (,), or if you want to return all properties then remove | Select DisplayName altogether.

You can also add | Export-CSV-path "C:\Export.csv" -notype to the end to export your query results to a .csv file.

Tuesday, 5 February 2013

Querying Exchange Mailboxes with Powershell

Exchange and Powershell go hand in hand - as it is essentially what Exchange is built on top of, and is what the Exchange Management Console (EMC) uses to execute commands you choose through the GUI. (Ever noticed you get the Powershell command line equivalent for commands you execute in EMC?)

One of the most common things an administrator will need to do is query all the mailboxes within the system for certain criteria, which I will explain and breakdown in this blog entry.

The command Get-Mailbox is one of the most useful and powerful commands you can use (for information gethering). It can be used to retrieve all the properties for all the mailboxes in your system, or can be tweaked to only return some of the properties for some of the mailboxes within your system.

If you execute the command Get-Mailbox on its own, you will probably be flooded with 1000 responses, followed by the following warning message;


WARNING: By default only the first 1000 items are returned. To change the number of items returned, specify the parameter "-ResultSize". To return all items specify "-ResultSize Unlimited" (Note: Returning all items may take a 
very long time and consume a large amount of memory depending on the actual number of items). It is not recommended to store the results in a variable; instead pipe the results to another task or script to perform batch changes

As per the message, the command on its own will only return the first 1000 results. You can change this by adding -ResultSize Unlimited to it, so it would look like this;

Get-Mailbox -ResultSize Unlimited

If you run this command it will run through and display the first few properties for every mailbox within your system. While this can be useful, the command can be further tweaked to run faster and provide more accurate/informative results.

To get all the properties for a single users mailbox, you can use the following command

Get-Mailbox -Identity "Morrissey, Peter"

You can replace what is between the " " with any identifier for the mailbox - such as Primary SMTP Address, Display Name or Alias.

When you run this command it will only display the first few properties as it is presenting the information in a table format. If you change the command to display in list format (by adding | fl), you get MUCH more information:

Get-Mailbox -Identity "Morrissey, Peter" | fl

Now you can view ALL the properties for an individual users mailbox. These properties apply to every mailbox within the system, so you can once again, modify the Get-Mailbox command to search on any of the properties you see in this list.

For example, if I wanted to query all the mailboxes within my system, and only return those whose 'Name' property contain the text "Peter", I would run the following command

Get-Mailbox -ResultSize Unlimited | Where {$_.Name -like "*Peter*"}

You still need to include -Resultsize Unlimited because although you aren't expecting more than 1000 results to be returned, you do want the Get-Mailbox command to query more than the first 1000 mailboxes, which it will not do if this omitted.

You can replace the $_.Name with any of the other properties for a mailbox - it just needs to have the $_. before it.

The -like operator can also be changed to use -eq (equal to) -ne (not equal to) -gt (greater than) -lt (less than) -le (less than or equal to) -ge (greater than or equal to)

Next you can fine tune the properties that you wish to display for each object whos name contains "Peter". Say you want to only display the DisplayName, Alias, Database and PrimarySMTPAddress properties for each of the results. You could use the following line

Get-Mailbox -ResultSize Unlimited | Where {$_.Name -like "*Peter*"} | Select DisplayName, Alias, Database, PrimarySMTPAddress

The benefit of doing this is that by retrieving fewer properties for each object, it speeds up the time it takes for the query to run. It also makes looking through the results much faster as you aren't reading over information you don't need. Once again, you can replace the properties I used with any of the properties available for each mailbox, as we discovered earlier.

Finally, you  can export the results of your query to a CSV file

Get-Mailbox -ResultSize Unlimited | Where {$_.Name -like "*Peter*"} | Select DisplayName, Alias, Database, PrimarySMTPAddress | Export-CSV -path "C:\Export.csv" -notype

Once you have the information in a CSV file you can attach it to an email and send it to yourself (or someone else) as per my previous blog post

Thursday, 24 January 2013

Exporting Exchange Distribution Group Members with Powershell

Before making any major changes to distribution groups, I like to take a backup of the current membership lists prior to making any changes. Particularly in cases where membership lists are quite large, it's always better to be safe than sorry for when a user or distribution group owner wants to know who was a member prior to making the change.

Getting the list of members and exporting it to a simple .csv file can be achieved using the Powershell script below.

Note that you should change the first two (2) variables ($DLName and $ExportFilePath) accordingly.

#Script to get/export list of all distribution group members
#Date Created: 24th January, 2013
#Author: Peter Morrissey


#Enable Exchange cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue

$DLName = "DL_Example_List"
$ExportFilePath = "C:\Export\Export.csv"


$MemberList = get-distributiongroupmember -identity $DLName

ForEach ($Member in $MemberList){write-output "$($member.name)" | out-file -filepath "$exportfilepath" -append -noClobber}

Friday, 18 January 2013

Enabling Exchange Cmdlets in Powershell

In order to run Exchange Server commands within a Powershell script, the relevant cmdlets need to be 'called' within Powershell.

This is accomplished with the following line, which is found at the start of nearly all of my Powershell scripts.

#Enable Exchange cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue

If you attempt to run Exchange commands in Powershell (eg. Get-Mailbox) without loading the Exchange cmdlets first, you will get an error similar to the following;


The term 'get-mailbox' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:12
+ get-mailbox <<<< 
    + CategoryInfo          : ObjectNotFound: (get-mailbox:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException


Exchange Global Address List Not Updating - Force Global Address List (GAL) Update

I have created this Powershell script to be able to force an update of the Global Address List within Exchange 2007. After making changes to recipients/distribution lists within Exchange, I sometimes required a way to make these changes quickly accessible to users, so when they next download the GAL through Outlook, they obtain the latest changes. Most environments do this automatically once or twice a day, which is fine, but this script can be used to force the process to run as required.

Before running this script, I manually force an update of the Default Offline Address Book (OAB) through the Exchange Management Console. I then run this script to force the latest version of the OAB to the Client Access Server's so it is available for download by end users.


#Enable Exchange cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue

#Force Update of OAB

Get-OfflineAddressBook | Update-OfflineAddressBook

#Get List of Current CAS Servers

$CASList = Get-ExchangeServer | where {$_.isClientAccessServer -eq $true}

#Force Deployment of GAL to CAS's

ForEach ($CAS in $CASList)
    {
    Update-FileDistributionService $($CAS.Name)
    }