#Add references to SharePoint client assemblies and authenticate to Office 365 site as required for CSOM Add-Type -AssemblyName System.Drawing Function UploadImage () { Param( [Parameter(Mandatory=$True)] [String]$SiteURL, [Parameter(Mandatory=$True)] [String]$SPOAdminPortalUrl, [Parameter(Mandatory=$True, HelpMessage="Enter user email address or All for all mailboxes")] [String]$UserEmail ) #Default Image library and Folder value $DocLibName ="User Photos" $foldername="Profile Pictures" Connect-ExchangeOnline $siteConnection = Connect-PnPOnline -Url $SiteURL #NOTE: there is a bug in Set-PnPUserProfileProperty in which the ConnectPnPOnline must connect with the UseWebLogin option # https://github.com/pnp/powershell/issues/277 $adminConnection = Connect-PnPOnline -Url $SPOAdminPortalUrl $spoimagename = @{"_SThumb" = "48"; "_MThumb" = "72"; "_LThumb" = "200"} $allUserMailboxes = Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox Foreach($mailbox in $allUserMailboxes) { if(($mailbox.PrimarySmtpAddress -eq $UserEmail) -or ($UserEmail -eq "All")){ Write-Host "Processing " $mailbox.PrimarySmtpAddress try{ #Download Image from Exchange online $photo = Get-UserPhoto -Identity $mailbox.Identity Write-Host "Exchange online image downloaded successful for" $mailbox.PrimarySmtpAddress $username = $mailbox.PrimarySmtpAddress.Replace("@", "_").Replace(".", "_") $Extension = ".jpg" Foreach($imagename in $spoimagename.GetEnumerator()) { #Covert image into different size of image $ms = new-object System.IO.MemoryStream(,$photo.PictureData) $img = [System.Drawing.Image]::FromStream($ms) [int32]$new_width = $imagename.Value [int32]$new_height = $imagename.Value $img2 = New-Object System.Drawing.Bitmap($new_width, $new_height) $graph = [System.Drawing.Graphics]::FromImage($img2) $graph.DrawImage($img, 0, 0, $new_width, $new_height) #Covert image into memory stream $stream = New-Object -TypeName System.IO.MemoryStream $format = [System.Drawing.Imaging.ImageFormat]::Jpeg $img2.Save($stream, $format) $streamseek=$stream.Seek(0, [System.IO.SeekOrigin]::Begin) #Upload image into sharepoint online $FullFilename=$username+$imagename.Name+$Extension Add-PnPFile -Connection $siteConnection -Folder "User Photos/Profile Pictures" -FileName $FullFilename -Stream $stream } Write-Host "SharePoint online image uploaded successful for" $mailbox.PrimarySmtpAddress #Change user Profile Property in Sharepoint onlne $PictureURL=$SiteURL+$DocLibName+"/"+$foldername+"/"+$username+"_MThumb"+$Extension Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName PictureURL -Value $PictureURL Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName SPS-PicturePlaceholderState -Value 0 Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName SPS-PictureExchangeSyncState -Value 0 Set-PnPUserProfileProperty -Connection $adminConnection -Account $mailbox.PrimarySmtpAddress -PropertyName SPS-PictureTimestamp -Value 63605901091 Write-Host "Image processed successfully and ready to display for" $mailbox.PrimarySmtpAddress }catch{ $ErrorMessage = $_.Exception.Message Write-Host "Failed to process " $mailbox.PrimarySmtpAddress -ForegroundColor red Write-Host $ErrorMessage -ForegroundColor red } } } } #Input parameter $siteUrl="https://domain.sharepoint.com/sites/yoursite" $SPOAdminPortalUrl = "https://domain-admin.sharepoint.com/" uploadimage -SiteURL $siteUrl -SPOAdminPortalUrl $SPOAdminPortalUrl