0 votes

Hi All,

Weve switched to Office365 and Im using Adaxes to create users which is working really well. However lots of our users now have remote mailboxes which is all good except I can't run my deprovision any more as part of that process was to create a PST of the users mailbox and archive.

Is there any way to get adaxes to remote powershell and export mailboxes to PST somewhere within the office365 service so mailboxes can be stored even though the user will be removed from the users list.

Thanks,

Will

by (350 points)

2 Answers

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

Hello Will,

Unfortunately, that can't be done with Office 365 mailboxes. The only way how you can export an Office 365 mailbox is to use Outlook. You can use PowerShell to export from on-premise Exchange servers, but apparently they haven't added this feature to Office 365. Actually, it has been requested a multitude of times already and hanging on Microsoft site as 'pending review' for ages (http://mymfe.microsoft.com/Microsoft%20 ... PageLayout).

We can provide a workaround if you have a hybrid Exchange setup. In this case, we can suggest first moving the mailbox to your on-premises Exchange Server, and then exporting it locally. However, it can take quite a lot of time and cause huge traffic between your organization and Office 365. If you are OK with such a solution, we will provide you the steps to achieve it.

0

Thanks for the response, I feared this was the answer. If thats ok I'd like to look at that script and maybe test run it when we get hybrid in.

Thanks,

Will

0

Our solution may or may not work for you, we created a set of scripts that convert the de-provisioned users mailbox to a shared MB and add their manager to 'full access' permissions for 30 days, then remove the user/mailbox after that date. This is all automated through creation of scheduled tasks. If you are interested, I can share some of our scripts we use to accomplish this.

0

Hello ggallaway,

Could you share your scripts? We are also in the middle of creating something you have already accomplished :).

Thanks!

0 votes
by (300 points)

So our process is made up of the following 4 'Steps':

We created the following business rule (Note: 'Deprovision Date' is an adm-customattributedate field that we renamed)

if the 'Provide Manager Access to MB (Home Folder always provided)' property has changed AND
the User is not located under the 'Previous Employee Mailboxes (stcu.local\STCU\Shared Mailboxes)' container AND
the 'Deprovision Date' property has changed then
action: Run Powershell script 'create a scheduled task to de-provision the user' for the user
action: Modify the User: set Account Expires to '%adm-customattributeDate1, +5m%'
action: send e-mail notification (user deactivation scheduled by %initiator%)

the Script within 'create a scheduled task to de-provision the user' is as follows:

# Scheduled task settings
$containerName = "Deprovisioned User Processing" #must match a folder under scheduled tasks
$taskName = "Initial Deprovision - %username%" 
$taskDescription = "This will process the disabling of the user account and provide Manager with access" 
$deleteTaskAfterExecution = $True
$now = (Get-Date).addMinutes(5)

if("%adm-CustomAttributeDate1%" -lt $now){

    $ProcessTime = $now.addminutes(5)

}else {
    $ProcessTime = "%adm-CustomAttributeDate1%"
}

# Script for action
$scriptDescription = "Process Deprovisioning"
$scriptToExecute = {
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")
Import-Module Adaxes

$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly("localhost")

$userDN = (Get-AdmUser -Identity "%objectGUID%" -AdaxesService "localhost").DistinguishedName
$user = $admService.OpenObject("Adaxes://$userDN", $NULL, $NULL, 0)

$commandID = "{fb93226e-d3e7-4b97-afde-5262b3c2b931}" #This is a Custom Command (deprovision step 1) and the GUID will need to be changed to match your environment
$user.executecustomCommand($commandID)
}

function CheckNameForUnique($taskPath)
{
    try
    {
        $task = $Context.BindToObject($taskPath)
        return $False
    }
    catch
    {
        return $True
    }
}

# Bind to the Scheduled Tasks container
$scheduledTasksPath = $Context.GetWellKnownContainerPath("ScheduledTasks")
$scheduledTasksPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $scheduledTasksPath
$containerPath = $scheduledTasksPathObj.CreateChildPath("CN=$containerName")
$container = $Context.BindToObject($containerPath)

# If the task name is not unique, generate a unique one
$uniqueName = $taskName
for ($i = 1; $True; $i++)
{
    $taskPath = $containerPath.CreateChildPath("CN=$uniqueName")
    if (CheckNameForUnique $taskPath)
    {
        break
    }
    $uniqueName = "$taskName`_$i"
}

# Create a Scheduled Task
$task = $container.Create("adm-ScheduledTask", "CN=$uniqueName")

