There are numerous posts out there about how to do this, but thought I’d share my small script which includes the option to have images > 10kb. The script assumes you have a folder with with images on the notation <username>.jpg. It will loop over all images and use the Set-UserPhoto commandlet to upload the image.
The first time you run the script it prompts you for the password for the account you are using and stores it as a secure string in a file to be used on sub-sequent runs or on a schedule. The script will also move images one folder up after processing.
$adminUser = "foo@contoso.onmicrosoft.com" $localFolderPath = "d:\images\upload" $passwordFile = "$PSScriptRoot\userphoto-password.txt" if(![System.IO.File]::Exists($passwordFile)){ read-host -prompt "Type the password for $adminUser to be used (will be saved encrypted)" -assecurestring | convertfrom-securestring | out-file $passwordFile } $password = cat $passwordFile | convertto-securestring $MSOLCred = new-object -typename System.Management.Automation.PSCredential ` -argumentlist $adminUser, $password $ExOLSession = New-PSSession -Credential $MSOLCred -authentication Basic -Configurationname Microsoft.Exchange -ConnectionURI https://outlook.office365.com/powershell-liveid/?proxyMethod=RPS -allowredirection #load Exchange Online Management cmdlets Import-PSSession $ExOLSession -AllowClobber $files = ([System.IO.DirectoryInfo] (Get-Item $localFolderPath)).GetFiles() | ForEach-Object { if(([IO.Path]::GetExtension($_.FullName)) -eq ".jpg") { $username = [IO.Path]::GetFileNameWithoutExtension($_.FullName); $userPhoto = ([Byte[]] $(Get-Content -Path $_.FullName -Encoding Byte -ReadCount 0)) Set-UserPhoto -Identity $username -PictureData $userPhoto -Confirm:$False #move files one folder up after processing $destinationFolder = Split-Path -Parent $_.Directory.FullName move-item $_.FullName $destinationFolder } } #unload session Remove-PSSession $ExOLSession