I'm receiving error 403 when trying to read e-mails using code below
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenant)
.WithAuthority(new Uri(String.Format(CultureInfo.InvariantCulture, instance, tenant)))
.WithRedirectUri(redirectUri)
.Build();
string[] scopes = new string[] { "https://outlook.office365.com/.default" };
result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
if (result != null)
{
string token = result.AccessToken;
service = new ExchangeService
{
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
Credentials = new OAuthCredentials(token),
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, email)
};
service.HttpHeaders.Add("X-AnchorMailbox", email);
}
var emails = service.FindItems(WellKnownFolderName.Inbox, new FolderView(10));
On Azure portal I did:
Register new application and copied tenant id, client id, client secret
Added EWS.AccessAsUser.All in API auth.
But still receiving 403 - Forbidden when trying to get email from inbox
What am I missing?
Related
I am getting The Url property on the ExchangeService object must be set, while sending email from O365 EWS using modern authentication.
My code works perfectly from local machine. But while deploying it on PROD IIS server it gives me error while sending email.
Below is my code.
public async void SendMail(string fromId, string toId, string body, string priMailId, string appId, string clientSecret, string tenantId)
{
var ewsClient = await ModernAuthenticate(priMailId, appId, clientSecret, tenantId);
if (!errorMsg)
{
var msg = new EmailMessage(ewsClient);
msg.ToRecipients.Add(toId.Trim());
msg.From = fromId;
msg.Subject = "Test Email Kindly Ignore";
msg.Body = "Test Email Kindly Ignore";
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)768 | (SecurityProtocolType)3072;
msg.Send();
}
}
public async Task<ExchangeService> ModernAuthenticate(string priMailId, string appId, string clientSecret, string tenantId)
{
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)768 | (SecurityProtocolType)3072;
var ewsClient = new ExchangeService();
var cca = ConfidentialClientApplicationBuilder
.Create(appId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
try
{
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync();
ewsClient.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, priMailId);
ewsClient.HttpHeaders.Add("X-AnchorMailbox", priMailId);
}
catch (Exception ex)
{
}
return ewsClient;
}
Can anyone help me out in this
Looking at your code you don't do anything with the exception in
try
{
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync();
ewsClient.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, priMailId);
ewsClient.HttpHeaders.Add("X-AnchorMailbox", priMailId);
}
catch (Exception ex)
{
}
So if your authentication if failing you would never know and it would never reach
ewsClient.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");
so the error your getting is what you would expect. You need to improve your error handing and debugging so you can work out what's happening in your production server (eg it could be proxying, connectivity etc).
I created a ClientID & Client Secret (using this guide) to authenticate a desktop application (C#/.NET) to send emails from a Gmail account, with Gmail SMTP OAUTH because Google will no longer support less secure apps to send e-mail.
The first time application ran, browser was open and i had need to enter on accounts.google.com with my credential and mail has been sent.
After i receveid an Error "JWT is expired" when i try to execute
var jwtPayload = GoogleJsonWebSignature.ValidateAsync(asyncUserCredential.Token.IdToken).Result;
I can't able to understand how it works and how i can obtain a refreshed token for passing to ValidateAsync method.
This is code used:
private async Task AuthenticateAsync()
{
bool expired;
string mytoken;
try
{
string CLIENT_ID = "41527eeeeee489-xxxxxxxxxxxxxxxxxxxusercontent.com";
asyncUserCredential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = CLIENT_ID,
ClientSecret = "GOCXXXXXXXXXXXXXXXXXXX"
},
new[] { "email", "profile", "https://mail.google.com/" },
"user",
CancellationToken.None
);
var sFromMailAddress = "office#gmail.com";
var jwtPayload = GoogleJsonWebSignature.ValidateAsync(asyncUserCredential.Token.IdToken).Result;
var mailMessage = new MimeMessage();
mailMessage.From.Add(new MailboxAddress("Office", sFromMailAddress));
mailMessage.To.Add(new MailboxAddress("Frank", "someone#gmail.com"));
mailMessage.Subject = "Automated Mail with OAuth";
mailMessage.Body = new TextPart("plain")
{
Text = "Hello"
};
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTls);
// use the access token
var oauth2 = new SaslMechanismOAuth2(sFromMailAddress, asyncUserCredential.Token.AccessToken);
client.Authenticate(oauth2);
client.Send(mailMessage);
client.Disconnect(true);
}
}
catch (Exception ex)
{
string msg = ex.Message;
if (ex.InnerException != null)
msg = ex.InnerException.Message;
if (msg.Contains("JWT has expired"))
{
expired = true;
}
else if (msg.Contains("JWT invalid"))
{
//XtraMessageBox.Show("JWT invalid" , "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
//XtraMessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
//return string.Empty;
}
}
For sending email used:
using MailKit.Net.Smtp;
using MimeKit;
using MailKit.Security;
I have written below code to send email using Outlook Office365.
ExchangeService myService = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
myService.Credentials = new WebCredentials(sender_mailId,sender_password);
try
{
string serviceUrl = <<service url>> // This URL
myService.Url = new Uri(serviceUrl);
EmailMessage emailMessage = new EmailMessage(myservice);
emailMessage.Subject = "Subject test ";
emailMessage.Body = new MessageBody("Testing Exchange Web Service API");
emailMessage.ToRecipients.Add(to_email_id);
emailMessage.Send();
}
catch (SmtpException exception)
{
string msg = "Mail cannot be sent (SmtpException):";
msg += exception.Message;
throw new Exception(msg);
}
What web service URL should be used?
The below code is worked to send or save to email draft.
static void CheckEmail()
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = new WebCredentials(senderEmailId, password);
service.AutodiscoverUrl(senderEmailId, RedirectionUrlValidationCallback);
EmailMessage emailMessage = new EmailMessage(service);
emailMessage.Subject = "Test office 365 project draft ";
emailMessage.Body = new MessageBody("Testing Exchange Web Service API");
emailMessage.ToRecipients.Add(emailTo);
//send email
emailMessage.Send();
//save to draft
emailMessage.Save(WellKnownFolderName.Drafts);
}
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;
}
I'm trying to retrieve the list of appointment from a specific meeting room using Exchange Web Services managed API.
I'm using Office365 and Exchange Online.
I tried the following code.
try
{
ExchangeService newExchangeService = new ExchangeService (ExchangeVersion.Exchange2013);
//Admin permission account
newExchangeService.Credentials = new NetworkCredential(username, password);
newExchangeService.AutodiscoverUrl(email-id, RedirectionUrlValidationCallback);
SearchFilter.SearchFilterCollection searchFilter = new SearchFilter.SearchFilterCollection();
searchFilter.Add(new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, startDate));
searchFilter.Add(new SearchFilter.IsLessThanOrEqualTo(AppointmentSchema.Start, endDate));
ItemView view = new ItemView(50);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.AppointmentType, AppointmentSchema.End);
var calendarSearch = new FolderId(WellKnownFolderName.Calendar, new Mailbox("adachi#fairuse.jp"));
var appointmentresult = service.FindItems(calendarSearch, searchFilter, view);
}catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
I got the error:
The specified folder could not be found in the store.
Apparently this is a permissions issue, but where is this permission set?
You don't have to create a new mailbox, a string with only the mail address is enough:
var calendarSearch = new FolderId(WellKnownFolderName.Calendar, "adachi#fairuse.jp");
As for permissions: Ar you in a domain? Do you use NTLM or ADFS?
I am trying to connect online TFS using WCF service but it is throwing me exception "TF30063: You are not authorized to access https://abdul-r.visualstudio.com/DefaultCollection/TestTFS.".
Below is my sample code
NetworkCredential netCred = new NetworkCredential(
"*MyEmail*",
"*MyPassword*");
BasicAuthCredential basicCred = new BasicAuthCredential(netCred);
TfsClientCredentials credential = new TfsClientCredentials(basicCred);
credential.AllowInteractive = false;
string TFSServerPath = "https://abdul-r.visualstudio.com/DefaultCollection/TestTFS";
using (TfsTeamProjectCollection tfs1 = new TfsTeamProjectCollection(new Uri(TFSServerPath), credential))
{
tfs1.EnsureAuthenticated();
}
Any help would be appreciated.