Wednesday, July 31, 2013

Sending a VoiceMail using EWS and Powershell

If you want to send a VoiceMail via EWS and have the UM controls appear in Outlook and OWA so it appears the same as it was generated from Exchange UM you need to set a number of different extended properties on an Email Message when you send it. The full list of properties is documented in the following Exchange Protocol document .

While some of these properties are optional the most important is to the set the PidTagVoiceMessageAttachmentOrder  http://msdn.microsoft.com/en-us/library/ee202885%28v=exchg.80%29.aspx property which needs to be set to the name of the attachment. You also need to make sure you set the ItemClass to IPM.Note.Microsoft.Voicemail.UM.CA .

The following is a sample of sending a mp3 voicemail as a message with powershell, I've put a download of this script here .

  1. ## Get the Mailbox to Access from the 1st commandline argument  
  2.   
  3. $MailboxName = $args[0]  
  4.   
  5. #MessageProperties  
  6.   
  7. $VoiceMailSuject = "Voice Mail from .."  
  8. $Mp3FileName = "c:\temp\vmMail.mp3"  
  9. $duration = 30  
  10. $voiceMailFrom = "FirstName LastName"  
  11. $callerId = "1234"  
  12. $jobTitle = "Tech"  
  13. $Company = "CompanyName"  
  14. $workNumber = "11111-11111"  
  15. $emailAddress = "test@domain.com"  
  16. $SipAddress = "sip:test@domain.com"  
  17. $ToAddress = "user@domain.com"  
  18.   
  19. $fileInfo = Get-Item $Mp3FileName  
  20.   
  21. $BodyHtml = "<html><head><META HTTP-EQUIV=`"Content-Type`" CONTENT=`"text/html; charset=us-ascii`">"  
  22. $BodyHtml += "<style type=`"text/css`"> a:link { color: #3399ff; } a:visited { color: #3366cc; } a:active { color: #ff9900; } </style>"  
  23. $BodyHtml += "</head><body><style type=`"text/css`"> a:link { color: #3399ff; } a:visited { color: #3366cc; } a:active { color: #ff9900; } </style>"  
  24. $BodyHtml += "<div style=`"font-family: Tahoma; background-color: #ffffff; color: #000000; font-size:10pt;`"><div id=`"UM-call-info`" lang=`"en`">"  
  25. $BodyHtml += "<div style=`"font-family: Arial; font-size: 10pt; color:#000066; font-weight: bold;`">You received a voice mail from " + $voiceMailFrom + " at " + $callerId + "</div>"  
  26. $BodyHtml += "<br><table border=`"0`" width=`"100%`"><tr><td width=`"12px`"></td><td width=`"28%`" nowrap=`"`" style=`"font-family: Tahoma; color: #686a6b; font-size:10pt;border-width: 0in;`">"  
  27. $BodyHtml += "Caller-Id:</td><td width=`"72%`" style=`"font-family: Tahoma; background-color: #ffffff; color: #000000; font-size:10pt;`">"  
  28. $BodyHtml += "<a style=`"color: #3399ff; `" dir=`"ltr`" href=`"tel:" + $callerId + "`">" + $callerId + "</a></td></tr><tr><td width=`"12px`"></td><td width=`"28%`" nowrap=`"`" style=`"font-family: Tahoma; color: #686a6b; font-size:10pt;border-width: 0in;`">"  
  29. $BodyHtml += "Job Title:</td><td width=`"72%`" style=`"font-family: Tahoma; background-color: #ffffff; color: #000000; font-size:10pt;`">"  
  30. $BodyHtml += $jobTitle + "</td></tr><tr><td width=`"12px`"></td><td width=`"28%`" nowrap=`"`" style=`"font-family: Tahoma; color: #686a6b; font-size:10pt;border-width: 0in;`">"  
  31. $BodyHtml += "Company:</td><td width=`"72%`" style=`"font-family: Tahoma; background-color: #ffffff; color: #000000; font-size:10pt;`">"  
  32. $BodyHtml += $Company + "</td></tr><tr><td width=`"12px`"></td><td width=`"28%`" nowrap=`"`" style=`"font-family: Tahoma; color: #686a6b; font-size:10pt;border-width: 0in;`">"  
  33. $BodyHtml += "Work:</td><td width=`"72%`" style=`"font-family: Tahoma; background-color: #ffffff; color: #000000; font-size:10pt;`">"  
  34. $BodyHtml += "<a style=`"color: #3399ff; `" dir=`"ltr`" href=`"tel:&#43;" + $workNumber + "`">&#43;" + $workNumber + "</a></td></tr><tr><td width=`"12px`"></td><td width=`"28%`" nowrap=`"`" style=`"font-family: Tahoma; color: #686a6b; font-size:10pt;border-width: 0in;`">"  
  35. $BodyHtml += "E-mail:</td><td width=`"72%`" style=`"font-family: Tahoma; background-color: #ffffff; color: #000000; font-size:10pt;`">"  
  36. $BodyHtml += "<a style=`"color: #3399ff; `" href=`"mailto:" + $emailAddress + "`">" + $voiceMailFrom + "</a></td></tr><tr><td width=`"12px`">"  
  37. $BodyHtml += "</td><td width=`"28%`" nowrap=`"`" style=`"font-family: Tahoma; color: #686a6b; font-size:10pt;border-width: 0in;`">IM Address:</td>"  
  38. $BodyHtml += "<td width=`"72%`" style=`"font-family: Tahoma; background-color: #ffffff; color: #000000; font-size:10pt;`">"  
  39. $BodyHtml += "<a style=`"color: #3399ff; `" href=`"" + $SipAddress + "`">" + $emailAddress + "</a></td></tr></table></div></div></body></html>"  
  40.   
  41.   
  42.   
  43. ## Load Managed API dll    
  44. Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"    
  45.     
  46. ## Set Exchange Version    
  47. $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2    
  48.     
  49. ## Create Exchange Service Object    
  50. $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)    
  51.     
  52. ## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials    
  53.     
  54. #Credentials Option 1 using UPN for the windows Account    
  55. $psCred = Get-Credential    
  56. $creds = New-Object System.Net.NetworkCredential($psCred.UserName.ToString(),$psCred.GetNetworkCredential().password.ToString())    
  57. $service.Credentials = $creds        
  58.     
  59. #Credentials Option 2    
  60. #service.UseDefaultCredentials = $true    
  61.     
  62. ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates    
  63.     
  64. ## Code From http://poshcode.org/624  
  65. ## Create a compilation environment  
  66. $Provider=New-Object Microsoft.CSharp.CSharpCodeProvider  
  67. $Compiler=$Provider.CreateCompiler()  
  68. $Params=New-Object System.CodeDom.Compiler.CompilerParameters  
  69. $Params.GenerateExecutable=$False  
  70. $Params.GenerateInMemory=$True  
  71. $Params.IncludeDebugInformation=$False  
  72. $Params.ReferencedAssemblies.Add("System.DLL") | Out-Null  
  73.   
  74. $TASource=@' 
  75.   namespace Local.ToolkitExtensions.Net.CertificatePolicy{ 
  76.     public class TrustAll : System.Net.ICertificatePolicy { 
  77.       public TrustAll() {  
  78.       } 
  79.       public bool CheckValidationResult(System.Net.ServicePoint sp, 
  80.         System.Security.Cryptography.X509Certificates.X509Certificate cert,  
  81.         System.Net.WebRequest req, int problem) { 
  82.         return true; 
  83.       } 
  84.     } 
  85.   } 
  86. '@   
  87. $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)  
  88. $TAAssembly=$TAResults.CompiledAssembly  
  89.   
  90. ## We now create an instance of the TrustAll and attach it to the ServicePointManager  
  91. $TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")  
  92. [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll  
  93.   
  94. ## end code from http://poshcode.org/624  
  95.     
  96. ## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use    
  97.     
  98. #CAS URL Option 1 Autodiscover    
  99. $service.AutodiscoverUrl($MailboxName,{$true})    
  100. "Using CAS Server : " + $Service.url     
  101.      
  102. #CAS URL Option 2 Hardcoded    
  103.     
  104. #$uri=[system.URI] "https://192.168.0.6/ews/exchange.asmx"    
  105. #$service.Url = $uri      
  106.     
  107. ## Optional section for Exchange Impersonation    
  108.     
  109. #Extended Prop Definition  
  110.   
  111. $PidTagVoiceMessageAttachmentOrder = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x6805, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)  
  112. $PstnCallbackTelephoneNumberVal = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition([Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet]::UnifiedMessaging,"PstnCallbackTelephoneNumber", [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)  
  113. $PidTagSIPAddress = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x5FE5, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)  
  114. $PidTagCallIdVal = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x6806, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)  
  115. $PidTagSenderTelephoneNumber = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x6802, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)  
  116. $PidTagVoiceMessageDuration =  new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x6801, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)  
  117. $PidTagVoiceMessageSenderName = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x6803, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)  
  118.    
  119. #$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)   
  120. $EmailMessage = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $service    
  121. $EmailMessage.Subject = $VoiceMailSuject  
  122. #Add Recipients      
  123. $EmailMessage.ToRecipients.Add($ToAddress)    
  124. $EmailMessage.Body = New-Object Microsoft.Exchange.WebServices.Data.MessageBody    
  125. $EmailMessage.Body.BodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::HTML    
  126. $EmailMessage.Body.Text = $BodyHtml  
  127. $EmailMessage.ItemClass = "IPM.Note.Microsoft.Voicemail.UM.CA"  
  128. $vmAttachment = $EmailMessage.Attachments.AddFileAttachment($Mp3FileName)  
  129. $vmAttachment.ContentType = "audio/mp3";  
  130. $EmailMessage.SetExtendedProperty($PidTagVoiceMessageAttachmentOrder,$fileInfo.Name)  
  131. $EmailMessage.SetExtendedProperty($PstnCallbackTelephoneNumberVal,$workNumber)  
  132. $EmailMessage.SetExtendedProperty($PidTagSIPAddress,$SipAddress)  
  133. $EmailMessage.SetExtendedProperty($PidTagCallIdVal,$callerId)  
  134. $EmailMessage.SetExtendedProperty($PidTagSenderTelephoneNumber,$workNumber)  
  135. $EmailMessage.SetExtendedProperty($PidTagVoiceMessageDuration,$duration)  
  136. $EmailMessage.SetExtendedProperty($PidTagVoiceMessageSenderName,$voiceMailFrom)  
  137. $EmailMessage.SendAndSaveCopy()    




