0 votes

Currently our organization does not delete Active Directory accounts when users leave the company. Long story but the short of it is, occasionally users come back to the company and we have an automated process that re-enables / re-provisions their account (moves to certain OUs, adds to groups, creates home drive, etc). This process works great with the exception of the account's mailbox.

We retain disabled mailboxes for 180 days and what ends up happening is that our automated process re-provisions this previously 'terminated' employee and creates a new mailbox for the user. These users inevitably request their old mailbox data and it becomes a cumbersome process to delete the newly created mailbox and find/reconnect the old one.

Our process uses a custom boolean property within the web-front end of ADAXES to indicate whether or not the to-be-re-provisioned account should have a mailbox. If the property returns True then a mailbox gets created via a business rule that executes after the user has been re-provisioned.

What we would like to do is to have a business rule that executes after the user has been re-provisioned which checks to see if the account's mailbox exists in a disconnected state and if it does then A) re-connect it to the account being re-provisioned or if this is not possible B) display a warning that the account may have a mailbox in a disconnected state and may need to be reconnected manually. If the check returns false (no disconnected mailbox found) then create a new mailbox.

I have exchange powershell code that will locate the disconnected mailbox using the account's DisplayName below:

Get-MailboxDatabase | Get-MailboxStatistics | ?{$_.DisconnectDate -and ($_.displayname -eq “%displayName%”)} | fl DisplayName,MailboxGuid,ServerName,Database,DisconnectDate

Is it possible to leverage this code within a business rule to accomplish our goal? Thanks in advance!

by (610 points)
0

Hello,

How do you re-provision users? Is it done with the help of a Custom Command?

0

Actually, we use a business rule and a custom attribute.

On the front-end we utilize the user-picker pointed at our decommissioned user account's OU. This "home page action" uses a predefined field with a custom attribute with the default value of 'Zombie%adm-RandomInteger%' along with a customized form to make changes to the basic user attributes like Department, Job Title, Manager, Mailbox Required (boolean), etc.

The business rule runs after the above changes have been made (after updating a user) and if it sees that the custom attribute has changed then it begins "reviving" the account. The account gets enabled, the password is reset to the default, the password is set to change on next logon, the user is moved to another OU, etc.

If the "Mailbox Required" field is set to True (another condition in the above mentioned business rule) then the mailbox is created.

1 Answer

0 votes
by (216k points)
selected by
Best answer

Hello,

The minimum information necessary to re-connect a disconnected mailbox are the GUID of the disconnected mailbox and the Distinguished Name (DN) of the Exchange mailbox store where the mailbox resides. Usually, this information is stored in the properties of a user account, but when a mailbox is disconnected, Exchange removes these properties from the user account. To be able to successfully reconnect the database on re-provisioning, we recommend you to save this information in certain properties of the user whose mailbox is being disconnected. To do this, you need to add an action to the Custom Command that you use for user deprovisioning that will save this information once a user is deprovisioned.

To store a mailbox GUID and a mailbox store DN, you can use Adaxes virtual attributes. Such attributes are not stored in Active Directory, but you may use them the same as any other properties of directory objects. For mailbox GUIDs you'll need an attribute that can store binary values, for example, CustomAttributeBinary1, for mailbox stores you'll need a string attribute, for example, CustomAttributeText1.

Then, you can add an action to the Business Rule that performs re-provisioning. The action will run a PowerShell script that will search for a disconnected mailbox with a GUID and located in a mailbox store that are specified in the virtual attributes. If such a mailbox is found, the action will reconnect it. If it is not found (the mailbox has already been deleted by Exchange) or if a GUID and a mailbox store are not specified in the virtual attributes, it will create a new mailbox.

To implement such a solution:

I. Add an action that saves the mailbox GUID and mailbox store DN in virtual attributes
To add an action that will save the mailbox GUID and mailbox store DN in virtual attributes to your Custom Command that you use for deprovisioning:

  1. Launch Adaxes Administration Console.

  2. In the Console Tree, expand the service node that represents your Adaxes service.

  3. Navigate to and select the Custom Command that you use to deprovision users.

  4. Select the set of actions and conditions, in which the user's mailbox gets disconnected.

  5. Click the Add Action button.

  6. Select the Run a program or PowerShell script action and paste the following script:

     $mbGUIDProperty = "adm-CustomAttributeBinary1" # TODO: modify me
     $mbStorePathProperty = "adm-CustomAttributeText1" # TODO: modify me
    
     # Get mailbox guid and mailbox store dn
     $exchangeGuid = $Context.TargetObject.Get("msExchMailboxGuid")
     $mailboxStoreDN = $Context.TargetObject.Get("homeMDB")
    
     # Save exchange guid and database dn in custom attribute
     $Context.TargetObject.Put($mbGUIDProperty, $exchangeGuid)
     $Context.TargetObject.Put($mbStorePathProperty, $mailboxStoreDN)
     $Context.TargetObject.SetInfo()
    
  7. In the script:

    • $mbGUIDProperty - specifies the virtual attribute that will be used to store the mailbox GUID,
    • $mbStorePathProperty - specifies the virtual attribute that will be used to store the mailbox store DN.

    Modify them, if necessary.

  8. When done, click OK.

  9. Now you need to put the action before the mailbox is disconnected, otherwise the necessary properties will be deleted by Exchange before Adaxes can save them. For this purpose use the Move Up button located at the bottom of the list of actions and conditions.

  10. When done, click Save changes.

