Microsoft Exchange

Exchange 2010 - Can't Delete Mailbox Database

posted 13 Jul 2016, 08:37 by Tristan Self

While doing some housekeeping on an Exchange 2010 server, I needed to delete a mailbox database but couldn't getting the error shown below:


 The mailbox database 'Mailbox Database 2 G-L' cannot be deleted.

Mailbox Database 2 G-L
Error:This mailbox database contains one or more mailboxes, mailbox plans, archive mailboxes, or arbitration mailboxes. To get a list of all mailboxes in this database, run the command Get-Mailbox -Database <Database ID>. To get a list of all mailbox plans in this database, run the command Get-MailboxPlan. To get a list of archive mailboxes in this database, run the command Get-Mailbox -Database <Database ID> -Archive. To get a list of all arbitration mailboxes in this database, run the command Get-Mailbox -Database <Database ID> -Arbitration. To disable a non-arbitration mailbox so that you can delete the mailbox database, run the command Disable-Mailbox <Mailbox ID>. To disable an archive mailbox so you can delete the mailbox database, run the command Disable-Mailbox <Mailbox ID> -Archive. Arbitration mailboxes should be moved to another server; to do this, run the command New-MoveRequest <parameters>. If this is the last server in the organization, run the command Disable-Mailbox <Mailbox ID> -Arbitration DisableLastArbitrationMailboxAllowed to disable the arbitration mailbox. Mailbox plans should be moved to another server; to do this, run the command Set-MailboxPlan <MailboxPlan ID> -Database <Database ID>.


You'll find there is some mailbox(es) still on the database, but they may not be visible via the GUI. A possible is a person has a mailbox created, but they have yet to login or recieve a mail, in which case a mailbox is not created yet but is still homed there, the other is an arbitration mailbox that needs to be moved before the database can go.

To fix follow the procedure below:

> get-mailbox -database "Mailbox Database 2 G-L" -Arbitration

 Name                      Alias                ServerName       ProhibitSendQuota
