This script that I am sharing has been written to assist with our provisioning process:
As you are aware when you provisioin new exchnage onine mailbox, if license is not applied, you have 30 days to assign the license.
To detect these mailboxes and applying the Exchange license –> this solution has been written (I have included SkOB license along with it)
Command that is being used inside the script to fetch the accounts that needs license reconciliation is :
Get-MsolUser -LicenseReconciliationNeededOnly
After fetching the accounts, these are checked against Exchange Online for their existence, if these exists than
it is checked if main license is assigned to them is E3 or K1 than accordingly Exchange Online and Skype for Bussiness billet is activated.
Download and extract the script from below link:(Update the variables)
https://github.com/VikasSukhija/Downloads/blob/master/LicenseReconcilation.zip
####################
$licenseE3 = “Company:ENTERPRISEPACK”
$licenseF1 = “Company:DESKLESSPACK”
$smtpserver = “smtp.labtest.com”
$from = “AutomateA@labtest.com”
$erroremail = “Reports@labtest.com”
#####################userid/password###############
$userId = “MGMT-SVC@labtest.com”
$encrypted1 = “01000000d08c9ddf0115”
##############################################
I have included the script to encrypt the password(run the encrypt.bat, it will prompt you for password and encrypt it in password1.txt file)
copy the encrypted password and paste it inside the license reconciliation ps1.
You can schedule the script to run daily after Exchange Mailbox provisioning process is completed.
logs folder will contain transcript logs, report folder will have two types of csv report. (one of which is error report)
Both these reports are saved and sent via email.
If everything is processed correctly than below is the report:
If there are errors in aplying license or user did not have E3 or F1 license applied(LicensenotFound) than below is the report that is generated.
I have added the code at the end of the script to recycle the logs/report after 60 days.(You can change that as per your requirement)
$limit = (Get-Date).AddDays(-60)
Here is the whole powershell Script.
<# .NOTES =========================================================================== Created on: 3/16/2018 1:26 PM Created by: Vikas Sukhija (http://SysCloudPro.com) Organization: Filename: LicenseReconciliation.ps1 =========================================================================== .DESCRIPTION This script will detect users with Licence reconcliation needed and will apply EOL/SKOB license #> #############Load Functions################# $error.clear() try { stop-transcript | out-null } catch { $error.clear() } function Write-Log { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [array]$Name, [Parameter(Mandatory = $true)] [string]$Ext, [Parameter(Mandatory = $true)] [string]$folder ) $log = @() $date1 = get-date -format d $date1 = $date1.ToString().Replace("/", "-") $time = get-date -format t $time = $time.ToString().Replace(":", "-") $time = $time.ToString().Replace(" ", "") foreach ($n in $name) { $log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext" } return $log } function LaunchEOL { param ( $cred ) $UserCredential = $cred $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection Import-PSSession $Session -Prefix "EOL" -AllowClobber } Function RemoveEOL { $Session = Get-PSSession | where { $_.ComputerName -like "outlook.office365.com" } Remove-PSSession $Session } function LaunchMSOL { param ( $cred ) $UserCredential = $cred import-module msonline Write-Host "Enter MS Online Credentials" -ForegroundColor Green Connect-MsolService -Credential $UserCredential } Function RemoveMSOL { Write-host "Close Powershell Window - No disconnect available" -ForegroundColor yellow } ##########################Load variables & Logs#################### $log = Write-Log -Name "process_o365EOLLicenseReconciliation" -folder logs -Ext log $Report1 = Write-Log -Name "o365EOLLicenseReconciliation" -folder Report -Ext csv $Report2 = Write-Log -Name "Erroro365EOLLicenseReconciliation" -folder Report -Ext csv $licenseE3 = "Company:ENTERPRISEPACK" $licenseF1 = "Company:DESKLESSPACK" $service1 = "EXCHANGE_S_ENTERPRISE" $service2 = "MCOSTANDARD" $service1f1 = "EXCHANGE_S_DESKLESS" $service2f1 = "MCOIMP" $collection = @() $smtpserver = "smtp.labtest.com" $from = "AutomateA@labtest.com" $erroremail = "Reports@labtest.com" #####################userid/password########################## $userId = "MGMT-SVC@labtest.com" $encrypted1 = "01000000d08c9ddf0115d1118c7a00c04fuljhvxnlhmxkwh00c000000010000000e140468d5d37jjk00000004800000a000000010000000e217f1a562a51a14cc58536b442e919b200000003dec6fa22cbb8482ebf6c724b74718c7127bf52594c4ac527fa26701fd49b1321400000072da6316c8fd50bd9facca90f475660c24dab279" $pwd = ConvertTo-SecureString -string $encrypted1 $Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $userId, $pwd ##########Start Script main############## Start-Transcript -Path $log get-date try { LaunchEOL -Cred $Credential LaunchMSOL -cred $Credential } catch { write-host "$($_.Exception.Message)" -foregroundcolor red Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Exchange online/MSOL License reconciliation connection Error" -Body $($_.Exception.Message) break } $AllLicensingPlansE3 = Get-MsolAccountSku | Where-Object{ $_.AccountSkuId -eq $licenseE3 } $AllLicensingPlansF1 = Get-MsolAccountSku | Where-Object{ $_.AccountSkuId -eq $licenseF1 } $getUsersneedingLic = Get-MsolUser -LicenseReconciliationNeededOnly -ALL $getUsersneedingLic | ForEach-Object{ $mcoll = "" | select UserPrincipalName, EOLExist, LicenseStatus $upn = $_.UserPrincipalName $mcoll.UserPrincipalName = $upn $eolmbx = Get-EOLMailbox -id $upn -ea silentlycontinue $Error.clear() if ($eolmbx) { $mcoll.EOLExist = "True" ###########Apply EOL/SKOB License############ Write-host "License Processing for .... $upn" -ForegroundColor Green $lic = get-msoluser -UserPrincipalName $upn ###########Check for E3 for assigning EOL/SKOB######## if ($lic.Licenses.AccountSkuid -eq $licenseE3) { $sts = $lic.Licenses | where{ $_.AccountSkuId -eq $licenseE3 } $status = $sts.servicestatus if ($status -ne $null) { $collnmsts = @() foreach ($svc in $status) { $svcnm = $svc.Serviceplan.ServiceName $svcsts = $svc.ProvisioningStatus if ((($svcsts -eq "Disabled") -and ($svcnm -ne $service1)) -and (($svcsts -eq "Disabled") -and ($svcnm -ne $service2))) { $collnmsts += $svcnm } } $O365Licences = $null for ($i = 0; $i -lt $AllLicensingPlansE3.count; $i++) { $O365Licences = New-MsolLicenseOptions -AccountSkuId $AllLicensingPlansE3[$i].AccountSkuId -DisabledPlans $collnmsts } Set-MsolUserLicense -UserPrincipalName $upn -LicenseOptions $O365Licences if ($error) { $mcoll.LicenseStatus = "error" $Error.clear() } else { Write-Host "Updating License for ...$upn" -ForegroundColor Magenta $mcoll.LicenseStatus = "Updated" } } } ###########Check for F1 for assigning EOL/SKOB######## if ($lic.Licenses.AccountSkuid -eq $licenseF1) { $sts = $lic.Licenses | where{ $_.AccountSkuId -eq $licenseF1 } $status = $sts.servicestatus if ($status -ne $null) { $collnmsts = @() foreach ($svc in $status) { $svcnm = $svc.Serviceplan.ServiceName $svcsts = $svc.ProvisioningStatus if ((($svcsts -eq "Disabled") -and ($svcnm -ne $service1f1)) -and (($svcsts -eq "Disabled") -and ($svcnm -ne $service2f1))) { $collnmsts += $svcnm } } $O365Licences = $null for ($i = 0; $i -lt $AllLicensingPlansF1.count; $i++) { $O365Licences = New-MsolLicenseOptions -AccountSkuId $AllLicensingPlansF1[$i].AccountSkuId -DisabledPlans $collnmsts } Set-MsolUserLicense -UserPrincipalName $upn -LicenseOptions $O365Licences if ($error) { $mcoll.LicenseStatus = "error" $Error.clear() } else { Write-Host "Updating License for ...$upn" -ForegroundColor Magenta $mcoll.LicenseStatus = "Updated" } } } if($lic.IsLicensed -eq $false) { $mcoll.LicenseStatus = "LicenseNotFound" } ################################################### } else { $mcoll.EOLExist = "False" $mcoll.LicenseStatus = "Not Required" } $collection += $mcoll } if ($collection) { $reportcoll1=@() $reportcoll1 = $collection | where{ ($_.LicenseStatus -ne "Error") -and ($_.LicenseStatus -ne "LicenseNotFound") } if ($reportcoll1) { $reportcoll1 | Export-Csv $Report1 -NoTypeInformation Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Exchange online/MSOL License reconciliation Report" -Attachments $Report1 } $reportcoll2 = @() $reportcoll2 = $collection | where{ ($_.LicenseStatus -eq "error") -or ($_.LicenseStatus -eq "LicenseNotFound") } if ($reportcoll2) { $reportcoll2 | Export-Csv $Report2 -NoTypeInformation Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error Report - Exchange online/MSOL License reconciliation" -Attachments $Report2 } } ########################Recycle reports & logs############## $path1 = ".\report\" $path2 = ".\Logs\" $limit = (Get-Date).AddDays(-60) #for report recycling Get-ChildItem -Path $path1 | Where-Object { $_.CreationTime -lt $limit } | Remove-Item -recurse -Force Get-ChildItem -Path $path2 | Where-Object { $_.CreationTime -lt $limit } | Remove-Item -recurse -Force get-date Write-Host "Script finished" -ForegroundColor green Stop-Transcript ##############################################################################
Thanks for reading and downloading
Sukhija Vikas
Pingback: Office 365 License Reconciliation | Cloud Computers Guide