Trouble with o365/exchange script

I have this script I’m developing for my employer that will allow us to quickly create and terminate users. With such a high turnover, it gets pretty time consuming. I’ve got most of it working, but I can’t get past one issue (I hope it’s the last one anyways)

(pre)function New-PVSUser {
[CmdLetBinding(SupportsShouldProcess = $true)]
param(
[Parameter(Position=0,Mandatory=$true)]
[string]$Alias,
[Parameter(Position=1,Mandatory=$true)]
[string]$FirstName,
[Parameter(Position=2,Mandatory=$true)]
[string]$LastName,
[Parameter(Position=3,Mandatory=$false)]
[string]$Copied,
[switch]$Licensed
)
# Create user without license
if ($Licensed) {
# Create new user with exchange license
New-MsolUser -FirstName $FirstName -LastName $LastName -DisplayName “$FirstName $LastName” -UserPrincipalName “$Alias@propertyvaluationservices.net” -LicenseAssignment propertyvaluation:EXCHANGESTANDARD -UsageLocation US
Write-Verbose “Copying groups from $Copied and adding $FirstName $LastName to them”

        # Copy distribution group membership

        $copied_dn = (get-mailbox $Copied).distinguishedname
        $new_dn = (get-mailbox $Alias).distinguishedname 
        $groups = Get-DistributionGroup -ResultSize unlimited
        
	    foreach ($group in $groups) {
		    if ((get-distributiongroupmember $group.identity | select -expand distinguishedname) -contains $copied_dn) { 
                Add-DistributionGroupMember -Identity $group.identity -Member $Alias
                Write-Verbose "Added to $($group.identity)"
	    }
	
	}
}
	else {
   Write-Verbose "Creating user"
      New-MsolUser -FirstName $FirstName -LastName $LastName -DisplayName "$FirstName $LastName" -UserPrincipalName "$Alias@propertyvaluationservices.net" -UsageLocation US
        Write-Verbose "User creation complete"

    }
    Write-Verbose "Changing user password to Welcome1"
    Set-MsolUserPassword -UserPrincipalName "$Alias@propertyvaluationservices.net" -NewPassword Welcome1
    Write-Verbose "Password is now Welcome1"
				
}(/pre)

All of my verbose messages display, but I keep getting the same error when it’s copying distros no matter what I try

(pre)The operation couldn’t be performed because object ‘dummy6@propertyvaluationservices.net’ couldn’t be found on
BN1PR02A001DC03.NAMPR02A001.prod.outlook.com’.
+ CategoryInfo : NotSpecified: (:slight_smile: [Get-Mailbox], ManagementObjectNotFoundException
+ FullyQualifiedErrorId : [Server=BY2PR02MB188,RequestId=99ca3eb8-06dc-4fc6-a056-56c015ade2df,TimeStamp=10/9/2014 7:28:55 PM] [FailureCategory=Cmd
let-ManagementObjectNotFoundException] 4C68FEBC,Microsoft.Exchange.Management.RecipientTasks.GetMailbox
+ PSComputerName : pod51035psh.outlook.com(/pre)

I think what you’re running into is mailbox provision time. When you assign an Exchange license in O365, a job is kicked off that provisions the mailbox for the user asynchronously. You can see the same thing when you assing the license in the EAC and then you have to wait a minute before you can edit the mailbox properties. In my experience, this can take anywhere from 30 seconds to several minutes to complete (averages 50 seconds in my tenant).

What I did to tackle this so I can automate mailbox creation is write a loop into my function that checks repeatedly until the mailbox provisioning is complete. Something like this:

$Params = @{
    FirstName = $FirstName
    LastName = $LastName
    DisplayName = "$FirstName $LastName"
    UserPrincipalName = "$Alias@propertyvaluationservices.net"
    LicenseAssignment = 'propertyvaluation:EXCHANGESTANDARD'
    UsageLocation = 'US'
}
New-MsolUser @params    

$EAPPrevious = $ErrorActionPreference
$Global:ErrorActionPreference = 'Stop'

1..12 | ForEach-Object {

    try 
    {
        $null = Get-Mailbox $UserPrincipalName
        $NoMailbox = $false          
        break
    }
    catch {$NoMailbox = $true; Start-Sleep -Seconds 10}
}

$Global:ErrorActionPreference = $EAPPrevious

if ($NoMailbox)
{
    throw 'The Mailbox was not provisioned within the allotted time!'
    Set-MsolUserLicense -UserPrincipalName $Params.UserPrincipalName -RemoveLicenses $Params.LicenseAssignment
}

This looks like a lot of code but what’s going on is it sets the license then checks every ten seconds until the mailbox is provisioned. If the mailbox does not provision after 12 loops (roughly 2 minutes), it rolls back the license assignment. You could just have it loop forever until the mailbox is ready, but I have had a few instances where something was up on the Exchange back-end and mailboxes were not provisioning. Having a timeout prevents this from creating an infinite loop.

Note: I set the ErrorActionPreference to Stop temporarily because this is the only way I could get the try/catch to work. I’ll probably take some flak for that.