Accessing Exchange shared folders using Mailkit - c#

I am creating an application to read emails and attachments from an account on a Microsoft hosted Exchange server (Office 365). The difficulty I'm having is that I cannot find a way to get the MailKit API to see shared folders on the email account that I have connected to.
I can connect to my email account and see my Inbox and other folders that are under my main account. In Outlook, the tree-view of folders shows my main account (associated with my main email address) in the root, with the Inbox and other folders under that account. Outlook then shows my shared folder name (associated with another email address) also starting at the root, with it's Inbox and other folders under it. The shared folder (with its associated email address) does not actually have its own Exchange account to connect to.
When connected, I have examined the ImapClient.SharedNamespaces and ImapClient.Others collections and they are both empty.
Is there a way to see this type of shared folder in Exchange with MaikKit?

This is possible by appending a backslash and the shared mailbox alias to the end of the username during authentication, here's some example code...
void Main()
{
var userName = "main#user.com"; // The email address that has permissions to the shared mailbox
var sharedMailboxAlias = "aliasName"; // This is the alias name as setup in Exchange
var password = Util.GetPassword("Office365Password"); // Util.Password is a LinqPad method
using (var client = new ImapClient())
{
client.Connect("outlook.office365.com", 993, true);
client.Authenticate(userName + #"\" + sharedMailboxAlias, password);
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly);
Console.WriteLine("Total messages: {0}", inbox.Count);
Console.WriteLine("Recent messages: {0}", inbox.Recent);
client.Disconnect(true);
}
}
The shared mailbox alias usually defaults to the left part of the email address before the #
Updated: As per #Nischo comment - removing XOAUTH2 is no longer required. For more details: https://github.com/jstedfast/MailKit/issues/566
So removed the following line as it's no longer
client.AuthenticationMechanisms.Remove("XOAUTH2");

The answer by Sean on Jan 17 is correct. Note that you MUST remove the XOATH2 authentication as Office 365 does not support it even though it says it does when you first connect. MailKit then tries to use XOAUTH2 and has an internal exception when it fails to work. This is probably a bug in MailKit.

Related

How can we access the exchange mailboxes via EWS when the user has no own mailbox?

We want to access mailboxes via EWS (Exchange Web Services) with an dedicated user who has no own mailbox.
The target is to cover all Exchange Server version 2007-2019.
Reason why we want to have an dedicated user with no mailbox: We want analyze all mailboxes in an Exchange Server by an software. But therefore we not really need an user and even an mailbox. Only the data inside the mailboxes are interesting for the software.
We use Independentsoft´s API to access the EWS:
var lCredential = new NetworkCredential("ADUserWithNoMailbox", "Password");
m_Service = new Service("https://hostname/EWS/Exchange.asmx", lCredential);
try
{
FindFolderResponse lResponse = m_Service.FindFolder(StandardFolder.MailboxRoot);
// [...]
}
catch (Exception e)
{
// cast in into multiple expected types
var lServiceRequestException = e as Independentsoft.Exchange.ServiceRequestException;
if (lServiceRequestException.ResponseCode == "ErrorNonExistentMailbox")
{
// lServiceRequestException.Message shows: "No mailbox with such guid."
// [...]
}
// [...]
throw;
}
Our user ADUserWithNoMailbox which is in the Active Directory has no mailbox. Therefore an exception occurs with the message:
"No mailbox with such guid."
Question: How can we access the exchange mailboxes via EWS when the user has no own mailbox?
It should work okay if the servers are patched to the correct levels eg there can be problem like https://support.microsoft.com/en-us/topic/-the-smtp-address-has-no-mailbox-associated-with-it-error-when-you-access-a-user-s-mailbox-by-using-ews-application-c8e31e36-b6e2-229e-cc78-305ab9fea94a. I've always found this to be problematic if your deploying apps in different customer environments and found for most OnPrem deployments giving the Service account your using a Mailbox is not a problem, to stop it appearing in address lists most customers can just hide it. (Office365 is a different matter because of the cost of consuming a licence but you can use App tokens which don't require a user or mailbox)
Probably for your requirement using EWS Impersonation https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/impersonation-and-ews-in-exchange is a better option as that will give you access to all Mailboxes.

The specified object was not found in the store., The process failed to get the correct properties

