Porting Exchange 2010 impersonation code to Exchange 2013 (permission denied) - c#

I have verified that the user account (the service) can log into OWA and read the contents of the "targetEmail".
The only difference is that I'm now using an Exchange 2013 CAS server. When I use Exchange 2013, I get the following:
The remote server returned an error: (403) Forbidden.
Do I need to do anything special for Exchange 2013?
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, targetEmail);
var fldsList = GetSubFolders(targetEmail,WellKnownFolderName.MsgFolderRoot);
//
//
FindFoldersResults folderResults = null;
var Propset = new PropertySet(BasePropertySet.FirstClassProperties);
Propset.Add(PR_MESSAGE_SIZE_EXTENDED);
var folderView = new FolderView(100);
folderView.PropertySet = Propset;
try
{
folderResults = service.FindFolders( WellKnownFolderName.MsgFolderRoot, folderView);
}
catch (ServiceResponseException e)
{
// If no voicemail folder, archive etc.
}

Related

Read email from outlook - problem with XML

I'm trying to connect to outlook online and download some emails with predefined conditions.
in browser when I go to https://outlook.office.com/mail/ and logon with specific email and pass, I can see all mails.
I have c# console application that should connect, search and manipulate with emails.
public void EmailReceiver()
{
try
{
ExchangeService exchangeService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
exchangeService.Credentials = new NetworkCredential("username", "pass");
exchangeService.Url = new Uri("https://outlook.office.com/mail/");
var inbox = Folder.Bind(exchangeService, WellKnownFolderName.Inbox);
var sf1 = new SearchFilter.ContainsSubstring(EmailMessageSchema.From, "searchMail");
SearchFilter.SearchFilterCollection searchFilterCollection = new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
searchFilterCollection.Add(sf1);
var view = new ItemView(1000);
var findResults = service.FindItems(WellKnownFolderName.Inbox, searchFilterCollection, view);
return;
//foreach (Item item in findResults)
//{
// GetAttachmentsFromEmail(item.Id);
//}
}
catch (Exception ex)
{
throw;
}
}
But cannot connect to outlook
Any suggestions?
Office 365 no longer allows basic authentication, you need to switch to OAuth2. You can still allow basic auth, but you must explicit do so in the Exchange admin console for your tenant. But even in that case, you need to use WebCredentials class, not NetworkCredential. In case of OAuth, you need OAuthCredentials class.
You might also want to set TraceEnabled property to true and provide your class (assign it to the TraceListener property) to log all EWS calls.
exchangeService.TraceEnabled = true;
exchangeService.TraceListener = new MyTraceListener(this);
exchangeService.TraceFlags = TraceFlags.All;

Getting 403 error when trying to get Folder items from Office 365 mailbox using ExchangeService

I'm trying to read all Inbox email items from an Office 365 mailbox using ExchangeService.
For that, I:
Created an app in my AzureAD portal.
Given this app all permissions.
Issues this app an access secret to use in my code.
The code works to the point that I sucessfully get a token, but when trying to get the folder items I get an 403 error:
'The request failed. The remote server returned an error: (403)
Forbidden.'
I get this error from my dev and my prod environments so I'm pretty sure it's not a network or port issue.
Here's my code:
var cca = ConfidentialClientApplicationBuilder
.Create("myApplicationId")
.WithClientSecret("myClientSecret")
.WithTenantId("myTenantId")
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
// This is where I get the token
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync();
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "my#mail.box");
ewsClient.HttpHeaders.Add("X-AnchorMailbox", "my#mail.box");
// This is where I get the 403 error:
var items = ewsClient.FindItems(
new FolderId(WellKnownFolderName.Inbox, new Mailbox("my#mail.box")),
new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter[] {}
),
new ItemView(15)
);
403 if its coming back from Office365 sounds like they have either disabled EWS on the Mailbox your trying to access or they have limited the clients that are allowed to connect eg https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-control-access-to-ews-in-exchange . You could try testing EWS itself using a user account via the EWSeditor https://github.com/dseph/EwsEditor

