I am getting this error while try to accessin the resource mailbox. pls any one help me on this . I am new to EWS.
I am able to access the resource mailbox through OWA(Outlook web app). But i am not owner of this mailbox as it is shared mailbox.
my code:
ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
ExchangeService newExchangeService = new ExchangeService (ExchangeVersion.Exchange2007_SP1);
newExchangeService.Credentials = new NetworkCredential(username, password, domain);
newExchangeService.AutodiscoverUrl(email-id, RedirectionUrlValidationCallback);
newExchangeService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, email_which_i_want_to_access);
Folder visitorsFolder = Folder.Bind(newExchangeService, WellKnownFolderName.Inbox);
foreach (Folder childfolder in visitorsFolder.FindFolders(new FolderView(10)))
{
Console.WriteLine(childfolder.DisplayName);
}
The problem could be that you do not have permissions to impersonate the mailbox but you may have delegate access. Please see my answer to this similar question on how to access a mailbox when you have delegate access:
https://stackoverflow.com/a/9242792/64161
Related
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
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
I'm struggling with a simple Task, that gets new E-Mails in specific Folders in Exchange Online, sets "Processed"-Category and then stores the E-Mail.
Firstly, I create App permissions like that:
var app = ConfidentialClientApplicationBuilder.Create(_appConfig.ClientId)
.WithAuthority(AzureCloudInstance.AzurePublic,
_appConfig.Tenant)
.WithClientSecret(_appConfig.ClientSecret)
.Build();
AuthenticationResult authResultresult = null;
var ewsScopes = new[] {"https://outlook.office.com/.default"};
authResultresult = await app.AcquireTokenForClient(ewsScopes)
.ExecuteAsync();
then I create Exchange-Client and use created Oauth-Token to authorize:
var result = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
result.KeepAlive = false;
result.DateTimePrecision = DateTimePrecision.Milliseconds;
result.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
result.UseDefaultCredentials = false;
var authResultresult = await CreateAppPermissions(_appConfig);
result.Credentials = new OAuthCredentials(authResultresult.AccessToken);
after that I impersonate SMTP-User with my mainSMTP account
result.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, _appConfig.SMTPMailAccount);
after that I use this Code to retrieve an Email using known Id, add for it new Category and update the item like this:
var itemsToStore = result.BindToItems(new []{newItemId}, props);
foreach (var itemToStore in itemsToStore)
{
itemToStore.Item.Categories.Add("Processed");
itemToStore.Item.Update(ConflictResolutionMode.AlwaysOverwrite, true);
}
This code has previously produced “Access is denied. Check credentials and try again., Cannot save changes made to an item to store." - Exception on Item.Update. After a research I have found this :
Office 365 API ErrorAccessDenied (Access is denied. Check credentials and try again.)
and followed the proposed solution by removing "Have full access to a users mailbox"- checkbox flag.
After that I'm getting 401 unauthorized, when I'm calling BindToItems.
Was it a step backwards to remove the checkbox?
RESOLVED:
Found the solution for 401:
since I'm using EWS a.k.a. older API called Exchange Web Services it was a mistake to remove the checkbox.
the reason for “Access is denied. Check credentials and try again., Cannot save changes made to an item to store." was that impersonated user didn't have rights to change someones elses emails
I am able to create new users in a remote ActiveDirectory server, which I am doing using an admin account on that server. This is how I do that:
String connection = "LDAP://serveraddress/OU=NewUsers,OU=People,DC=mydomain,DC=local";
usersDirectoryEntry = new DirectoryEntry(connection, "adminUserName","adminPass");
DirectoryEntry newUser = usersDirectoryEntry.Children.Add(userString, "user");
newUser.CommitChanges();
However, immediately after I am trying to set the password using:
UpdatePassword(newUser, "userPasswordMeetsRequirements");
where
private static void UpdatePassword(DirectoryEntry User, String password)
{
User.Properties["pwdLastSet"].Value = -1;
User.Invoke("SetPassword", new object[] { password.Trim() });
User.Properties["userAccountControl"].Value = 0x0200 | 0x10000;
User.CommitChanges();
}
Where User is of type DirectoryEntry (https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry(v=vs.110).aspx)
And on the User.Invoke line I get a System.Reflection.TargetInvocationException --> System.UnauthorizedAccessException: Access is denied.
That admin user should indeed have set password permissions. After looking in the AD logs I found that at the User.Invoke line my program was trying to connect to the AD server using my current credentials on my computer (which is on a different domain).
Why is this happening, and how can I force it to just use the admin account that it used for user creation?
Are you passing that newUser object to UpdatePassword? I would assume it's using the same credentials.
But if not, you can create a new object like this:
var user = new DirectoryEntry(newUser.Path, "adminUserName","adminPass");
UpdatePassword(user, somepassword);
Begining on .NET 3.5 and newer, you can use the System.DirectoryServices.AccountManagement
You can find information about it in System.DirectoryServices.AccountManagement Namespace.
Why don't you try the following :
PrincipalContext context = new PrincipalContext( ContextType.Domain, null, adAdminLogin, adAdminPassword );
UserPrincipal user = UserPrincipal.FindByIdentity( context, adUserLogin );
user.SetPassword( adUserNewPassword );
I'm able swicth to 3 diff domain using this (just changing domain LDAP path)
i don't see why you couldn't.
Domain = "LDAP://domain2.com";
ADUSER = MySuperAdmin;
ADpassword = "123";
DirectoryEntry Entry = new DirectoryEntry(Domain, ADUSER, ADpassword);
DirectoryEntry Entry = new DirectoryEntry(Domain, ADUSER, ADpassword);
DirectorySearcher Search = new DirectorySearcher(Entry);
Search.Filter = string.Format("(&(objectCategory=computer)(cn={0}))", HostName);
SearchResult Result = Search.FindOne();
now check if your are able find a device on your targeted domain
if it work try change the password if you not able it have nothing to do with the C# code but more with "MySuperAdmin" rigth on the domain2 .try direct in mmc you should pop the same error than in your application.
maybee a checkbox "User cannot change password" may cause the fail too
Is it possibly to access the folders and items of other Exchange accounts other than the one of the logged in user?
Can I do this via Exchange Web Services Managed API?
Yes it is possible, but you should know the password of the other user or grab in some ways this credentials (NetworkCredential object). The typical first lines of you code could be
ExchangeService myService = new ExchangeService (ExchangeVersion.Exchange2007_SP1);
myService.Credentials = new NetworkCredential ("user#mycorp.local", "P#ssword00");
so you can access Exchange Server Web Services with the account which is other as the current user. See ExchangeService object description for more information.
If you are an admin you can make user impersonation by SMTP address.
Here's how you do it without impersonation or knowing credentials.
ExchangeService _service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
//CREDENTIALS OF AN ACCOUNT WHICH HAS READ ACCESS TO THE CALENDAR YOU NEED
_service.Credentials = new WebCredentials(username, password);
_service.Url = new Uri(serviceURL);
SearchFilter.SearchFilterCollection searchFilter = new SearchFilter.SearchFilterCollection();
searchFilter.Add(new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, DateTime.Now.AddDays(-1)));
searchFilter.Add(new SearchFilter.IsLessThanOrEqualTo(AppointmentSchema.Start, DateTime.Now.AddDays(2)));
ItemView view = new ItemView(50);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.AppointmentType, AppointmentSchema.End);
//THIS NEXT LINE!!!
var calendarSearch = new FolderId(WellKnownFolderName.Calendar, new Mailbox("email#ofsomemailbox.com"));
var appointments = _service.FindItems(calendarSearch, searchFilter, view);
I suggest to use impersonation instead of login for each user.
Via impersonation you can impersonate users. Its not the same like full access. Full access is on behave of, impersonation is act as.
A pre of impersonation is you have one username and password instead of having x usernames and passwords.
You can use impersonation like this way:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
service.Credentials = new NetworkCredential(appName, appPassword, emailDomain);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userToImpersonate);
when a user has delegate access to someone else, you can access the folder of the other user. For example: Person A will be impersonated and is able to access Person B