Scott Townsend
asked on
EWS Impersonation in Hybrid Environment - Cant find user in Office365
I have some Code on our Intranet that Syncs Employee contacts with the Users Outlook Contacts.
The code has been working great for On-Premise users for years. I am testing the Migration of users to O365. When The user used the code below while still residing in the On-Premise server it works great. After the Migration the code fails with 'Object reference not set to an instance of an object.' Though I'm still working with the WebTeam on what line the Error is coming from.
When using EWS what is the Flow for how it knows where the mailbox resides? It would be great if there was Minimal Change to the Code.
I have converted other code that accesses the Office 365 Server Directly through EWS, though I would assume it would have an issue finding an On-Premise Mailbox.
Thanks,
Scott<-
The code has been working great for On-Premise users for years. I am testing the Migration of users to O365. When The user used the code below while still residing in the On-Premise server it works great. After the Migration the code fails with 'Object reference not set to an instance of an object.' Though I'm still working with the WebTeam on what line the Error is coming from.
When using EWS what is the Flow for how it knows where the mailbox resides? It would be great if there was Minimal Change to the Code.
I have converted other code that accesses the Office 365 Server Directly through EWS, though I would assume it would have an issue finding an On-Premise Mailbox.
Thanks,
Scott<-
Private Const ExchangeURL As String = "https://On-PremiseServer/EWS/Exchange.asmx"
Private Const ExchangeUserName As String = "UserWithImpersonationRights"
Private Const ExchangePassword As String = "UserPassword"
Private Const ExchangeDomain As String = "AD-Domain"
Private Function GetEWSConnection(ByVal UserEmailAddress As String) As ExchangeService
Static EWS As ExchangeService = Nothing
Static LastUserEmailAddress As String = String.Empty
If UserEmailAddress <> LastUserEmailAddress Then EWS = Nothing
If EWS Is Nothing Then
EWS = New ExchangeService(ExchangeVersion.Exchange2010_SP1)
'**********************************************************************************************
'Dim listener As New ExchangeTraceListener
'EWS.TraceListener = listener
'EWS.TraceFlags = TraceFlags.EwsRequest Or TraceFlags.EwsResponse Or TraceFlags.DebugMessage
'EWS.TraceEnabled = True
'**********************************************************************************************
EWS.Credentials = New WebCredentials(ExchangeUserName, ExchangePassword, ExchangeDomain)
EWS.Url = New Uri(ExchangeURL)
ServicePointManager.ServerCertificateValidationCallback = AddressOf CertificateValidationCallback
EWS.ImpersonatedUserId = New ImpersonatedUserId(ConnectingIdType.SmtpAddress, UserEmailAddress)
End If
Return EWS
End Function
Private Shared Function CertificateValidationCallback(sender As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) As Boolean
If sslPolicyErrors = Security.SslPolicyErrors.None Then
Return True
End If
Return False
End Function
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
make sure when its identified that the user is O365, then your o365 admin account with application impersonation rights is passed to EWS service for authentication.
ASKER
I think I was impatient. After doing both of the above, I tried my code and it was saying I still didn't have Impersonation rights. Asked a co-worker to look at my code 10 minutes later to show him the issue and where it was failing and it didn't fail. So it must of taken some time to replication the permissions to whichever server that EWS was connecting to.
Thank you!
Thank you!
ASKER
After using AutoDiscovery and setting the impersonation permissions I was good to go...
ASKER
For anyone interested here is my Sample code to read the subject of the first item in a mailbox that is either hosted or on-premise.
Option Strict On
Option Explicit On
Imports System.Net
Imports System.Net.Security
Imports System.Security.Cryptography.X509Certificates
Imports Microsoft.Exchange.WebServices.Data
Imports Microsoft.Exchange.WebServices.Autodiscover
Imports System.Xml
Public Class Form1
Private EWS As ExchangeService = Nothing
Private Const strO365ADURL As String = "https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml"
Private Const strOPADURL As String = "https://<yourOn-PremMailServer>.com/autodiscover/autodiscover.xml"
Private Sub SetupEWS()
'Clear out the URL and Status
tbEWSURL.Text = ""
tbConnectionStatus.Text = ""
' Set the Version of Exchange to the ON-PRemise Server version
EWS = New ExchangeService(ExchangeVersion.Exchange2010_SP2)
'Set our User Credentials
EWS.Credentials = New WebCredentials(tbEWSUserName.Text, tbEWSPassword.Text)
'Use AutoDiscover to find the Connection URL for the mailbox we are looking at accessing.
tbConnectionStatus.Text = "Attempting Audiscover for user:" + tbEWSImpersonationUser.Text.ToString
tbEWSURL.Text = ""
Cursor = Cursors.WaitCursor
Try
EWS.AutodiscoverUrl(tbEWSImpersonationUser.Text, AddressOf AutoDiscoverURLValidationCallback)
Cursor = Cursors.Default
tbEWSURL.Text = EWS.Url.ToString
'If there is some funniness with the SSL on the Connection Set our CertificateValidationCallback, We dont care about Warnings vs Errors.
ServicePointManager.ServerCertificateValidationCallback = AddressOf CertificateValidationCallback
'Let the EWS Connection know we want to access someone elses mailbox
EWS.ImpersonatedUserId = New ImpersonatedUserId(ConnectingIdType.SmtpAddress, tbEWSImpersonationUser.Text)
Catch ex As Exception When TypeOf ex Is AutodiscoverRemoteException OrElse TypeOf ex Is AutodiscoverLocalException
Dim strErrorMessage As String = ""
If ex.GetType = GetType(AutodiscoverRemoteException) Then
'Handle exception type AutodiscoverRemoteException
strErrorMessage = DirectCast(ex, AutodiscoverRemoteException).Error.Message
ElseIf ex.GetType = GetType(AutodiscoverLocalException) Then
'Handle exception type AutodiscoverLocalException
strErrorMessage = DirectCast(ex, AutodiscoverLocalException).Message + " Could Not Connect to AutoDiscover URL!"
End If
'MsgBox("Exception thrown: " + strErrorMessage, MsgBoxStyle.Exclamation, "Autodiscover service Error")
tbConnectionStatus.Text = strErrorMessage
tbEWSURL.Text = ""
Cursor = Cursors.Default
End Try
End Sub
' See if there was just a SSL Warning vs an Error. If only a Warning (Self Signed) and no Errors then return True
Private Shared Function CertificateValidationCallback(sender As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) As Boolean
Dim bSSLNoError As Boolean = False
If sslPolicyErrors = Security.SslPolicyErrors.None Then
bSSLNoError = True
End If
Return bSSLNoError
End Function
' Be sure we are talking to whom we think we should be asking for the EWS URL
' We should get an O365 URL or a On-Premise URL
Private Shared Function AutoDiscoverURLValidationCallback(url As String) As Boolean
Dim bURLOk As Boolean = False
If url.ToLower().StartsWith(strO365ADURL) Or url.ToLower().StartsWith(strOPADURL) Then
bURLOk = True
End If
Return bURLOk
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SetupEWS()
End Sub
Private Sub btnGetEmail_Click(sender As Object, e As EventArgs) Handles btnGetEmail.Click
Dim inboxItems As FindItemsResults(Of Item)
' Create a view with a page size of 1.
Dim view As New ItemView(1)
view.PageSize = 1
'Identify the Subject and DateTimeReceived properties to return.
'Indicate that the base property will be the item identifier
view.PropertySet = (New PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject))
' Send the request to search the Inbox and get the results.
inboxItems = EWS.FindItems(WellKnownFolderName.Inbox, view)
' Process each item.
For Each item As Item In inboxItems.Items
If TypeOf item Is EmailMessage Then
tbEmailSubject.Text = TryCast(item, EmailMessage).Subject.ToString
Else
' Else handle other item types.
End If
Next
End Sub
End Class