4
votes

I need to make a VB .net tool to read email and save attachments. My company recently migrated from on-premise Exchange to Office 365. I have been reading EWS tutorials for 2 days now, and searching StackOverflow, but cannot get past the most basic step of authorized access to the O365 mailbox.

I took the original code from this article: htp://www.c-sharpcorner.com/UploadFile/jj12345678910/reading-email-and-attachment-from-microsoft-exchange-server/. I had some trouble converting it to VB using the Telerik converter but I think I have it right. Each time I try using the FindItemsResults method it halts with "(401) Unauthorized."

The instructions for asking a question state that I should include links to what I have already found and why it did not work, but my SO reputation only allows me 2 links. Here is what I have tried:

I have tried every possible usercode and domain combination I can think after reading this page: htps://stackoverflow.com/questions/10107872/ews-connections-issues-401-unauthorized

I am trying to read my own mailbox, so this one does not help: htps://stackoverflow.com/questions/43346498/401-unauthorized-access-when-using-ews-to-connect-to-mailbox

My connection looks identical to the connection on this page, but using it in my project did not get past the same Unauthorized error as before:htps://stackoverflow.com/questions/29009295/ews-managed-api-retrieving-e-mails-from-office365-exchange-server

Here is my code:

Public Class Form1
Public Exchange As ExchangeService
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    lstMsg.Clear()
    lstMsg.View = View.Details
    lstMsg.Columns.Add("Date", 150)
    lstMsg.Columns.Add("From", 250)
    lstMsg.Columns.Add("Subject", 400)
    lstMsg.Columns.Add("Has Attachment", 50)
    lstMsg.Columns.Add("Id", 100)
    lstMsg.FullRowSelect = True

End Sub

Public Sub ConnectToExchangeServer()
    Me.lblMsg.Text = "Connecting to Exchange Server"
    lblMsg.Refresh()
    Try
        'Exchange = New ExchangeService(ExchangeVersion.Exchange2013)
        Exchange = New ExchangeService()
        Exchange.TraceEnabled = True
        'Exchange.UseDefaultCredentials = True
        Exchange.Credentials = New WebCredentials("DoeJohn", "mypasswd", "mycorp.com")
        'Exchange.AutodiscoverUrl("[email protected]", AddressOf MyRedirectionURLValidationCallback)
        'Exchange.AutodiscoverUrl("[email protected]", AddressOf MyRedirectionURLValidationCallback)

        Exchange.Url = New System.Uri("https://outlook.office365.com/ews/exchange.asmx")
        lblMsg.Text = "Connected to Exchange Server"
        lblMsg.Refresh()
    Catch ex As Exception
        MsgBox("Fatal Error in Connect: " & ex.Message)
        End
    End Try
End Sub
Public Function MyRedirectionURLValidationCallback(RedirectionURL As String) As Boolean
    Dim Result As Boolean = False
    Dim RedirectionURI As Uri = New Uri(RedirectionURL)
    If RedirectionURI.Scheme = "https" Then
        Return True
    End If
    Return False
End Function
Private Sub btnRead_Click(sender As Object, e As EventArgs) Handles btnRead.Click
    Call ConnectToExchangeServer()
    Dim ts As TimeSpan = New TimeSpan(0, -1, 0, 0)
    Dim MyDate As DateTime = DateTime.Now.Add(ts)
    Dim MyFilter As SearchFilter.IsGreaterThanOrEqualTo = New SearchFilter.IsGreaterThanOrEqualTo(ItemSchema.DateTimeReceived, MyDate)

    If Exchange IsNot Nothing Then
        Dim FindResults As FindItemsResults(Of Item) =
            Exchange.FindItems(WellKnownFolderName.Inbox, MyFilter, New ItemView(50))
        Dim NewRow As ListViewItem
        For Each MyItem As Item In FindResults
            Dim Message As EmailMessage = EmailMessage.Bind(Exchange, MyItem.Id)
            NewRow = New ListViewItem(Message.DateTimeReceived.ToString())
            NewRow.SubItems.Add(Message.From.Name.ToString())
            NewRow.SubItems.Add(Message.Subject)
            NewRow.SubItems.Add(Message.HasAttachments.ToString())
            NewRow.SubItems.Add(Message.Id.ToString())
            lstMsg.Items.Add(NewRow)
        Next
    Else

    End If
End Sub

I have confirmed that AutoDiscover is correctly finding the server, comparing to Test Email AutoConfiguration in Outlook.

AutoConfig

An interesting sidenote -- after my company moved to Office 365, I noticed that I have two new SMTP mail addresses. If I open Outlook properties on myself, I see this:

Props

This means someone can send mail to me now either at the old address [email protected], and also now at [email protected]. The new address is based on my domain usercode. I tested the microsoft one from a gmail account and it works.

To sum up, here are my questions: 1. Why am I getting the (401) Unauthorized errors when I try to read my Inbox? 2. Does Office 365 expect me to use my domain account or my mailbox name for user credentials? 3. In the domain part of the WebCredentials statement, do I use my company's mycorp.com or instead do I use Office 365's domain outlook.office365.com?

If you have read this far, many thanks!

1

1 Answers

2
votes

I found the answer to the problem above, so I'll share here in case anyone needs it. The problem is down to security protocols added by my IT organization that were not documented because of recent phishing attacks on our company.

The first clue was that IT stated if I want to check company email on my personal 4G device like smartphone or ipad, I must also install Microsoft InTune for MFA connection to the O365 mail server. Since I am unaware of how to integrate InTune into my .Net app, I had to look for another answer.

I requested and was approved to move my functional mailbox from O365 to an on-premise Exchange server for this app. That solved the authentication problem.