Picture Sync from Office 365 to AD (PowerShell way)

Well, this came up when I was dealing with a Photo policy where the customer have Office365 and On Premise applications such as SharePoint.  We all know that Pictures stored in Office365 cloud could be of resolution 648x648 (High Resolution pictures). If your organization has all the workloads in cloud, you are good because, Skype Online and SharePoint Online also supports this . The way Office 365 is configured, you would allow end users to upload their own pictures and it could take about 24 hours before its reflected in all the other workloads.

However, if you have on premise applications which depend on AD for picture sync, you need to automate the picture sync between AD and Office365 to ensure that you have the same picture across the workloads. Unfortunately, I couldn't see any tools that could be configured readily for this automation at schedules. So, I have decided to come up with a PowerShell script that does this for me. Well, most of you could write this too. But wanted to help those who are in need readily..:)

*************PowerShell Start***************
Download this module resize-image and rename the extension from .TXT to .psm1 and store it into the same share(share1)

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force

Import-Module \\share1\Resize-Image.psm1

rmdir \\Share1\O365Pictures\ -Force -Confirm:$false -Recurse

Start-Sleep -Seconds 30
mkdir \\Share1\O365Pictures\ -Force -Confirm:$false

#MSOnline Connection String#

Import-Module MSOnline

$User = "Office365GA@bugga.onmicrosoft.com"
$PWord = ConvertTo-SecureString -String " **** " -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
Connect-MsolService -Credential $Credential
Remove-PSSession $ExSession
$ExSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/?proxymethod=rps -Credential $Credential -Authentication Basic -AllowRedirection
Import-PSSession $ExSession

#Pictures are Downloaded to#

$folderpath="\\Share1\O365Pictures\"

#Download all user profile pictures from Office 365:
New-Item -ItemType directory -Path $folderpath –force
$allUsers=Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited|select UserPrincipalName,Alias
Foreach($user in $allUsers)
{
$path=$folderpath+$user.Alias+".Jpg"
$photo=Get-Userphoto -identity $user.UserPrincipalName -ErrorAction SilentlyContinue
If($photo.PictureData -ne $null)
{
[io.file]::WriteAllBytes($path,$photo.PictureData)
Write-Host $user.Alias “profile picture downloaded”
}
}

Remove-PSSession $ExSession

rmdir \\Share1\CroppedPictures\ -Force -Recurse -Confirm:$false
Start-Sleep -Seconds 30
mkdir \\Share1\CroppedPictures\ -Force -Confirm:$false

$Input="\\Share1\O365Pictures\"

#Output to store Resized images#
$output= "\\Share1\CroppedPictures\"

$users=Get-ChildItem $Input

foreach($user in $users)
{
$name=$user.Name
Resize-Image -InputFile $input$name -Width 96 -Height 96 -OutputFile $output$name
#$user.Name

}

$users=Get-ChildItem $output

foreach($user in $users)
{
$account=$user.Name.Split('.')[0]
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = $dom.GetDirectoryEntry()
$search = [System.DirectoryServices.DirectorySearcher]$root
$search.Filter = "(&(objectclass=user)(objectcategory=person)(samAccountName=$account))"
$result = $search.FindOne()

if ($result -ne $null)
{
$userRe = $result.GetDirectoryEntry()
[byte[]]$jpg = Get-Content $input2$user -encoding byte
$userRe.put("thumbnailPhoto", $jpg )
$userRe.setinfo()
Write-Host $userRe.displayname " updated"
}
else {Write-Host $userRe " Does not exist"}
}

Hope this helps. And make sure to use an account which has domain admin credentials or at least use an account that could have privileges to set the thumbnailPhoto.