Finding Exchange Database hidden mailboxes.

Story:

Maybe you have been in this situation before, trying to delete an Exchange database after moving all of its mailboxes, arbitration or archives to another server or database but it didn’t work and said that there is still something in the database? 

Now I am in a similar situation however I checked nothing in the database as you can see in the below screenshot. 

I have noticed that these issues could happen when an Exchange server gets broken or forcefully deleted from AD without properlty uninstalling it. some traces of system mailboxes might remain there with database attributes pointing to the database. 

Solution:

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Snapin
Function Get-HiddenMailbox
{
  [CmdletBinding()]
  Param(
  [Parameter(Mandatory=$True)][string]$Path,
  [Parameter(Mandatory=$True)][string]$Database
  )
<#Check for any remaining mailboxes in a database that you can’t delete.

 

[PS] C:\Program Files\Microsoft\Exchange Server\V15\scripts>Remove-MailboxDatabase a-sb-com-udb1-v1
This mailbox database contains one or more mailboxes, mailbox plans, archive mailboxes, public folder mailboxes or
arbitration mailboxes, Audit 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 public folder mailboxes in this database, run the command Get-Mailbox -Database <Database ID>
-PublicFolder. To get a list of all arbitration mailboxes in this database, run the command Get-Mailbox -Database
<Database ID> -Arbitration. To get a list of all Audit mailboxes in this database, run the command Get-Mailbox
-Database <Database ID> -AuditLog. 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. To disable a public folder mailbox so that you can delete the
mailbox database, run the command Disable-Mailbox <Mailbox ID> -PublicFolder. To disable a Audit mailbox so that you
can delete the mailbox database, run the command Get-Mailbox -AuditLog | Disable-Mailbox. 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>.
  + CategoryInfo          : InvalidOperation: (a-sb-com-udb1-v1:DatabaseIdParameter) [Remove-MailboxDatabase], Assoc
 iatedUserMailboxExistException
  + FullyQualifiedErrorId : [Server=SBG-MX03,RequestId=480ce97d-8492-41a9-82fa-93ed30efe652,TimeStamp=6/28/2022 9:04
 :09 AM] [FailureCategory=Cmdlet-AssociatedUserMailboxExistException] 45D30D02,Microsoft.Exchange.Management.System
ConfigurationTasks.RemoveMailboxDatabase
  + PSComputerName        : server.domain.local
#>

 

#Fist get DB’s HomeMDB value

 

#Write-host ‘Enter your Database Name’ -ForegroundColor Red -BackgroundColor Black

 

$DN = (Get-MailboxDatabase $Database).distinguishedName
$Date = (Get-date).ToString(“MM-dd-yyyy”)

 

$Mailboxes = Get-ADObject -filter {(HomeMDB -eq $DN)}

 

$QueryResult = $Mailboxes.count
$CurrentCount = 0

 

foreach ($Mailbox in $Mailboxes){

 

  try{
       $ObjectProps = [Ordered]@{ ‘DisplayName’ = $Null; ‘UserPrincipalName’ = $Null; ‘Database’ = $Null; ‘Mailbox’ = $Null; ‘Arbitration’ = $Null; ‘Archive’ = $Null; ‘Audit’ = $Null; ‘Monitoring’ = $Null; ‘ErrorResponse’ = $Null}
       $MBX = $Mailbox.name
       $CurrentCount ++

 

      Write-Progress -Activity “Checking Hidden Mailboxes in the database $DB $CurrentCount of $QueryResult -Status “Fetching $MBX -PercentComplete (($CurrentCount / $QueryResult) * 100)
       $Result = New-Object -TypeName PSObject -Property $ObjectProps

 

       $MailboxResult = Get-mailbox -Identity $MBX -ErrorAction SilentlyContinue
      if ($MailboxResult){Write-Host “User $MBX. is a Mailbox” -ForegroundColor Green  }
          $ArbResult = get-mailbox -Identity $MBX -Arbitration -ErrorAction SilentlyContinue
          if($ArbResult){Write-host “User $MBX. is an Arbitration Mailbox” -ForegroundColor White }

 

               $ArchiveResult = get-mailbox -Identity $MBX -Archive -ErrorAction SilentlyContinue
                  if($ArchiveResult){Write-host “User $MBX. is a Archive” -ForegroundColor Red}
                              $AuditResult = get-mailbox -Identity $MBX -AuditLog -ErrorAction SilentlyContinue
                                if($AuditResult){Write-host “User $MBX. is a Audit Mailbox” -ForegroundColor DarkRed}
                                      $Monitoring = get-mailbox -Identity $MBX -Monitoring -ErrorAction SilentlyContinue
                                          if ($Monitoring){Write-host “User $MBX. is a monitoring Mailbox” -ForegroundColor Yellow }

 

          $Result.DisplayName = $MBX
          $Result.UserPrincipalName = (Get-ADUser -Identity $Mailbox.DistinguishedName).UserprincipalName
          $Result.Database = $DB
          $Result.Mailbox = $MailboxResult
          $Result.Arbitration = $ArbResult
          $Result.Archive = $ArchiveResult
          $Result.Audit = $AuditResult
          $Result.Monitoring = $Monitoring
          $Result.ErrorResponse = ‘#N/A’
          $NewPath = $path.Split(‘.’)[0] + ‘_’ + $date + ‘.csv’

 

          $Result | export-csv -path $NewPath -Delimiter ‘;’ -NoTypeInformation -NoClobber -Append -Encoding utf8
          }
              Catch{
              Write-Warning $_.Exception.Message}

 

              $Result | export-csv -path $NewPath -Delimiter ‘;’ -NoTypeInformation -NoClobber -Append -Encoding utf8
     }
}

Prerequisites:

– You will have to run this script from Exchange Server.

– An account that can connect to Active Directory with at least read permission and Exchange admin read role. 

The script will utilize Active Directory and Exchange to get the Database’s distinguished name and scan any AD User Object that has this DB’s DN and post it to you as an output. 

Example:

Get-HiddenMailbox -Path ‘C:\example.csv’ -database ‘Affected Database’

As you can see in the below screenshot, I got mostly health mailboxes which should not really be a problme in case you’re deleting database, however I got one system mailbox that is still there and pointing to this Database however, I already have scanned the database for any arbitration mailboxes but Exchange CMDlet showed none. 

Now that I know which user it is, the solution for me to be able to remove/delete this database which I no longer need is to delete this AD user object since its no longer in use by Exchange. 

You won’t be able to get this mailbox through get-mailbox cmdlet because its not an active mailbox. however you will find it in AD. 

So I deleted the mailbox mentioned below and next I am going to try and delete the mailbox database in question. 

Result

Here’s the result after deleting the user in Question.

moh10ly

Recent Posts

Reset passwords for Active Directory Users

Reset and manage your Active Directory users' Passwords Active Directory is one of the most…

1 year ago

Setting up ADConnect and PTA (Password auth through) servers agents behind proxy

If you're using a Proxy server in your firewall or in your network and have…

1 year ago

Get Report of Active Directory Locked Accounts and Machine they logged in from

Story:I got some clients  that have reported some of their users being locked out and…

1 year ago

Checking and Providing Full and SendAs delegate access on O365 Exchange Online

Delegate Permissions This is a code that I have wrote recently to check if an…

1 year ago

Retrieving attachments from Exchange mailbox using python

Story: I got a request from a client who constantly gets CVs and have to…

2 years ago

550 relay not permitted distribution group contact

550 relay not permitted distribution group contact Symptoms When trying to add an external contact…

2 years ago