$task.ObjectType = "domainDNS"
$task.Description = $taskDescription
$task.Disabled = $False
$task.ExecutionMoment = "ADM_BUSINESSRULEEXECMOMENT_BEFORE"
$task.OperationType = "none"
$task.DeleteTaskAfterExecution = $deleteTaskAfterExecution

$recurrencePattern = $task.GetRecurrencePattern()
$recurrencePattern.RecurrenceType = "ADM_RECURRENCEPATTERNTYPE_ONCE"
$recurrencePattern.PatternStartDateTime = $ProcessTime
$task.SetRecurrencePattern($recurrencePattern)

$task.SetInfo()

# Define actions and conditions

# Create a new set of actions and conditions
$actionsAndConditions = $task.ConditionedActions.Create()
$actionsAndConditions.ConditionsLogicalOperation = "ADM_LOGICALOPERATION_AND"
$actionsAndConditions.SetInfo()

# Add Run PowerShell Script action
$action = $actionsAndConditions.Actions.CreateEx("adm-RunScriptAction")
$action.ExecutionOptions = "ADM_ACTIONEXECUTIONOPTIONS_SYNC"
$scriptAction = $action.GetAction()
$scriptAction.ScriptType = "ADM_SCRIPTTYPE_POWERSHELL"
$scriptAction.ScriptDescription = $scriptDescription
$scriptAction.Script = $scriptToExecute.ToString()
$action.SetAction($scriptAction)
$action.SetInfo()
$actionsAndConditions.Actions.Add($action)

# Add the set to the Scheduled Task
$task.ConditionedActions.Add($actionsAndConditions)

# Set the scope of activity to All Objects
$scopeItem = $task.ActivityScopeItems.Create()
$scopeItem.BaseObject = $NULL
$scopeItem.Type = "ADM_SCOPEBASEOBJECTTYPE_ALL_DIRECTORY"
$scopeItem.Inheritance = "ADS_SCOPE_SUBTREE"
$scopeItem.Exclude = $False
$scopeItem.SetInfo()

$task.ActivityScopeItems.Add($scopeItem)

The Custom Command deprovision user step 1 is configured as follows:

If the User is not located under the 'Previous Employee Mailboxes ([domainpath to location to house 'old mailboxes']\)' container then
Action:Execute custom command 'Convert Mailbox to Shared (Sub-routines)' for the User


         $mailboxType = "Shared" # TODO: uncomment the type you need
# $mailboxType = "Room"
# $mailboxType = "Equipment"

# Get the object ID in Office 365
try
{
    $objectId = [Guid]$Context.TargetObject.Get("adm-O365ObjectId")
}
catch
{
    $Context.LogMessage("The user doesn't have an Office 365 account", "Warning")
    return
}

try
{
    # Connect to Exchange Online
    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $Context.GetOffice365Credential() -Authentication Basic -AllowRedirection
    Import-PSSession $session -AllowClobber -DisableNameChecking

    # Change mailbox type


    Set-Mailbox $objectId.ToString() -Type $mailboxType


}
catch
{
    $Context.LogMessage($_.Exception.Message, "Warning")
}
finally
{
    # Close the remote session and release resources
    Remove-PSSession $session
}

Action:Move the User to 'Previous Employee Mailboxes ([domainpath to location to house 'old mailboxes']\)'
Action:Reset password for the User
Action:Modify the User: disable the account
Action:Deactivate Office 365 account of the User: revoke all licenses
Action:Run PowerShell script 'Remove User from All Groups' for the User

# E-mail message settings
$to = "helpdeskemail@company.com" # TODO: modify me
$subject = "List of groups user '%name%' has been removed from" # TODO: modify me
$reportHeader = "<b>User {0} has been removed from the following groups:</b><br/>" # TODO: modify me
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # TODO: modify me

# Get the default Web Interface address
$webInterfaceAddress = "%adm-WebInterfaceUrl%"
if ([System.String]::IsNullOrEmpty($webInterfaceAddress))
{
    $Context.LogMessage("Default web interface address not set for Adaxes service. For details, see http://www.adaxes.com/help/?HowDoI.ManageService.RegisterWebInterface.html", "Warning")
}

# Add link to user
$userGuid = [Guid]$Context.TargetObject.Get("objectGuid")
$reportHeader = [System.String]::Format($reportHeader, "<a href='$webInterfaceAddress`ViewObject.aspx?guid=$userGuid'>%name%</a>")