I'm trying to achieve folder from a user with an admin user (just for test)
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.Credentials = new WebCredentials("AdminUsername", "AdminPass");
service.AutodiscoverUrl("UserItryToImpersonate#domain.com", RedirectionUrlValidationCallback);
//creates an object that will represent the desired mailbox
Mailbox mb = new Mailbox(#"UserItryToImpersonate#domain.com");
// Create Calendar object for testing
CalendarFolder folder1 = new CalendarFolder(service);
folder1.DisplayName = "UserItryToImpersonate#domain.com";
folder1.Save(WellKnownFolderName.Calendar);
FolderId rootCalendarFolder = new FolderId(WellKnownFolderName.Calendar, "UserItryToImpersonate#domain.com");
UserConfiguration.Bind(service, "CategoryList", rootCalendarFolder, UserConfigurationProperties.All); //// error here....
That error is happening because the user I try to impersonate is a new user and never log in to OWA even once...
when I logged into OWA it worked...
How can I bypass that...
How can I create the objects from remote???
Most of the Topics say it Permissions Error... but I sure I have the permissions...
That problem solved when I take permission and enter OWA as impersonate him...
thank you in advance
That error is happening because the user I try to impersonate is a new user and never log in to OWA even once... when I logged into OWA it worked...
It sounds like the Mailbox hasn't been provisioned and logging into OWA is just kicking off that process. Using EWS alone won't do the provisioning the easiest way it just send an Email to the Mailbox. Another method I've used in the past is if you run Test-MapiConnectivity https://learn.microsoft.com/en-us/powershell/module/exchange/mailboxes/test-mapiconnectivity?view=exchange-ps from the Exchange Management Shell before you run your EWS code that will always ensure that the Mailbox has been provisioned.

How to connect to an Exchange sub account using EWS?

I have been developing an email client within Visual Studio 2019 using C#.
While also using the Microsoft.Exchange.WebServices library.
I need to connect to an email, but that email has sub accounts on it.
Example:
username/email: SomeRandomMail#domain.com
sub account: received#domain.com
I have no idea how to connect to the sub account or if you can?
// The code used to connect to an email address.
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials(Email, Password, Domain);
service.Url = new Uri(Asmx);
There is no such thing as a sub account in Exchange you just have mailboxes and a Mailbox maybe assigned more the one Email Address. Or you may have a Delegate Mailbox or Shared Mailbox which are separate mailbox that you may have been granted access to.
The code you posted just finds the best CAS Endpoint for EWS for the credentials you used it has nothing to do with connecting to a mailbox. If you want to access a Mailbox other then those of the credentials you using then you should just be using the FolderId overload to specify the Mailbox you want to access. eg if your shared Mailbox was called Shared#domain.com then use
FolderId SharedMailbox = new FolderId(WellKnownFolderName.Inbox,"Shared#domain.com");
ItemView itemView = new ItemView(1000);
service.FindItems(SharedMailbox,itemView);

Accessing a generic process inbox using EWS

I am trying to use EWS to access a process mailbox. For some automated queries we created a genric process mailbox. I want to parse emails by watching the Process inbox.
My code was working earlier with the old exchange server. But after migration to office 365 it fails.
I am able to access my mailbox and parse on the office 365 using my credentials.
How do I access this process mailbox? Earlier I create an ExchangeService and connect to the process email address with UseDefaultCredentials = true.
I set the AutoDiscoverURl and used DefaultCredentials. But When I tried to read emails I get "The SMTP address has no mailbox associated with it."
EDIT:
I tried to use my own credentials instead of the Default Credentials.
string smtpaddress = "somesharedsmtp#domain.com";
es.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
es.Credentials = new WebCredentials("myemail", "mypassword");
es.AutodiscoverUrl(smtpaddress, RedirectionCallback);
FolderId SharedMailbox = new FolderId(WellKnownFolderName.Inbox, "somesharedsmtp#domain.com");
Folder sharedInbox = Folder.Bind(es, SharedMailbox);
At this point I can check sharedInbox containing the details of the Inbox. I can see the unread email count and others.
But when I access
ItemView itemView = new ItemView(100);
FindItemsResults<Item> findResults1 = es.FindItems(pqInbox.Id, itemView);
I get exception "SMTP address has no mailbox associated with it"
disclaimer: I haven't worked with EWS in a while.
You can't use the default credentials for Office 365. You'll need to provide either the basic credential or use an OAuth token.
You should confirm that the account was migrated to Office 365. Login to OWA and look at the URL to make sure you are using Office 365 and not an on-premise server.
This was already answered by Exchange Web Services: UseDefaultCredentials property

Outlook Redemption library - Accessing shared mailboxes / specific folders with a service account

I’m converting an existing piece of code using Redemption (an MS Exchange library) to operate under a service account. The issue I’m having is that I’m unable to look up mail folders as I previously was.
The first hurdle in moving to a service account was overcome by switching
_rdoSession.Logon() // <- Which uses the account’s MAPI profile, and throws an exception under a service account
To:
_rdoSession.LogonExchangeMailbox("", "mailserver.example.com");
The problem comes with trying to access specific folders. Previously I was able to use:
_session.GetFolderFromPath("\\\\Mailbox - Example shared mailbox\\Inbox\\FolderOne");
_session.GetFolderFromPath("\\\\Mailbox - Example shared mailbox\\Inbox\\FolderTwo");
Under a service account, I can’t address shared mail accounts with that same syntax, as I get the error:
Could not open store "Mailbox – Example shared mailbox": Error in IMAPITable.FindRow: MAPI_E_NOT_FOUND
Some Googling has shown the beginning step is to use:
_session.Stores.GetSharedMailbox("Example shared mailbox ")
I've verified this returns the correct shared mailbox object.
However - from there, there are no search methods. I can try my luck with building new code to navigate the folder structure from the .RootFolder property, but this seems like a hack.
How should I be accessing specific folders in a shared mailbox, run under a service account in Redemption?
You can use either
store = _session.Stores.GetSharedMailbox("Example shared mailbox ");
folder = store.IPMRootFolder.Folders.Item("Inbox").Folders.Item("FolderTwo");
or
store = _session.Stores.GetSharedMailbox("Example shared mailbox ");
folder = store.GetDefaultFolder(olFolderInbox).Folders.Item("FolderTwo");

Categories

Resources