I. Add an action that recoonects a disconnected mailbox
To add an action that will reconnect a mailbox:

  1. In the Console Tree, navigate to and select the Business Rule that re-provisions users.

  2. Select a set of actions and conditions and click the Add Action button or click the Add action to a new set link if you want to create a new action/condition set.

  3. Select the Run a program or PowerShell script action and paste the following script:

     $exchangeServer = "exchangeserver.domain.com" # TODO: Modify me
     $alias = "%username%" # TODO: modify me
     $mbGUIDProperty = "adm-CustomAttributeBinary1" # TODO: modify me
     $mbStorePathProperty = "adm-CustomAttributeText1" # TODO: modify me
    
     function CreateMailbox($alias)
     {
         # Select an Exchange mailbox store for the user based on Property Patterns
         $propertyPatternDNs = $Context.TargetObject.GetEx("adm-EffectivePropertyPatterns")
         foreach ($propertyPatternDN in $propertyPatternDNs)
         {
             # Bind to property patern
             $propertyPattern = $Context.BindToObjectByDN($propertyPatternDN)
    
             # Search an item for the Exchange mailbox store
             foreach ($item in $propertyPattern.Items)
             {
                 if ($item.PropertyName -ine "homeMDB")
                 {
                     continue
                 }
    
                 # Get the mailbox store
                 $mailboxStorageDatabase = $item.GetNextMailboxStorageDatabase($Context.TargetObject)
    
                 # Create a mailbox
                 $Context.TargetObject.CreateMailbox($alias, $mailboxStorageDatabase.AdsPath)
    
                 # Notify that the mailbox store has been used
                 $item.NotifyMailBoxStorageDataBaseIsUsed($Context.TargetObject, $mailboxStorageDatabase)
    
                 # Exit the function
                 return
             }
         }
    
     }
    
     # Get mailbox GUID and Exchange mailbox store DN from virtual properties
     try
     {
         $mailboxGuidByte = $Context.TargetObject.Get($mbGUIDProperty)
         $mailboxStoreDN = $Context.TargetObject.Get($mbStorePathProperty)
     }
     catch
     {
         # No saved information about a disconnected mailbox, a new mailbox will be created
         CreateMailbox $alias
         return
     }
    
     # Create a remote PowerShell session to the Exchange Server
     $session = New-PSSession -connectionURI "http://$exchangeServer/powershell" -ConfigurationName Microsoft.Exchange
     Import-PSSession -session $session
    
     # Search the user's disconnected mailbox
     $mailboxGuid = New-Object "System.Guid" (,$mailboxGuidByte)
     $disconnectMailbox = Get-MailboxStatistics -Database $mailboxStoreDN | Where {$_.DisconnectDate -ne $Null -and $_.Identity -eq $mailboxGuid} 
    
     # If the disconnected mailbox was not found, create a new one
     if($disconnectMailbox -eq $NULL)
     {
         CreateMailbox $alias
         return
     }
    
     # Reconnect the mailbox
     Connect-Mailbox -Identity $mailboxGuid -Database $mailboxStoreDN -User "%distinguishedName%"
    
     # Exit remove session, free up resources
     Remove-PSSession -Session $session
    
  4. In the script:

    • $mbGUIDProperty - specifies the virtual attribute that will be used to store the mailbox GUID,
    • $mbStorePathProperty - specifies the virtual attribute that will be used to store the mailbox store DN,
    • $exchangeServer - specifies the fully qualified domain name (FQDN) of your Exchange Server,
    • $alias - specifies a template for generate a user's Exchange Alias (in case a new mailbox needs to be created).

    Modify them, if necessary.

  5. When done, click OK, then click Save changes.

0

Wow, this is a very thorough reply. Thank you!

I'm kicking the tires on this solution and will get back to you when I've tested it out.

0

I've been attempting a variation of the script to simply search for a mailbox within our exchange organization with the same display name as the account in question. When I run the following powershell from one of our exchange servers (we have several, all CAS/Mailbox servers) within EMS I am able to locate a disconnected mailbox with the designated displayname:

Get-MailboxDatabase | Get-MailboxStatistics | Where {$_.DisconnectDate -ne $Null -and $_.displayName -eq "testing123"} 

If I use the same code within a script executed by ADAXES I get some very strange errors saying that "The specified mailbox MailboxDatabaseName doesn't exist".