# Get all groups user is a direct member of
$groupGuidsBytes = $Context.TargetObject.GetEx("adm-DirectMemberOfGuid")
$totalRemovedGroups = $groupGuidsBytes.Length - 1
if ($totalRemovedGroups -eq 0)
{
    $Context.LogMessage("This user is a member only the primary group", "Information")
    return
}

# Get the Primary Group ID
$primaryGroupId = $Context.TargetObject.Get("primaryGroupID")

$reportHeader += "<ol>"
foreach ($groupGuidBytes in $groupGuidsBytes)
{
    # Bind to the group
    $groupGuid = [Guid]$groupGuidBytes
    $groupPath = "Adaxes://<GUID=$groupGuid>"
    $group = $Context.BindToObject($groupPath)

    # Skip the group if it is the user's Primary Group
    if ($group.Get("primaryGroupToken") -eq $primaryGroupId)
    {
        continue
    }

    # Remove user from the group
    $group.Remove($Context.TargetObject.AdsPath)

    # Add group to the report
    $groupDisplayName = [Softerra.Adaxes.Utils.ObjectNameHelper]::GetObjectName($groupPath, "IncludeParentPath")
    $reportHeader += "<li><a href='$webInterfaceAddress`ViewObject.aspx?guid=$groupGuid'>$groupDisplayName</a></li>"
}
$reportHeader += "</ol>"

# Build report
$htmlReport = $reportHeader + "<br/>Total remove groups:$totalRemovedGroups" + $reportFooter

# Send mail
$Context.SendMail($to, $subject, $NULL, $htmlReport)

Action:Execute custom command 'Copy Users Home folder to manager (Sub-routines)' for the User