Monday, July 22, 2013

Forwarding a Message as an Attachment using the EWS Managed API and Powershell

While you can easily create an Inbox rule to forward a Message as an Attachment, doing this programmatically in EWS isn't that straight forward. As there is no direct method in EWS to attach an existing Store item a work around is needed.

With this workaround we use the MimeContent of an existing email message which will allow you to create an ItemAttachment of this existing message (using the method from this post) in the Inbox and maintain all the Mime Properties and attachments on the message your forwarding. Note this method doesn't maintain full fidelity of a Message as it won't include any MAPI properties or Exchange rich datatypes which may or may not be important.

The following sample demonstrates how to forward the more recently received email in the Inbox as an Item Attachment using the MimeContent (and also setting the MessageFlags property to make sure the message appears sent). 
  1. $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)     
  2. $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)  
  3. #Define ItemView to retrive just 1 Item     
  4. $ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(1)      
  5. $fiItems = $service.FindItems($Inbox.Id,$ivItemView)   
  6. if($fiItems.Items.Count -eq 1){  
  7.     $mail = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage($service)   
  8.     $OriginalEmail = $fiItems.Items[0]  
  9.     $psPropset= new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly)    
  10.     $psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)  
  11.     $psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject)  
  12.     $OriginalEmail.Load($psPropset)  
  13.     $AtColtype = ("Microsoft.Exchange.WebServices.Data.AttachmentCollection") -as "Type"  
  14.     $Emailtype = ("Microsoft.Exchange.WebServices.Data.EmailMessage") -as "Type"  
  15.     $methodInf = $AtColtype.GetMethod("AddItemAttachment");  
  16.     $AddItmAttachMethod = $methodInf.MakeGenericMethod($Emailtype);  
  17.     $EmailAttachment = $AddItmAttachMethod.Invoke($mail.Attachments,$null);  
  18.     $EmailAttachment.Item.MimeContent = $OriginalEmail.MimeContent  
  19.     $PR_Flags = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(3591, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);    
  20.     $EmailAttachment.Item.SetExtendedProperty($PR_Flags,"1")    
  21.     $EmailAttachment.Name = $OriginalEmail.Subject  
  22.     $mail.Subject = "See the Attached Email"  
  23.     $mail.ToRecipients.Add("glen.scales@domain.com")   
  24.     $mail.SendAndSaveCopy()     
  25. }  