----                      -----                ----------       -----------------
SystemMailbox{1f05a927... SystemMailbox{1f0... exch-mbx2        unlimited
SystemMailbox{e0dc1c29... SystemMailbox{e0d... exch-mbx2        unlimited

Here there are two arbitration mailboxes that need to be moved!

> get-mailbox -Database "Mailbox Database 2 G-L" -Arbitration | New-MoveRequest -TargetDatabase "MBX2_DB1"

 DisplayName               Status                    TotalMailboxSize          TotalArchiveSize         PercentComplete
-----------               ------                    ----------------          ----------------         ---------------
Microsoft Exchange App... Queued                    161.1 KB (164,933 bytes)                           0
Microsoft Exchange        Queued                    22.7 MB (23,803,480 by...                          0

> Get-MoveRequest

 DisplayName                                    Status                    TargetDatabase
-----------                                    ------                    --------------
Microsoft Exchange Approval Assistant          CompletionInProgress      MBX2_DB1
Microsoft Exchange                             CompletionInProgress      MBX2_DB1

Wait for them to complete then re-run the first command to check for any hidden mailboxes again.
Nothing shown, we should be good to delete that mailbox store now!

Exchange 2010 Restoration fails with: ROP Error: 0x80070057 Error: MapiExceptionInvalidParameter: Unable to modify table.

posted 13 May 2016, 12:16 by Tristan Self

A colleague had a problem when attempting a restore a mailbox, this error was generated:

Error: MapiExceptionInvalidParameter: Unable to modify table. (hr=0x80070057, ec=-2147024809)
                                Diagnostic context:
                                    Lid: 55847   EMSMDBPOOL.EcPoolSessionDoRpc called [length=228]
                                    Lid: 43559   EMSMDBPOOL.EcPoolSessionDoRpc returned [ec=0x0][length=348][latency=15]
                                    Lid: 23226   --- ROP Parse Start ---
                                    Lid: 27962   ROP: ropModifyRules [65]
                                    Lid: 17082   ROP Error: 0x80070057
                                    Lid: 27745 
                                    Lid: 21921   StoreEc: 0x80070057
                                    Lid: 27962   ROP: ropExtendedError [250]

To resolve this you need to restore as follows by adding in the "-AssociatedMessagesCopyOption copy" argument, for example the below:

New-MailboxRestoreRequest -SourceDatabase MBX1 -SourceStoreMailbox "Fred Blogs" -TargetMailbox RST1 -AllowLegacyDNMismatch -ExcludeDumpster -BadItemLimit 100 -AcceptLargeDataLoss -AssociatedMessagesCopyOption copy -IncludeFolders "#Inbox#”

This additional argument specifies that the hidden associated messages such as those used for rules, views and forms should also be copied. Doing this should resolve this "ROP Error."

Exchange 2013 - What does good mailflow look like?

posted 20 Aug 2015, 13:41 by Tristan Self

You'll probably find yourself using the message tracking logs to find if an email has gone missing. But what should a normal working mail transaction look like? Well below shows it, where the mailboxes are stored on the same server.


This is a message going from to Basically if it says DELIVER STOREDRIVER, it means the message has gone into the mailbox, if it doesn't appear, it means there's some spam filtering or weird rules setup in the users Outlook that is putting it somewhere else!

Microsoft Exchange 2013 Sending Junk to the User's Outlook "Junk E-Mail" Folder

posted 6 Aug 2015, 08:26 by Tristan Self   [ updated 6 Aug 2015, 08:32 ]

In Exchange 2013 you can set an email to be put in the user's Junk E-Mail folder based on if you think it is SPAM or not. This doesn't use the Exchange built in spam filtering, it assumes you have a spam filter external to your Exchange environment that can tag an email that it thinks is spam or possible spam.

In my case we had a Barracuda Spam Firewall, this would pass messages with a spam score of 0 to 3.5, would tag messages with a spam score of 3.6 to 5.9 and block 6 and over. The tagging involved adding [POSSIBLESPAM] to the subject line and sending the message on to Exchange. This caused some confusion to users who wondered if it was spam or not and also didn't want it in their inbox. So to configure this you need to use transport rules in Exchange, here's the process:

1. First your anti-spam product will need to tag the subject line with [POSSIBLESPAM].

2. Within Exchange create a transport rule as shown below, this should come before all your other rules (probably).
(Click to increase image)

This rule catches any messages with [POSSIBLESPAM] and then setting the SCL tag of the email to 8.

3. Now at this point Exchange needs to be checked to ensure it will process the SCL tag of the email accordingly. The documentation for Exchange says that email which has a an SCL tag of 7 or over for the configured SCLJunkThreshold say, will be sent to Junk Email. However I've found it means an SCL tag of over 7, i.e. 8 and above.

4. Configure the -SCLJunkThreshold to 7 with this command:

set-OrganizationConfig -SCLJunkThreshold 7

5. Now test that the a message which is tagged ends up in your Junk mail folder within Outlook. If its tagged with [POSSIBLESPAM] its set with an SCL of 8, and the message stuck in the Junk email folder.

Microsoft Exchange 2013 Automated PST Import Script

posted 27 Jul 2015, 07:32 by Tristan Self

I needed to have an automated way to bulk import a load of PST files into Exchange 2013. In my case all the files were named as follows: so for example:

You can run this command from an Exchange PowerShell console, bear in mind that you'll need to change your domain name on the New-MailboxImportRequest command as you need to change the FilePath too to match the place were the PST files are for import. Note this must be a UNC path, even if they are stored locally on the Exchange server.

You, if you haven't done it already need to grant the user that will be running the task the rights to perform an import or export, to do this run this command, note you only need to do this once.

New-ManagementRoleAssignment –Role “Mailbox Import Export” –User "DOMAIN\USER"

New-ManagementRoleAssignment –Role “Mailbox Import Export” –SecurityGroup "DOMAIN\GROUP"

So here is the script, pop the files in the location, adjust the DOMAIN and filepath to match what you need it to be then you can run it from the Exchange 2013 PowerShell console or from the PowerShell ISE.

### AutomatedMailboxImport.ps1
### This script automatically imports PST files into a users mailbox based on the name of the file named
# as the username.

# Uncomment this line for testing within the Windows PowerShell ISE.
add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010

# initialize the items variable with the contents of a directory
$items = Get-ChildItem -Path "g:\import" -Filter *.pst

# Print to the screen, what this script is now doing.
Write-Host "Importing PST files into Exchange Mailboxes"

# enumerate the items array
foreach ($item in $items)
      # if the item is not a directory, then process it.
      if ($item.Attributes -ne "Directory")
            Write-Host "Processing the file: $item"
            $importfilename = $item.Name
            # If it contains a substring of @ then we want to chop this off to create the username.
            if ($item.Name -match
'@') {
                # the filename contains a
'@' we want to get only the first part of the filename as the username.
                $importusername = ($item.basename -split
            } else {
                # the filename didn't contain a
'@', so we can just use the file base name.
                $importusername = $item.BaseName

            Write-Host "Import Filename: $importfilename"
            Write-Host "Username: $importusername"

            New-MailboxImportRequest -Mailbox "DOMAIN\$importusername" -FilePath “\\SERVER\g$\import\$importfilename" -BadItemLimit Unlimited –AcceptLargeDataLoss

Once you've run it, it will have queued up all the imports, you can look at their current state of import with:

get-mailboximportrequest | get-mailboximportrequeststatistics

Once they have all been imported, you can clean them up with:

Get-MailboxImportRequest -Status Completed | Remove-MailboxImportRequest

Microsoft Exchange 2013 PowerShell Useful Scripts

posted 5 Jun 2015, 05:50 by Tristan Self

There's some basic tasks which are good to automate, to save you some time, you can configure them to run as a scheduled task.

First step is to create a user account to run the scripts, this account should have access to change Exchange and change Active Directory, lets call the account: exchangeserviceuser.

To run a PowerShell script from a scheduled task you should create a scheduled task with the following settings:



< different on each script  >



Use the following user account:


Run whether user is logged on or not. (Ticked)

Run within highest privileges. (Ticked)


Configure for:

Windows 7, Windows Server 2008 R2



Start a program

Program Script:


Add Arguments (optional):

-command ". 'c:\Program Files\Microsoft\Exchange Server\v15\Bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; c:\scripts\<different on each script>.ps1"

Start in (optional):

< blank >

The PowerShell scripts are shown below for each task:


### AddressBookPolicy.ps1
### This script sets the address book policy for all users.

# Uncomment this line for testing within the Windows PowerShell ISE.
#add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010

$allmailbox = get-mailbox -ResultSize Unlimited -OrganizationalUnit "OU=Users,DC=domain,DC=co,DC=uk"

Write-Host "Applying Address Book Policies to"$allmailbox.count"Staff accounts......"

$i = 0

Foreach ($item in $allmailbox) {
    $i = $i + 1
    Set-Mailbox -Identity ($item.alias) -AddressBookPolicy "Address Book Policy"

Write-Host "Processing Complete!"
Write-Host ""
Write-Host $i "Accounts Processed"


### MailboxPerm.ps1
### This script sets the calendar sharing permissions for all users.

# Uncomment this line for testing within the Windows PowerShell ISE.
#add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010

$allmailbox=get-mailbox -ResultSize Unlimited -OrganizationalUnit "OU=Users,DC=domain,DC=co,DC=uk"
Foreach ($item in $allmailbox) {

    Set-mailboxfolderpermission –identity ($item.alias+’:\calendar’) –user Default –Accessrights Reviewer

Set-mailboxfolderpermission -identity ("mtgfm1:\calendar") -user Default -Accessrights AvailabilityOnly
Set-mailboxfolderpermission -identity ("mtgfm2:\calendar") -user Default -Accessrights AvailabilityOnly
Set-mailboxfolderpermission -identity ("mtgfm3:\calendar") -user Default -Accessrights AvailabilityOnly
Set-mailboxfolderpermission -identity ("mtgfm4:\calendar") -user Default -Accessrights AvailabilityOnly


### MailboxRetention.ps1
### This script sets the Archive and retention policy for all mailboxes.

# Uncomment this line for testing within the Windows PowerShell ISE.
#add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010

Get-Mailbox -Resultsize Unlimited | Set-Mailbox -RetentionPolicy "Oaklands Archive and Retention Policy"
Get-Mailbox -Resultsize Unlimited | Set-Mailbox -ArchiveQuota 25GB -ArchiveWarningQuota 20GB


Get-OWAMailboxPolicy | Set-OWAMailboxPolicy –AllowOfflineOn NoComputers
Get-OWAMailboxPolicy | Set-OWAMailboxPolicy -setphotoenabled:$false
Get-CASMailbox -ResultSize Unlimited | Set-CASMailbox -OWAMailboxPolicy Default


### StaffAutomaticCreateMailbox.ps1
### This script enables the mailbox on all users yet to have a mailbox enabled.

# Uncomment this line for testing within the Windows PowerShell ISE.
#add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010

# Get a list of all the users within the OU within Active Directory.
$allusers = Get-AdUser -Filter * -SearchBase "OU=Users,DC=domain,DC=co,DC=uk" |  select samaccountname

Write-Host ""
Write-Host "Starting to process" $allusers.count "user accounts:"
Write-Host ""

$i = 0

Foreach ($item in $allusers) {

    if (!(Get-Mailbox $item.samAccountName -ErrorAction SilentlyContinue)) {
        Write-Host $item.samAccountName "- No Mailbox Exists, Creating....."
        Enable-Mailbox -Identity $item.samAccountName

        $i = $i + 1
    } else {
        Write-Host $item.samAccountName "- Mailbox Exists"
Write-Host ""
Write-Host "Account processing complete!"
Write-Host $allusers.count "user accounts processed," $i "mailboxes created."

Exchange 2013 Message Tracking Logs

posted 28 Apr 2015, 02:52 by Tristan Self   [ updated 27 Oct 2016, 04:55 ]

In Exchange 2013 the message tracking log viewer has gone, you need to view the tracking logs from PowerShell.

Here's a basic command to make that happen:

Get-MessageTrackingLog -Start "04/26/2015" -End "04/28/2015" -Sender "" -Recipient "" | Out-GridView

Okay this shows you the logs from a particular sender to a particular recipient and shows it in the GridView, this is a nice GUI type view with nice size adjustable columns. Obviously more you can tweak on this with more arguments on the command line.

If you would like the see a column with the time and date included you need to run this command:

Get-MessageTrackingLog -Start "04/26/2015" -End "04/28/2015" -Sender "" -Recipient "" | select-object timestamp,EventId,Source,Sender,Recipients,MessageSubject| Out-GridView

To search across all the transport servers in your organisation, i.e. if you are trying to track down a particular message across many exchange servers run the following:

Get-TransportServer | Get-MessageTrackingLog -Sender "" -Recipients ""  | sort-object Timestamp | select-object timestamp,eventid,source,sender,recipients,messagesubject | Out-GridView

After Exchange 2013 Migration, old 2010 server is still listed as "provisioned server"

posted 21 Apr 2015, 05:39 by Tristan Self

After a successful Exchange 2013 migration, the old exchange 2010 object was left behind. When opening Exchange 2013 EAC under the "Servers" option, "Servers" tab, you can see it listed as a "provisioned server".

For some reason this is not removed from AD automatically when Exchange 2010 is uninstalled from the server, so you need to remove it manually.

Using ADSIEdit, open the "Configuration" node, then "CN=Services", then "CN=Microsoft Exchange" then "CN=<organisation name>", then "CN=Administrative Groups", then "CN=Exchange Administrative Group (FYDIBOHF23SPDLT)", then "CN=Servers" under this you'll see the nodes for each Exchange server including the old 2010 server(s).

Delete the node for the old Exchange 2010 server(s).

Open up EAC, refresh and you'll see the object has gone.

Exchange 2010 to Exchange 2013 Migration - Outlook Anywhere Clients Username/Password Prompt Appears

posted 13 Jan 2015, 04:24 by Tristan Self

I'm in the middle of a migration from Exchange 2010 to Exchange 2013 at the moment. All was going well until I repointed the DNS records to the Exchange 2013 CAS servers.

In Exchange 2013 all client connectivity is now made using RPC over HTTPS (a.k.a Outlook Anywhere) unlike Exchange 2010 where only external clients use this and internal clients still use RPC over TCP as in the old days.

So the Microsoft approved method for migration is to setup your new Exchange 2013 CAS servers, then repoint all clients to use this. Your Exchange 2013 dwelling users will be proxied to the Exchange 2013 mailbox servers as expected (and as configured by the autodiscover DNS record). The Exchange 2010 dwelling users (who have yet to be moved) will be proxied through the Exchange 2013 CAS servers to the Exchange 2010 back-end if they are external to the organisation, or just redirected to the Exchange 2010 back-end if they are accessing internally.

So after redirecting the DNS the Exchange 2013 clients worked fine internally and externally. The Exchange 2010 clients worked fine internally, but externally, users started to complain about username/password boxes when using Outlook Anywhere from the laptops at home. Entering the username and password didn't help, it would just keep prompting.


It turns out that Exchange 2013 will use NTLM as default, therefore the server to which it is proxying the RPC over HTTPS request must also support NTLM authentication too. If it doesn't the clients trying to use it will connect and try to authenticate with Basic (plain) authentication to the Exchange 2013 CAS servers and be endlessly prompted for credentials.

Workaround / Proof

I took an external client with a user that was still on the Exchange 2010 server, outside the network the Outlook client attempted connection and failed prompting for password.

Check the RPC over HTTPS settings in Outlook, you'll notice it says "Basic Authentication", I changed this to NTLM authentication, re-started outlook, entered the password and hey presto I'm in. So this proves that the authentication mismatch between Exchange 2010 and Exchange 2013 is the issue. This isn't the solution though because autodisover will correct this setting again as this is not what the server is configured to so we need a permanent fix.


1. Run the command: Get-OutlookAnywhere | fl from the Exchange 2013 server.

You are looking for the line "ExternalClientAuthenticationMethod" this should be set to NTLM, in my case it was set to Basic.

2. Logon to the Exchange 2010 server and use the Exchange Management Console to change the Outlook Anywhere setting to NTLM. You can find this under “Server Configuration”->”Client Access” then right click on the server object and select “Properties”, look for the “Outlook Anywhere” tab, and then change the radio button to NTLM under there.

3. You also need to go to IIS Manager on the Exchange 2010 server and then drill down to the "RPC" virtual directory and click on "Authentication" Under here Windows Authentication (i.e. NTLM) was not set. To correct it I had to click Enable, then on the right hand side click "Providers..." and move NTLM to the top of the list above "Negotiate" Save these settings.
Restart IIS On the Exchange 2010 server. Now try again, you should find that the client can connect.

4. You may well need to close and reopen the client after a few minutes; this is so it gives time for the Autodiscover service time to change the setting it puts out to clients. And so your External Outlook client can pick up that for Outlook Anywhere it is supposed to use NTLM rather than Basic (plain) authentication.

Exchange 2013 - Setup POP3 Service via CAS Servers

posted 12 Jan 2015, 02:36 by Tristan Self

If you're like us you still have old legacy applications that use POP3 for various things. On Exchange 2013 the way POP3 works has changed slightly. Now you access a POP3 mailbox via the CAS servers that proxy you to the mailbox on the Mailbox role server(s).

Our application only supports plain text authentication, but this unsurprisingly is disabled by default, to enable POP3 and turn on plain text authentication follow these steps below. Note in my setup we have two CAS Role servers and two Mailbox Role servers.

1. Start the Microsoft Exchange POP3 services on each of the CAS Array servers. And the POP3 back end services on the Mailbox servers.

2. Set it to Automatic start for all these services.

3. Then on the EAC, go to the “Servers”, then click the “Servers” tab at the top. Now for both the CAS servers you need to do the following:

3.1. Click on the CAS Server, click on the edit button (pencil).

3.2. Click on the “POP3” option on the left hand side.

3.3. Set “Logon Method” to “Basic Authentication (Plain Text)”.

3.4. Repeat for all the other CAS servers, then restart the POP3 service on all the CAS servers and Mailbox servers. Then you are ready to test.

4. To test it is working telnet to the CAS array DNS name on port 110. And attempt to login by running the commands as below:

+OK The Microsoft Exchange POP3 service is ready.

USER username


PASS password

+OK User successfully logged on.


+OK 8 31602

1 4017

2 4009

3 4013

4 3521

5 3995

6 4004

7 4016

8 4027



5. Now repoint your applications to use the CAS array DNS name on the Exchange 2013 infrastructure.

1-10 of 25