[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$userDN = "%distinguishedName%"
$managerUserName = "%adm-ManagerUserName%"
$managerUserName = $managerUserName.Split("@")
$destDir = "\\somenetworkshare\$($managerUserName[0])\PreviousEmployeeData" #TODO Modify Me
$archivePath = "$destDir\%username%\%username%.zip"
$compressionLevel = 1

#Create Backup folder if not exist
If (!(Test-Path $destDir)) {
 
   New-Item -Path $destDir -ItemType Directory
}
If (!(Test-Path -Path "$destDir\%username%")){

   New-Item -Path "$destDir\%username%" -ItemType Directory
}

# Connect to Adaxes service
$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly("localhost")

# Bind to the user
$user = $admService.OpenObject("Adaxes://$userDN", $NULL, $NULL, 0)

try
{
# Archive the user's home folder
$user.ArchiveHomeDirectory($archivePath, $compressionLevel)
}
catch
{
    $Context.LogMessage("Archive Home Directory Failed", "Error") 
}

Action:Modify the User: clear msRTCSIP-PrimaryHomeServer, clear msRTCSIP-UserEnabled, clear msRTCSIP-OptionFlags, clear msRTCSIP-PrimaryUserAddress
Action:Modify the User: set Account Expires to '%accountExpires,+31d%'
Action:Delete the home directory of the User
Action:Run PowerShell script 'Set Manager Notification Scheduled Task' for the User

# Scheduled task settings
$containerName = "Deprovisioned User Processing" #must match a folder under scheduled tasks
$taskName = "Notify Manager 10days to deprovision - %username%" 
$taskDescription = "This will process the disabling of the user account and provide Manager with access" 
$deleteTaskAfterExecution = $True
$ProcessTime = (Get-Date).adddays(20)

# Script for action
$scriptDescription = "Notify Manager of impending user deletion" # TODO: modify me
$scriptToExecute = {
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")
Import-Module Adaxes

$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly("localhost")

$userDN = (Get-AdmUser -Identity "%objectGUID%" -AdaxesService "localhost").DistinguishedName
$user = $admService.OpenObject("Adaxes://$userDN", $NULL, $NULL, 0)
$commandID = "{b4b66610-be71-403a-a6b7-8bcf51d200ef}" #Custom Command GUID Deprovision step 2 TODO: Change Me
$user.executecustomCommand($commandID)
}

function CheckNameForUnique($taskPath)
{
    try
    {
        $task = $Context.BindToObject($taskPath)
        return $False
    }
    catch
    {
        return $True
    }
}

# Bind to the Scheduled Tasks container
$scheduledTasksPath = $Context.GetWellKnownContainerPath("ScheduledTasks")
$scheduledTasksPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $scheduledTasksPath
$containerPath = $scheduledTasksPathObj.CreateChildPath("CN=$containerName")
$container = $Context.BindToObject($containerPath)

# If the task name is not unique, generate a unique one
$uniqueName = $taskName
for ($i = 1; $True; $i++)
{
    $taskPath = $containerPath.CreateChildPath("CN=$uniqueName")
    if (CheckNameForUnique $taskPath)
    {
        break
    }
    $uniqueName = "$taskName`_$i"
}

# Create a Scheduled Task
$task = $container.Create("adm-ScheduledTask", "CN=$uniqueName")

$task.ObjectType = "domainDNS"
$task.Description = $taskDescription
$task.Disabled = $False
$task.ExecutionMoment = "ADM_BUSINESSRULEEXECMOMENT_BEFORE"
$task.OperationType = "none"
$task.DeleteTaskAfterExecution = $deleteTaskAfterExecution

$recurrencePattern = $task.GetRecurrencePattern()
$recurrencePattern.RecurrenceType = "ADM_RECURRENCEPATTERNTYPE_ONCE"
$recurrencePattern.PatternStartDateTime = $ProcessTime
$task.SetRecurrencePattern($recurrencePattern)

$task.SetInfo()

# Define actions and conditions

# Create a new set of actions and conditions
$actionsAndConditions = $task.ConditionedActions.Create()
$actionsAndConditions.ConditionsLogicalOperation = "ADM_LOGICALOPERATION_AND"
$actionsAndConditions.SetInfo()

# Add Run PowerShell Script action
$action = $actionsAndConditions.Actions.CreateEx("adm-RunScriptAction")
$action.ExecutionOptions = "ADM_ACTIONEXECUTIONOPTIONS_SYNC"
$scriptAction = $action.GetAction()
$scriptAction.ScriptType = "ADM_SCRIPTTYPE_POWERSHELL"
$scriptAction.ScriptDescription = $scriptDescription
$scriptAction.Script = $scriptToExecute.ToString()
$action.SetAction($scriptAction)
$action.SetInfo()
$actionsAndConditions.Actions.Add($action)

# Add the set to the Scheduled Task
$task.ConditionedActions.Add($actionsAndConditions)

# Set the scope of activity to All Objects
$scopeItem = $task.ActivityScopeItems.Create()
$scopeItem.BaseObject = $NULL
$scopeItem.Type = "ADM_SCOPEBASEOBJECTTYPE_ALL_DIRECTORY"
$scopeItem.Inheritance = "ADS_SCOPE_SUBTREE"
$scopeItem.Exclude = $False
$scopeItem.SetInfo()

$task.ActivityScopeItems.Add($scopeItem)

Action:Send e-mail notification (User has been deactivated)

If the 'Provide Manager Access to MB (Home Folder always provided)' property equals 'True' AND
If the 'Manager' property is not empty AND
If the User has an Exchange mailbox then
Action:Modify mailbox settings for the User: modify Mailbox Rights (add '%manager% (allow 'Full mailbox access')')
Action:Modify mailbox settings for the User: set Hide from Exchange address lists to 'True'
Action:Send e-mail notification (User Deactivation)

If the 'Provide Manager Access to MB (Home Folder always provided)' property equals 'False' AND
If the 'Manager' property is not empty then
Action: Send e-mail notification (User Deactivation)

Custom Command Step 2 is as follows:

If the 'Provide Manager Access to MB (Home Folder always provided)' property equals 'True' then
Action: Send e-mail notification (User Deactivation)

Always
Action: Run PowerShell script 'Delete User (send to helpdesk for approval)' for the User

# Scheduled task settings
$containerName = "Deprovisioned User Processing" #must match a folder under scheduled tasks
$taskName = "Send to Helpdesk to confirm delete - %username%" 
$taskDescription = "This will process the disabling of the user account and provide Manager with access" 
$deleteTaskAfterExecution = $True
$ProcessTime = (Get-Date).AddDays(11)

# Script for action
$scriptDescription = "Delete Account and send to helpdesk for confirmation" # TODO: modify me
$scriptToExecute = {
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")
Import-Module Adaxes

$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly("localhost")

$userDN = (Get-AdmUser -Identity "%objectGUID%" -AdaxesService "localhost").DistinguishedName
$user = $admService.OpenObject("Adaxes://$userDN", $NULL, $NULL, 0)
$commandID = "{918f9c02-a91b-428e-88f7-6d4a6e3d5ae2}" #Custom Command GUID deprovision Step 3 TODO:Modify Me
$user.executecustomCommand($commandID)
}

function CheckNameForUnique($taskPath)
{
    try
    {
        $task = $Context.BindToObject($taskPath)
        return $False
    }
    catch
    {
        return $True
    }
}

# Bind to the Scheduled Tasks container
$scheduledTasksPath = $Context.GetWellKnownContainerPath("ScheduledTasks")
$scheduledTasksPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $scheduledTasksPath
$containerPath = $scheduledTasksPathObj.CreateChildPath("CN=$containerName")
$container = $Context.BindToObject($containerPath)

# If the task name is not unique, generate a unique one
$uniqueName = $taskName
for ($i = 1; $True; $i++)
{
    $taskPath = $containerPath.CreateChildPath("CN=$uniqueName")
    if (CheckNameForUnique $taskPath)
    {
        break
    }
    $uniqueName = "$taskName`_$i"
}

# Create a Scheduled Task
$task = $container.Create("adm-ScheduledTask", "CN=$uniqueName")

$task.ObjectType = "domainDNS"
$task.Description = $taskDescription
$task.Disabled = $False
$task.ExecutionMoment = "ADM_BUSINESSRULEEXECMOMENT_BEFORE"
$task.OperationType = "none"
$task.DeleteTaskAfterExecution = $deleteTaskAfterExecution

$recurrencePattern = $task.GetRecurrencePattern()
$recurrencePattern.RecurrenceType = "ADM_RECURRENCEPATTERNTYPE_ONCE"
$recurrencePattern.PatternStartDateTime = $ProcessTime
$task.SetRecurrencePattern($recurrencePattern)

$task.SetInfo()

# Define actions and conditions

# Create a new set of actions and conditions
$actionsAndConditions = $task.ConditionedActions.Create()
$actionsAndConditions.ConditionsLogicalOperation = "ADM_LOGICALOPERATION_AND"
$actionsAndConditions.SetInfo()

# Add Run PowerShell Script action
$action = $actionsAndConditions.Actions.CreateEx("adm-RunScriptAction")
$action.ExecutionOptions = "ADM_ACTIONEXECUTIONOPTIONS_SYNC"
$scriptAction = $action.GetAction()
$scriptAction.ScriptType = "ADM_SCRIPTTYPE_POWERSHELL"
$scriptAction.ScriptDescription = $scriptDescription
$scriptAction.Script = $scriptToExecute.ToString()
$action.SetAction($scriptAction)
$action.SetInfo()
$actionsAndConditions.Actions.Add($action)

# Add the set to the Scheduled Task
$task.ConditionedActions.Add($actionsAndConditions)

# Set the scope of activity to All Objects
$scopeItem = $task.ActivityScopeItems.Create()
$scopeItem.BaseObject = $NULL
$scopeItem.Type = "ADM_SCOPEBASEOBJECTTYPE_ALL_DIRECTORY"
$scopeItem.Inheritance = "ADS_SCOPE_SUBTREE"
$scopeItem.Exclude = $False
$scopeItem.SetInfo()

$task.ActivityScopeItems.Add($scopeItem)

Custom Command deprovision step 3 is as follows:

Always
Action: Execute custom command 'Remove all Future appointments created by a user (Sub-routines)' for the User

$startDateProperty = "adm-CurrentDateTime" # Delete meetings starting today.
$endDateProperty = "$NULL" # Delete All Future Meetings
$exchangeWebServiceDllPath = "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"

Import-Module $exchangeWebServiceDllPath

function GetDates ($property, $addDays)
{
    try
    {
        $value = $Context.TargetObject.Get($property)
        if ($value -is [Softerra.Adaxes.Adsi.AdsLargeInteger])
        {
            $value = [DateTime]::FromFiletime([Int64]::Parse($value))
        }
        $value = New-Object "System.Datetime" $value.Year, $value.Month, ($value.Day + $addDays), 0, 0, 0, ([System.DateTimeKind]::Local)
    }
    catch
    {
        $value = $NULL
    }

    return $value
}

function ClearProperties ($propertiesName)
{
    foreach ($name in $propertiesName)
    {
        if (($name -eq $NULL) -or 
            ($name -eq "adm-CurrentDateTime"))
        {
            continue
        }

        $Context.TargetObject.Put($name, $NULL)
        $Context.TargetObject.SetInfoEx(@($name))
    }
}

# Check whether the user has mailbox in Exchange Online
if (-not($Context.TargetObject.RecipientType -eq "ADM_EXCHANGERECIPIENTTYPE_MAILBOXENABLED" -and `
    $Context.TargetObject.RecipientLocation -eq "ADM_EXCHANGERECIPIENTLOCATION_OFFICE365"))
{
    return
}

# Get search parameters
$startDate = GetDates $startDateProperty 0
$endDate = GetDates $endDateProperty 1

# Get primary SMTP Address
$mailboxParams = $Context.TargetObject.GetMailParameters()
$emailAddresses = $mailboxParams.EmailAddresses
$primarySMTPAddress = $NULL

for ($i = 0; $i -lt $emailAddresses.Count; $i++)
{
    $emailAddress = $emailAddresses.GetAddress($i,[ref]"ADS_PROPERTY_NONE")
    if ($emailAddress.IsPrimary -and $emailAddress.Prefix -eq "smtp")
    {
        $primarySMTPAddress = $emailAddress.Address
        break
    }
}

if ([System.String]::IsNullOrEmpty($primarySMTPAddress))
{
    $Context.LogMessage("Cannot remove meetings scheduled by the user because the user's mailbox doesn't have a primary SMTP address.", "Warning")
    return
}

# Connect to Exchange Online via the Exchange Web Services API
$exchangeWebService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
$office365Cred = $Context.GetOffice365Credential()
$exchangeWebService.Credentials = New-Object System.Net.NetworkCredential($office365Cred.Username, $office365Cred.GetNetworkCredential().Password)
$exchangeWebService.Url = "https://outlook.office365.com/EWS/Exchange.asmx"

# Get the user's calendar
$calendarFolderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar, $primarySMTPAddress)
$calendarFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchangeWebService, $calendarFolderId)
$itemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(500)

$propertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet(
    [Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties, 
    [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Organizer)

do
{
    $searchResult = $calendarFolder.FindItems($itemView)
    foreach ($item in $searchResult.Items)
    {
        if (!($item.IsMeeting))
        {
            continue # Not a meeting
        }

        $item.Load($propertySet)

        if ($startDate -eq $NULL -and $endDate -eq $NULL)
        {
            $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
        }
        elseif (($startDate -eq $NULL) -and
            ($item.Start -lt $endDate))
        {
            $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
        }
        elseif (($endDate -eq $NULL) -and 
            ($item.Start -ge $startDate))
        {
            $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
        }
        elseif (($startDate -ne $NULL) -and 
            ($endDate -ne $NULL) -and 
            ($item.Start -ge $startDate) -and 
            ($item.Start -lt $endDate))
        {
            $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
        }
    }

    $itemView.Offset = $searchResult.NextPageOffset
}
while($searchResult.MoreAvailable -eq $True)

# Clear date properties
ClearProperties @($startDateProperty, $endDateProperty)

Action: Delete the User

0

What kind of type is your Business Rule and how do you trigger it?

0

With the new ability to create parameters for your custom commands we no longer use a business rule to kick this process off. We just pass the deprovisioning date as a custom command parameter and trigger the first step in the process.

Related questions

0 votes
1 answer

Hi All, I have an OU ADSynced to Office 365 When I create Shared Mailboxes I basically create the user account sync it to 365 Assign it a license and and set ... only process the below actions if the previous one returned an Operation status of "Completed"

asked Oct 26, 2020 by casey101 (20 points)
0 votes
1 answer

I have a handful of manual PowerShell scripts that I run after a new user is created. Most of these commands can be done using a ... , SendOnBehalf -AuditOwner UpdateFolderPermission, MailboxLogin, Create, SoftDelete, HardDelete, Update, MoveToDeletedItems

asked Jul 10, 2019 by bjzielinski (70 points)
0 votes
1 answer

Is there a way to use the built-in "Modify Exchange Properties" action to add a mailbox delegate that only resides in the cloud? We can do it via a powershell script, but I ... action. For example, I want to add "Company Administrator" to a user via the GUI:

asked Sep 14, 2015 by yourpp (540 points)
0 votes
1 answer

We just finalize the purchase to our software license company and I want to try to automate more with Adaxes. Is there a way that it can automatically create mailboxes in Office 365 ... that relays out to 365) and set up a script to migrate them to Office 365?

asked Mar 6, 2013 by danftasc (440 points)
0 votes
1 answer

Hi, is it possible to export automatically the exchange online mailbox of a user to a .PST file on our archive server before the user is deleted? Kind regards, Fabian

asked Oct 26, 2023 by fabian.p (150 points)
3,326 questions
3,026 answers
7,727 comments
544,678 users