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.


        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

Open in new window

Scott TownsendIT DirectorAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Sunil ChauhanLead AdministratorCommented:
try using autodiscovery method to get the EWS URL that way it will automatically connect to 365 if the user mailbox is migrated.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Scott TownsendIT DirectorAuthor Commented:
I have AutoDiscovery working, thank you.

Now when I try and impersonate a Office 365 User I get an Error.
{"The account does not have permission to impersonate the requested user."}

I have Added the user I'm connecting as the ApplicationImpersonation Role on the Office 365 Server using EAC from:

and via Powershell from:

If I impersonate an On-Premise User it connects fine. Its only with users that I have already Migrated to Office 365.
Sunil ChauhanLead AdministratorCommented:
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.
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

Scott TownsendIT DirectorAuthor Commented:
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!
Scott TownsendIT DirectorAuthor Commented:
After using AutoDiscovery and setting the impersonation permissions I was good to go...
Scott TownsendIT DirectorAuthor Commented:
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
            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

    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 handle other item types.
            End If
    End Sub
End Class

Open in new window

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Office

From novice to tech pro — start learning today.