Read Mails from Outlook Web App using .net

I have code that works for office 365 Exchange web service https://outlook.office365.com/EWS/Exchange.asmx. However I am now trying to read mail from outlook web app say https://mail.company.com/owa
ExchangeService exchangeService = new ExchangeService(ExchangeVersion.Exchange2013);
exchangeService.Credentials = new NetworkCredential(i_EmailID, i_Password);
exchangeService.Url = new Uri(exchangeURL);
exchangeService.KeepAlive = true;
Mailbox mailbox = new Mailbox(email);
FolderId folder = new FolderId(WellKnownFolderName.Inbox, mailbox);
ItemView view = new ItemView(1);
FindItemsResults<Item> items = exchangeService.FindItems(folder, view);
If this code works only for Exchange Web Service then what method should I be using to access Outlook Web Access?
Please share me any article or code sample that can help me understand in getting this implemented.
UPDATE: Exchange Online deprecating Basic Authentication (Basic Auth)
Basic Authentication is no longer supported by Exchange Online. Use the
OAuth 2.0 authorization code flow
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
var confidentialClientApplicationBuilder = ConfidentialClientApplicationBuilder.Create(appId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
string[] ewsScopes = new string[] { "https://outlook.office365.com/.default" };
var authResult = await confidentialClientApplicationBuilder.AcquireTokenForClient(ewsScopes)
.ExecuteAsync();
return authResult.AccessToken;
and then use the token to pass to OAuthCredentials
exchangeService.Credentials = new OAuthCredentials(accessToken);

Exchange Server doesn't support the requested version

I get this error because the FindItemsResult isn't compatible with exchange version I'm using which is 2013.
Exchange Server doesn't support the requested version.
My codes:
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
FindItemsResults<Item> items = service.FindItems(WellKnownFolderName.Inbox, sf, new ItemView(10));
foreach (Item item in items.Items)
{
PropertySet propSet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.TextBody);
EmailMessage email = EmailMessage.Bind(service, item.Id, propSet);
Program.SearchItems(email);
}
I could just change it into Exchange 2010 but I get an error in TextBody since this is only for Exchange 2013 and later versions.
Is there any way to convert the code which can work in Exchange 2013?
You need to show more of the code your using as your question doesn't really make sense. The ItemSchema.TextBody was added in Exchange 2013 so as long you are running Exchange 2013 and you have set the Initial server version correctly it will work (So you are either not running 2013 or you have other issue in the code you haven't show). If your looking for something that will work on both Exchange 2007,2010 and 2013 the I would suggest you use.
String MailboxToAccess = "user#domain.com";
ExchangeService service = new Microsoft.Exchange.WebServices.Data.ExchangeService(ExchangeVersion.Exchange2010_SP1);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead,false);
service.Credentials = new NetworkCredential("user#domain.com", "password");
service.AutodiscoverUrl(MailboxToAccess, adAutoDiscoCallBack);
FolderId FolderToAccess = new FolderId(WellKnownFolderName.Inbox, MailboxToAccess);
ItemView ivItemView = new ItemView(10);
FindItemsResults<Item> FindItemResults = service.FindItems(FolderToAccess, sfSearchFilter, ivItemView);
PropertySet ItemPropertySet = new PropertySet(BasePropertySet.IdOnly);
ItemPropertySet.Add(ItemSchema.Body);
ItemPropertySet.RequestedBodyType = BodyType.Text;
if (FindItemResults.Items.Count > 0)
{
service.LoadPropertiesForItems(FindItemResults.Items, ItemPropertySet);
}
foreach (Item item in FindItemResults.Items)
{
Console.WriteLine(item.Body.Text);
}
internal static bool adAutoDiscoCallBack(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;
}
That will return just the Text body and will work on any version of EWS.
Cheers
Glen

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?

Categories

Resources