Access to Office 365 account "on behalf of" through EWS - c#

I need help with EWS service. I need to read inbox/sent mails of an account Office 365, the access to this account is "on behalf of" and I usually login with my domain credentials. This is the firt time I need to do this, so searching on Google I found this solution:
static void Main(string[] args)
{
ExchangeService _service;
try
{
Console.WriteLine("Registering Exchange connection");
_service = new ExchangeService
{
Credentials = new WebCredentials("user", "pwd", "domain")
};
AutodiscoverRedirectionUrlValidationCallback validurl = new AutodiscoverRedirectionUrlValidationCallback((a) => { return true; });
_service.AutodiscoverUrl("email#mail.com", validurl);
}
catch (Exception e)
{
Console.WriteLine("new ExchangeService failed with error '" + e.Message + "'. Press enter to exit:");
return;
}
// This is the office365 webservice URL
_service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
When I run this code, the program goes up to the line "_service.AutodiscoverUrl("email#mail.com", validurl);", so it remains as "suspended", no error no timeout.
I don't know what the problem is, can anyone help me?
Thanks everyone
Nick

Related

Read an office 365 mailbox using Exchange web services

I am using this below code but unable to read my office 365 Inbox emails from C# code. Once I get this working then later I would need to read emails from shared mailbox.
I’d really appreciate if someone could please help me in fixing this issue or guide me what am I missing here ?
If I use Url as Office365 one then getting this error: "The request failed. The remote server returned an error 401. Unauthorized "
If I use Url as casx16 one (found this in company's Q/A portal) then getting this error: " No mailbox with such GUID "
using Microsoft.Exchange.WebServices.Data;
public static void ReadMyMailbox_2()
{
ExchangeService exchangeService = new ExchangeService();
exchangeService.Credentials = new WebCredentials("ajain", "password ", "MS"); /// ajain is my MSID
// exchangeService.AutodiscoverUrl("a_jain#xyz.com", RedirectionUrlValidationCallback);
exchangeService.Url = new Uri("https://casx16.xyz.com/ews/exchange.asmx");
// exchangeService.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
FolderId mailbox = new FolderId(WellKnownFolderName.Inbox, "a_jain#xyz.com");
ItemView itemView = new ItemView(10);
FindItemsResults<Item> result = exchangeService.FindItems(mailbox, itemView);
foreach (var msg in result)
{
EmailMessage message = EmailMessage.Bind(exchangeService, msg.Id);
Console.WriteLine(message.Subject);
}
}
It looks like you're setting up the ExchangeService object correctly. A couple things to try:
Try passing the full email (a_jain#xyz.com) to WebCredentials
Make sure your the domain you're passing to WebCredentials is correct
Try the WebCredentials constructor that only takes username and password.
Note: I don't think autodiscover will work with O365

C# Console Application - Parsing Office 365 Inbox

I was able to succeed via a package I found called EAGetMail. Unfortunately, I realized soon after that they have a token system and this is not a free approach.
There are a couple other choices available, like using Outlook Mail REST API, and MimeKit, but I'm lost on how to achieve my end result because no "start to finish" code is available on either of these references that demonstrates how to parse an Inbox for an account.
I've started to write this with the help of Mimekit, but am not sure if this is the proper way at all.
I must imagine it looks something like:
using (var client = new SmtpClient ())
{
client.Connect("outlook.office365.com", 587);
client.Authenticate("myemail#office365account.com", "mypassword");
var message = MimeMessage.Load(stream);
}
I don't know how to setup the stream mentioned above, and I don't know if it's possible to do this with Mimekit and Office 365.
I'm open to seeing a solution for this in any other approach that's not through EAGetMail. If anyone has a lightweight solution ranging from actual establishing a connection, to pulling messages from the inbox, would be great to see!
I've got it using EWS (Exchange Web Services). Here's my code:
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.Credentials = new WebCredentials("email#myemail.com", "myPassword");
service.AutodiscoverUrl("email#myemail.com", RedirectionUrlValidationCallback);
//creates an object that will represent the desired mailbox
Mailbox mb = new Mailbox(#"email#myemail.com");
//creates a folder object that will point to inbox folder
FolderId fid = new FolderId(WellKnownFolderName.Inbox, mb);
//this will bind the mailbox you're looking for using your service instance
Folder inbox = Folder.Bind(service, fid);
//load items from mailbox inbox folder
if (inbox != null)
{
FindItemsResults<Item> items = inbox.FindItems(new ItemView(100));
foreach (var item in items)
{
item.Load();
Console.WriteLine("Subject: " + item.Subject);
}
}
}

Using multiple credentials calling web service with Basic Authentication

We have a 3rd party web service that we consume from our web application. I've created a windows service that call this web service for all our customer, each of them with their own credentials.
The web service is using basic authentication.
When cycling through the credentials, it always uses the first authenticated credential.
Example code below:
private void testConnection(string username, string password)
{
_url = "https://somewebservice.com.au/transport/SomeService";
using (var someWebService = new someWebService {Url = _url})
{
var netCredential = new NetworkCredential(username, password);
var credential = new CredentialCache
{
{new Uri(someWebService.Url), "Basic", new NetworkCredential(username, password)}
};
someWebService.Credentials = credential;
someWebService.PreAuthenticate = true;
someWebService.Timeout = 1200000;
try
{
var result = someWebService.testConnection();
textBoxMsg.Invoke(new UpdateTextBoxDelegate(UpdateTextBox), result);
}
catch (SoapException soapex)
{
textBoxMsg.Invoke(new UpdateTextBoxDelegate(UpdateTextBox), "SOAP Error: " + soapex.Message + "\r\n");
}
catch (WebException webex)
{
textBoxMsg.Invoke(new UpdateTextBoxDelegate(UpdateTextBox), "Web Error: " + webex.Message + "\r\n");
}
catch (Exception ex)
{
textBoxMsg.Invoke(new UpdateTextBoxDelegate(UpdateTextBox), "Error: " + ex.Message + "\r\n");
}
finally
{
credential.Remove(new Uri(someWebService.Url), "Basic");
}
}
}
private void buttonTest2_Click(object sender, EventArgs e)
{
ThreadStart start = () => testConnection("user1", "123");
new Thread(start).Start();
}
private void buttonTest3_Click(object sender, EventArgs e)
{
ThreadStart start = () => testConnection("user2", "1234");
new Thread(start).Start();
}
if "user1" is authenticated first, second call to testConnection will always use "user1" credentials.
I've tried setting HttpWebRequest KeepAlive to false so connection is not re-used. TCP monitoring show the connection getting killed after setting it to false. This did not solve the issue.
If I close down the application and restart, and run testConnection for "user2", it gives the correct result.
Seems like the credentials are cached in the process. The only way to get rid of it is to exit the process.
This present some challenges when I have to cycle through about 1000 credentials.
Is there a way to clear the credential cache in process? If that is what's happening. See this link How to stop credential caching on Windows.Web.Http.HttpClient?
Options that I've explored and protoyped
Self hosted WCF accessing the web service. Another process that start and stop the WCF service for every credential
WCF service hosted in Windows Services - Another process that start and stop the windows service for every credential
Wait more than 10 mins for server side credential to expire. Not viable too slow.
My problem with the aboves are they have to be sequential, so to cycle through 1000 of them will take a while. Each credential will be around 20-30 secs.
Try using CredentialCache.Remove() method after your last catch block.
https://msdn.microsoft.com/en-us/library/4zaz5c95(v=vs.110).aspx
This will remove it from cache.
Maybe this is a bit old question, but you PreAuthenticate should be false for HttpClient not to cache the credentials.

My Application should connect to Exchange Server 2013 set OOF for users on vacation

I am coding an C# app that should connect to Exchange Server 2013 on-premise (Servers Location is not in our Company). I`ve got an account (User and Pass) with readonly admin-rights for now and want to read and set OutOfOffice Objects for other users. I decide to use EWS Managed API over Autodiscovery but I am bit confuse how.
I tried to connect with "service.UseDefaultCredentials = true" and read contacts -> this works.
try
{
ExchangeService _service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
_service.Credentials = new WebCredentials("service.exchange", "1234", "domain");
_service.TraceEnabled = true;
_service.TraceFlags = TraceFlags.All;
_service.UseDefaultCredentials = true;
_service.AutodiscoverUrl("user2#domain.net", RedirectionUrlValidationCallback);
foreach (Contact contact in _service.FindItems(WellKnownFolderName.Contacts, new ItemView(2)))
{
var test = contact;
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
After that I tried the same with _service.UseDefaultCredentials = false; got error -> "The Autodiscover service couldn't be located." I am not shure if this "direct log on" is the right way, On msdn I've read about "delegate access" and "Impersonation" (NTLM and Basic Authentication) I'am a bit confused. Can anybody help me?

How to use Microsoft.Exchange.WebServices?

i try to use : Microsoft.Exchange.WebServices.dll to use outlook. but connection return error
Error return line:service.AutodiscoverUrl("myusernamek#xxxx.com");
The Autodiscover service could not be located. my codes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Net;
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Exchange.WebServices.Autodiscover;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace test
{
class Program
{
static void Main(string[] args)
{
try
{
// Connect to Exchange Web Services as user1 at contoso.com.
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("myusernamek#xxxx.com", "mypassword", "xxxx.com");
service.TraceEnabled = true;
service.AutodiscoverUrl("myusernamek#xxxx.com");
// Create the e-mail message, set its properties, and send it to user2#contoso.com, saving a copy to the Sent Items folder.
EmailMessage message = new EmailMessage(service);
message.Subject = "Interesting";
message.Body = "The proposition has been considered.";
message.ToRecipients.Add("recipientname#xxxx.aero");
message.SendAndSaveCopy();
// Write confirmation message to console window.
Console.WriteLine("Message sent!");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
Console.ReadLine();
}
}
}
}
I know this is an old question, but recently wrestled with this and similar looking error (including ISA server). It was fixed with:
service.EnableScpLookup = false;
This was not required when working with an explicit URL, but was when using AutoDiscover
This is a common problem , Autodiscover service error is encountered when this autodiscover service by exchange is down
Resolution is to provide actual URL for exchange location , rather than autodiscovering it.
This solved my same issue.
The code suggest that you have an Exchange 2007 server... Is it properly configured for using the Autodiscover features? Confirm that you can ping autodiscover.XXXX.com and view https://autodiscover.XXXX.com in a web browser.
Alternately, you may need to use your internal domain name for autodiscovery and login. For example, in my office the external email addresses are on a domain like CompanyX.com, but the internal Active Directory domain is like CompanyX.local, and we do not have autodiscover on the open Internet, so my EWS needs to locate Autodiscover.CompanyX.local.
this is an old post but maybe someone will need it.
do not use auto discover, it is rly slow.
how to find your exchange url:
-open your outlook application and connect to your exchange
-hold Ctrl key and right click on the outlook icon in the system tray
-select "test e-mail auto configuration"
-click the test button
-look for the following line:
oh and to use the url you trop that extra line of code:
service.Url = new Uri("your url here");
try these concept:
private static ExchangeService getService(String userEmail, String login, String password, String hostName)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
AutodiscoverService auservice = new AutodiscoverService(hostName);
if (auservice.ServerInfo != null)
{
try
{
service.AutodiscoverUrl(userEmail, RedirectionUrlValidationCallback);
}
catch (AutodiscoverRemoteException ex)
{
Console.WriteLine("Exception thrown: " + ex.Error.Message);
}
}
else
{
service.Url = new Uri("https://" + hostName + "/EWS/Exchange.asmx");
}
service.UseDefaultCredentials = true;
if (service.ServerInfo == null)
{
service.Credentials = new WebCredentials(login, password);
}
return service;
}

Categories

Resources