The code is below but does the remote powershell session to the exchange server operate differently in some way than executing the code directly from an exchange server within EMS? It's almost as if the pipe isn't working properly...

$exchangeServer = "ExchangeServer" # TODO: Modify me
$displayName = "testing123" # TODO: modify me

# Create a remote PowerShell session to the Exchange Server
$session = New-PSSession -connectionURI "http://$exchangeServer/powershell" -ConfigurationName Microsoft.Exchange
Import-PSSession -session $session

# Search the user's disconnected mailbox
$disconnectMailbox = Get-MailboxDatabase | Get-MailboxStatistics | Where {$_.DisconnectDate -ne $Null -and $_.displayName -eq $displayName} 

# Get-MailboxDatabase | Get-MailboxStatistics | ?{{$_.DisconnectDate} -and ($_.displayname -like "$displayName")} 
# Get-MailboxDatabase | Get-MailboxStatistics | Where {$_.DisconnectDate -ne $Null -and $_.displayName -like "$displayName"}

# If the disconnected mailbox was not found
if($disconnectMailbox -eq $NULL)
{
    $Context.LogMessage("A mailbox associated with $displayName does not exist.", "Warning")
    return
}

$Context.LogMessage("A mailbox associated with $displayName ALREADY EXISTS!.", "Warning")

# Reconnect the mailbox
# Connect-Mailbox -Identity $mailboxGuid -Database $mailboxStoreDN -User "%distinguishedName%"

# Exit remove session, free up resources
Remove-PSSession -Session $session
0

Hello,

The thing is that, for some reason, the data returned by the Get-MailboxDatabase cmdlet is of an incorrect data type when piped to another cmdlet within a remote PowerShell session. As a result, the Get-MailboxStatistics cmdlet cannot process the data passed to it by the Get-MailboxDatabase cmdlet correctly. Here's a version of the script that works around the issue:

$exchangeServer = "exchangeserver.example.com" # TODO: Modify me
$displayName = "%displayName%" # TODO: modify me

# Create a remote PowerShell session to the Exchange Server
$session = New-PSSession -connectionURI "http://$exchangeServer/powershell" -ConfigurationName Microsoft.Exchange
Import-PSSession -session $session -DisableNameChecking -AllowClobber

# Search the user's disconnected mailbox
$mailboxDatabases = Get-MailboxDatabase
$foundMailboxes = @()
foreach ($database in $mailboxDatabases)
{
    $result = Get-MailboxStatistics -Database $database.Name | Where {$_.DisconnectDate -ne $Null -and $_.displayName -eq $displayName}
    if ($result -eq $NULL)
    {
        continue
    }

    $foundMailboxes += $result
}

if ($foundMailboxes.Length -gt 1)
{
    # Found more than 1 mailbox with the specified displayName
    $Context.LogMessage("Cannot reconnect the mailbox because there is more than one object mailbox with display name $displayName", "Warning")
    return
}
elseIf($foundMailboxes -eq 0)
{
    # A mailbox with the specified displayName was not found
    $Context.LogMessage("A mailbox associated with $displayName does not exist.", "Warning")
    return
}
else
{
    $disconnectMailbox = $foundMailboxes[0]
}

# Reconnect the mailbox
Connect-Mailbox -Identity $disconnectMailbox.MailboxGuid -Database $disconnectMailbox.DatabaseName -User "%distinguishedName%"

# Exit the remote session, free up resources
Remove-PSSession -Session $session
0

Thank you for the code! This got me to where I wanted to be.

Related questions

0 votes
1 answer

Hello, I have a sheduled task running. This task checks if a user is a member of a Licensed Office 365 Group with exchange online. If the user does not have an ... the on prem exchange mailbox and the exchange online mailbox? Thanks if you have an idea!

asked Feb 24, 2023 by fabian.p (150 points)
0 votes
1 answer

Hi Everyone I want to create a custom command where I can select multiple users and then select a mailbox and give them full access to the mailbox. Is there a way to do it? Thank you for help

asked Nov 2, 2021 by Sandberg94 (340 points)
0 votes
1 answer

I want to create a custom Deprovission command which exports the mailbox of the user to a pst file, when it's completed the account should be deleted. Can this be done with adaxes? Thnx Remco

asked Jan 10, 2014 by RTiel (780 points)
0 votes
1 answer

I'd like some help with a script to revoke a users rights to a shared mailbox upon being removed from a security group. I already have the reverse, a script that adds users to a shared mailbox, if they are a member of a group, now I just need the reverse.

asked Mar 20 by dominik.stawny (160 points)
0 votes
1 answer

We are developing a process to mange mailboxes for terminated users. At the time of termination we would like to: convert the mailbox to a shared mailbox. Send an approval ... would run script to grant the manger access to the mailbox. Can this be done?

asked Oct 27, 2023 by mightycabal (1.0k points)
3,326 questions
3,026 answers
7,727 comments
544,678 users