How to acknowledge First Response Time for Service Requests in Microsoft System Center 2012 Service Manager
Most of the companies that use Microsoft System Center 2012 Service Manager are Microsoft-oriented. So no wonder that System Center Service Manager Connector 3.0 for Exchange is commonly used there.
One of the most required features is an ability to parse keywords for Incident first response. It works perfect and a first response's field is often used to create the Incident's service level objectives to measure a response duration. But how about Service Request? Service Request also has first response functionality but you cannot automate email’s acknowledgement in the Exchange Connector v3.0.
In this post, I’d like to share a solution that helps to repair this injustice. This code has a lot in common with our another solution that that allows a member of AD Group vote on behalf of the group the user belongs to. So if you are familiar with that code, it won’t surprise you.
As usual, this code used SMLets cmdlets. You have to change in the script the following values to fit your environment (“ask” is Acknowledged Keyword):
$1· $mailbox = ServiceRequest@contoso.kz
$1· $ack = "ack"
$1· $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010
Below the whole script code. It’s also available in the attached archive.
#------------ set culture----------------
$OldCulture=[System.Threading.Thread]::CurrentThread.CurrentCulture
$OldUICulture=[System.Threading.Thread]::CurrentThread.CurrentUICulture
try{
$culture=New-ObjectSystem.Globalization.CultureInfo("en-US")
[System.Threading.Thread]::CurrentThread.CurrentCulture =$culture
[System.Threading.Thread]::CurrentThread.CurrentUICulture =$culture
#------------- Load DDLs. Change the Path for R2 -----------------
Add-Type-Path"C:\Program Files\Microsoft System Center 2012\Service Manager\Microsoft.Exchange.WebServices.dll"
#------------- Set Exchange Version. To find your version pls refer to http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeversion(v=exchg.80).aspx
$ExchangeVersion=[Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010
$svc=New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
#-------------- load smlets ---------------------
$a= (get-module|%{$_.name}) -join" "
if(!$a.Contains("SMLets")){Import-Module SMLets -ErrorVariable err -Force}
#--------- initiate SM classes ------------------
$SRClass=Get-SCSMClass -name System.WorkItem.ServiceRequest$
$WIClass=Get-SCSMClass -name System.WorkItem$
$RAvotedId=Get-SCSMEnumeration ActivityStatusEnum.Completed
$ADUserClass=get-scsmclass System.Domain.User
$UserPref=Get-SCSMRelationshipClass -name System.UserHasPreference
#--------- set Exch variables -------------------
$SearchForRead=New- Object Microsoft.Exchange.WebServices.Data.SearchFilter + IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead,$true)
$query="System.IsRead:False"
#---------- use with impersonation -----------
$mailbox="ServiceRequest@contoso.com"
#---------- Delete mode -------------
$DeleteMode="MoveToDeletedItems"
# $DeleteMode = "HardDelete"
#----------set Acknowledged ------------------------
$ack="ack"
#-------- impersonate if needed-------------------
$id= New-Object -TypeName Microsoft.Exchange.WebServices.Data.ImpersonatedUserId -ArgumentList "SmtpAddress", $mailbox
$svc.ImpersonatedUserId =$id
#-------- get messages --------------------------
$svc.AutoDiscoverUrl($mailbox)
$view=new-object Microsoft.Exchange.WebServices.Data.ItemView(100)
$items=$svc.FindItems("Inbox",$SearchForRead,$view)
#-------- proccess messsages --------------------
$items|Foreach-Object{
$emailProps=New-Object -TypeName Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly, [Microsoft.Exchange.WebServices.Data.ItemSchema]::Body)
$emailProps.RequestedBodyType ="Text"
$email=[Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($svc,$_.Id,$emailProps)
#------------ Main body ------------------
# $_.Subject
$vals= ([regex]"(?i)\[SR\d*\]").Matches($_.Subject)
if ($vals.count -gt 0)
{
$FirstSR=$null
foreach ($val in $vals)
{
$valstr=$val.toString()
$SRval=$valstr.substring(1, ($valstr.length-2))
$SR_wi=Get-SCSMObject -class $WIClass -filter "ID -eq $SRval"
If($SR_wi -ne $null -AND $SR_wi.FirstResponseDate -eq $null -And $FirstSR -eq $null)
{
$FirstSR=$SR
#--------------- get decision ----------------
$Acknowledged= ([regex]"(?i)\[$ack\]").Matches($email.Body)
if ($Acknowledged.count -gt0)
{
Set-SCSMObject -SMObject $SR_w -Property FirstResponseDate -Value $_.DateTimeSent.ToUniversalTime()
}
}
}
}
#------------delete message by mode --------------
$email.Delete($DeleteMode)
}
#------------------------------------------------------------------------------
remove-module -name SMLets -force
#Get-Module | Remove-Module
}
finally {
#------------ recover culture-------------
[System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
[System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture
}
The script is light and fast and we recommend using it with Windows Task Scheduler to avoid possible issues when you rely on the PowerShell workflow in Service Manager. I personally prefer to run PowerShell scripts by a batch file that's why I added a batch file named ProcessExchange4SR.bat to the attached archive as well as Microsoft.Exchange.WebServices.dll (this version must work with this script).
Set up a task to start the batch file as required user on some schedule (we recommend using the same as in Exchange connector) with highest privileges. Then start acknowledging Service Request first response!
Download Ack for SRs.zip