Trouble with o365/exchange script

This topic contains 1 reply, has 2 voices, and was last updated by Profile photo of Matt McNabb Matt McNabb 2 years, 1 month ago.

  • Author
    Posts
  • #19573
    Profile photo of Aaron Hulse
    Aaron Hulse
    Participant

    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: (:) [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)

  • #19580
    Profile photo of Matt McNabb
    Matt McNabb
    Participant

    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.

You must be logged in to reply to this topic.