Creating Item Attachments with the EWS Managed API with Powershell

Item Attachments in EWS allow you to create an Attachment that is of a Rich Exchange type such as an EmailMessage, Task, Post, Contact etc or even your own custom form if your using these. Although one thing you can't do with an Item attachment is attach an existing Exchange Item.

To use ItemAttachments in Powershell you need to use reflection in .NET as it involves invoking a Generic Method which is not that straight forward in Powershell.

The following is an example of creating a Task as an Item Attachment in Powershell using reflection

  1. $mail = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage($service);  
  2. $AtColtype = ("Microsoft.Exchange.WebServices.Data.AttachmentCollection") -as "Type"  
  3. $Tasktype = ("Microsoft.Exchange.WebServices.Data.Task") -as "Type"  
  4. $methodInf = $AtColtype.GetMethod("AddItemAttachment");  
  5. $AddItmAttachMethod = $methodInf.MakeGenericMethod($Tasktype);  
  6. $TaskAttachment = $AddItmAttachMethod.Invoke($mail.Attachments,$null);  
  7. $TaskAttachment.Item.Subject = "Mondays Task"  
  8. $TaskAttachment.Item.StartDate = (Get-Date)  
  9. $TaskAttachment.Item.DueDate = (Get-Date).AddDays(7)  
  10. $TaskAttachment.Name = "Mondays Task"  
  11. $mail.Subject = "See the Attached Task"  
  12. $mail.ToRecipients.Add("user@domain.com")   
  13. $mail.SendAndSaveCopy()