With recent changes in Exchange web services where basic authentication will be discontinued in Office 365, I'm switching my code to Oauth.
Everything is working fine except when I'm accessing a shared mailbox or Unified group.
By experience, In basic auth, I must not set the ImpersonatedUserId.
with Oauth:
- If I don't set this header, I receive an error saying
"ExchangeImpersonation SOAP header must be present for this type of
oauth token".
- If I set this header, I receive an error saying "The
SMTP address has no mailbox associated with it."
The mailbox exists AND I access it using basic authentication.
The problem is the following: how to programmatically access a sharedmailbox (or Unified group mailbox) using oauth
Oauth setup : App Permission correctly set (If I access a user mailbox programmatically it works, If I access a shared mailbox, it doens not)
Code to generate token
_service = new ExchangeService(ExchangeVersion.Exchange2013);
_service.TraceFlags = TraceFlags.None;
_service.PreAuthenticate = true;
_service.Timeout = 600000; // 10 minutes
string token = GetTokenForUserAsync().Result;
_service.Credentials = new OAuthCredentials(token);
_service.UseDefaultCredentials = false;
string url = "https://outlook.office365.com/ews/Exchange.asmx";
_service.Url = new Uri(url);
_service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "sharedmailbox@domain.com");
_fdInbox = Microsoft.Exchange.WebServices.Data.Folder.Bind(_service, new FolderId(WellKnownFolderName.Inbox, "sharedmailbox@domain.com"));
private async System.Threading.Tasks.Task<string> GetTokenForUserAsync()
{
string domainName = _context.MigrationDefinition.TargetConfiguration.DomainName;
string clientId = _context.MigrationDefinition.TargetConfiguration.ClientID;
string clientSecret = _context.MigrationDefinition.TargetConfiguration.ClientSecret;
string microsoftLoginUrl = AzureURL.GetLoginUrl(_context.MigrationDefinition.TargetConfiguration.ServerRegion);
string loginUrl = string.Format("{0}/{1}", microsoftLoginUrl, domainName);
loginUrl = "https://login.microsoftonline.com/" + domainName + "/oauth2/v2.0/token";
string redirectUri = "https://myapp.azurewebsites.net";
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(loginUrl)
.WithRedirectUri(redirectUri)
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
Microsoft.Identity.Client.AuthenticationResult result = await app.AcquireTokenForClient(ewsScopes).ExecuteAsync();
return result.AccessToken;
}
question from:
https://stackoverflow.com/questions/65938777/exchangeimpersonation-soap-header-must-be-present-for-this-type-of-oauth-token-a 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…