by

Utilizing EWS to add / set person photographs in Trade On-line and 2016

Utilizing EWS to add / set person photographs in Trade On-line and 2016 Between Trade 2013 and 2016 there the place few new operations launched into EWS, one operation that was launched was the SetUserPhoto operation which pairs with the GetUserPhoto operation that was launched in Trade 2013.

What this operation does is means that you can set/add a excessive decision photograph for a person for use in Trade and Skype for Enterprise in Trade On-line or Trade 2016. Slightly bit extra in regards to the excessive ressolution person photograph is that if you set this it uploads this as an merchandise within the Non_IPM_Root of the Mailbox (so it’s not seen to the person) with a message class of IPM.UserPhoto when you the place to take a look at a Mailbox with a Mapi Editor you possibly can see the object that this creates. eg

In the event you take a look at the UserPhoto Object itself you possibly can see the completely different dimension codecs are saved able to entry in a lot of completely different Binary Mapi properties eg

So what the SetUserPhoto operation does is handles creating this object and all of the completely different photograph codecs that functions would possibly require.

Presently there is not something within the EWS Managed API to make the most of this new operation so to make use of this you possibly can both use the WSDL Proxy Objects (generated towards Trade 2016 or Trade On-line) or simply uncooked cleaning soap like the next.

<?xml model="1.0" encoding="utf-8"?>
<cleaning soap:Envelope xmlns:cleaning soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<cleaning soap:Header>
<RequestServerVersion Model="Exchange2016" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" />
</cleaning soap:Header>
<cleaning soap:Physique>
<SetUserPhoto xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
<E-mail>$MailboxName</E-mail>
<Content material>$Content material</Content material>
<TypeRequested>UserPhoto</TypeRequested>
</SetUserPhoto>
</cleaning soap:Physique>
</cleaning soap:Envelope>

I’ve put collectively a Powershell script that use the EWS Managed API to do the invention after which makes use of uncooked cleaning soap to do the add the photograph.. I’ve put this script up on GitHub right here https://github.com/gscales/Powershell-Scripts/blob/grasp/Add-Photograph.ps1

To make use of this script you employ the cmdlet like

Set-PhotoEWS -MailboxName mailbox@area -Photograph c:tempphoto1.jpg

The script itself seems to be like

perform Join-Trade{ 
param(
[Parameter(Place=0, Necessary=$true)] [string]$MailboxName,
[Parameter(Place=1, Necessary=$true)] [System.Management.Automation.PSCredential]$Credentials,
[Parameter(Place=2, Necessary=$false)] [string]$url
)
Start
{
Load-EWSManagedAPI

## Set Trade Model
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Trade2013

## Create Trade Service Object
$service = New-Object Microsoft.Trade.WebServices.Knowledge.ExchangeService($ExchangeVersion)

## Set Credentials to make use of two choices are availible Option1 to make use of explict credentials or Possibility 2 use the Default (logged On) credentials

#Credentials Possibility 1 utilizing UPN for the home windows Account
#$psCred = Get-Credential
$creds = New-Object System.Internet.NetworkCredential($Credentials.UserName.ToString(),$Credentials.GetNetworkCredential().password.ToString())
$service.Credentials = $creds
#Credentials Possibility 2
#service.UseDefaultCredentials = $true
#$service.TraceEnabled = $true
## Select to disregard any SSL Warning points brought on by Self Signed Certificates

Deal with-SSL

## Set the URL of the CAS (Consumer Entry Server) to make use of two choices are availbe to make use of Autodiscover to search out the CAS URL or Hardcode the CAS to make use of

#CAS URL Possibility 1 Autodiscover
if($url){
$uri=[system.URI] $url
$service.Url = $uri
}
else{
$service.AutodiscoverUrl($MailboxName,{$true})
}
Write-host ("Using CAS Server : " + $Service.url)

#CAS URL Possibility 2 Hardcoded

#$uri=[system.URI] "https://casservername/ews/exchange.asmx"
#$service.Url = $uri

## Non-compulsory part for Trade Impersonation

#$service.ImpersonatedUserId = new-object Microsoft.Trade.WebServices.Knowledge.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
if(!$service.URL){
throw "Error connecting to EWS"
}
else
{
return $service
}
}
}

perform Load-EWSManagedAPI{
param(
)
Start
{
## Load Managed API dll
###CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
$EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftExchangeWeb Companies'|Kind-Object Title -Descending| Choose-Object -First 1 -ExpandProperty Title)).'Set up Listing') + "Microsoft.Exchange.WebServices.dll")
if (Take a look at-Path $EWSDLL)
{
Import-Module $EWSDLL
}
else
{
"$(get-date -format yyyyMMddHHmmss):"
"This script requires the EWS Managed API 1.2 or later."
"Please download and install the current version of the EWS Managed API from"
"http://go.microsoft.com/fwlink/?LinkId=255472"
""
"Exiting Script."
#exit
}
}
}

perform Deal with-SSL{
param(
)
Start
{
## Code From http://poshcode.org/624
## Create a compilation surroundings
$Supplier=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Supplier.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add("System.DLL") | Out-Null

$TASource=@'
namespace Native.ToolkitExtensions.Internet.CertificatePolicy{
public class TrustAll : System.Internet.ICertificatePolicy {
public TrustAll() {
}
public bool CheckValidationResult(System.Internet.ServicePoint sp,
System.Safety.Cryptography.X509Certificates.X509Certificates cert,
System.Internet.WebRequest req, int drawback) {
return true;
}
}
}
'@
$TAResults=$Supplier.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly

## We now create an occasion of the TrustAll and connect it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll

## finish code from http://poshcode.org/624

}
}


perform Set-PhotoEWS {
param(
[Parameter(Place=0, Necessary=$true)] [string]$MailboxName,
[Parameter(Necessary=$true)] [System.Management.Automation.PSCredential]$Credentials,
[Parameter(Place=2, Necessary=$false)] [switch]$useImpersonation,
[Parameter(Place=3, Necessary=$false)] [string]$url,
[Parameter(Place=4, Necessary=$true)] [String]$Photograph
)
Start
{

if($url){
$service = Join-Trade -MailboxName $MailboxName -Credentials $Credentials -url $url
}
else{
$service = Join-Trade -MailboxName $MailboxName -Credentials $Credentials
}
if($useImpersonation.IsPresent){
$service.ImpersonatedUserId = new-object Microsoft.Trade.WebServices.Knowledge.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
}
[Byte[]]$FileContent = [System.IO.File]::ReadAllBytes($Photograph);
$Base64Content material = [System.Convert]::ToBase64String($FileContent);
$request = Get-SetPhotoRequest -MailboxName $MailboxName -Content material $Base64Content material
$SetPhotoRequest = [System.Net.HttpWebRequest]::Create($service.url.ToString());
$bytes = [System.Text.Encoding]::UTF8.GetBytes($request);
$SetPhotoRequest.ContentLength = $bytes.Size;
$SetPhotoRequest.ContentType = "text/xml";
$SetPhotoRequest.UserAgent = "EWS Photo upload";
$SetPhotoRequest.Headers.Add("Translate", "F");
$SetPhotoRequest.Technique = "POST";
$SetPhotoRequest.Credentials = New-Object System.Internet.NetworkCredential($Credentials.UserName.ToString(),$Credentials.GetNetworkCredential().password.ToString())
$RequestStream = $SetPhotoRequest.GetRequestStream();
$RequestStream.Write($bytes, 0, $bytes.Size);
$RequestStream.Shut();
$SetPhotoRequest.AllowAutoRedirect = $true;
$Response = $SetPhotoRequest.GetResponse().GetResponseStream()
$sr = New-Object System.IO.StreamReader($Response)
[XML]$xmlReposne = $sr.ReadToEnd()
if($xmlReposne.Envelope.Physique.SetUserPhotoResponse.ResponseClass -eq "Success"){
Write-Host("Photo Uploaded")
}
else
{
Write-Host("Upload failed")
Write-Host $sr.ReadToEnd()
}

}
}

perform Get-SetPhotoRequest
{
param(
[Parameter(Place=0, Necessary=$true)] [String]$MailboxName,
[Parameter(Place=0, Necessary=$true)] [String]$Content material
)
Start
{

$request = @"
<?xml model="1.0" encoding="utf-8"?>
<cleaning soap:Envelope xmlns:cleaning soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<cleaning soap:Header>
<RequestServerVersion Model="Exchange2016" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" />
</cleaning soap:Header>
<cleaning soap:Physique>
<SetUserPhoto xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
<E-mail>$MailboxName</E-mail>
<Content material>$Content material</Content material>
<TypeRequested>UserPhoto</TypeRequested>
</SetUserPhoto>
</cleaning soap:Physique>
</cleaning soap:Envelope>
"@
return $request
}
}