Unable to send mail using graph API - c#

Unable send mail using Microsoft-Graph-API (Azure AD B2c).
I have tried following code but not working
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(appId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
Message message = new Message
{
Subject = "Subject of mail",
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = "Mail content",
},
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = email,
}
}
},
};
await graphClient.Me.SendMail(message).Request().PostAsync();
It gives following error :
Code: OrganizationFromTenantGuidNotFound
Message: The tenant for tenant guid 'xxxxxx' does not exist.
Inner error:
AdditionalData:
requestId: 0ecdb3f9-a210-4259-bd62-0c79e757d1f6
date: 2020-08-05T02:17:07
request-id: 0ecdb3f9-a210-4259-bd62-0c79e757d1f6
ClientRequestId: 0ecdb3f9-a210-4259-bd62-0c79e757d1f6
Note : Also Given permission for Mail.Send

This is because your Azure AD B2C tenant doesn't have an Exchange online license under O365 subscription.
So the B2C user doesn't have a mailbox to send the email although its UPN looks like an email address.
Try to assign an O365 subscription to the tenant and add an Exchange online license to the B2C user if possible.

Related

MS Graph SDK retrive mailboxSettings return invalid user error

I tried to use MS Graph API to implement a backend API to access other users email setting (for getting out-of-office message). As it is backend API, client credential flow is used. I already granted the permissions "MailboxSettings.Read" and "MailboxSettings.ReadWrite" with application type.
I used my free Azure account for testing. Assume my login account is test#hotmail.com, then my Azure domain is testhotmail.onmicrosoft.com.
I created one more user client#testhotmail.onmicrosoft.com
I can get the result using Graph Explorer as below
https://graph.microsoft.com/v1.0/users/test#hotmail.com
https://graph.microsoft.com/v1.0/users/test#hotmail.com/mailboxSettings
https://graph.microsoft.com/v1.0/users/client#testhotmail.onmicrosoft.com
But it return error for below using Graph Explorer
{
"error": {
"code": "ErrorInvalidUser",
"message": "The requested user 'client#testhotmail.onmicrosoft.com' is invalid."
} }
https://graph.microsoft.com/v1.0/users/client#testhotmail.onmicrosoft.com/mailboxSettings
3a. If call by MS Graph SDK to get the user info for client#testhotmail.onmicrosoft.com as below, it is success
var scopes = new[] { "https://graph.microsoft.com/.default" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var user = await graphClient.Users["client#testhotmail.onmicrosoft.com"].Request().GetAsync();
3b. If call by MS Graph SDK to get the user info for test#hotmail.com, it returns error
Microsoft.Graph.ServiceException: 'Code: Request_ResourceNotFound
Message: Resource 'test#hotmail.com' does not exist or one of its
queried reference-property objects are not present.
var user = await graphClient.Users["test#hotmail.com"].Request().GetAsync();
If call by MS Graph SDK to get the mailbox setting as below, it returned error
Microsoft.Graph.ServiceException: 'Code: ErrorInvalidUser Message: The
requested user 'test#hotmail.com' is invalid.
var scopes = new[] { "https://graph.microsoft.com/.default" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var mail = await graphClient.Users["test#hotmail.com"].Request().Select("MailboxSettings").GetAsync();
Or returned error for below
Microsoft.Graph.ServiceException: 'Code: ResourceNotFound Message:
Resource could not be discovered.
var mail = await graphClient.Users["client#testhotmail.onmicrosoft.com"].Request().Select("MailboxSettings").GetAsync();
using Microsoft.Graph;
using Azure.Identity;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "aad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var user = await graphClient.Users["xx#xx.onmicrosoft.com"]
.Request()
.Select("MailboxSettings")
.GetAsync();
var automaticRepliesSetting = user.MailboxSettings.AutomaticRepliesSetting;
Could you pls try this? By the way you may also try to add the 2 application permissions which mentioned in the document: MailboxSettings.Read, MailboxSettings.ReadWrite. And the most important is, your error message is invalid user, so I'm afraid you can use user_PrincipalName instead of myuser#hotmail.com. You can try to get the user_id in Azure AD potal or from the result for await graphClient.Users["myuser#hotmail.com"].Request().GetAsync();.
You are using hotmail.com , as per the doc you should also have either a personal Microsoft account with a mailbox on Outlook.com, or a Microsoft work or school account.
Hope this helps
Thanks

Error - "The requested user is invalid" while sendmail using graph api

I am trying to send mail on behalf of some users using the Microsoft Graph API through my Winforms application. I registered the app in Application Registration at Azure Portal in my tenant and assigned application permissions for sending mail to the app. I am using client credentials flow for sending mail.
The mail is successfully sent when sending the mail on behalf of my tenant user. Then I granted the admin consent to my app from another tenant and tried to send mail on behalf of that tenant's user but I get an error
Code: ErrorInvalidUser
Message: The requested user 'foo#tenanttwo.onmicrosoft.com' is invalid.
That user has a valid license of O365.
Can we send the mail on behalf of other tenant's user using the Microsoft Graph API? If yes then please help me what else I need to do?
This is the code I'm using:
var scopes = new[] { "https://graph.microsoft.com/.default" };
// using Azure.Identity;
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
// https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(tenantID, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var message = new Microsoft.Graph.Message
{
Subject = strSubject,
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = strBody
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = strTo
}
}
}
};
var saveToSentItems = true;
await graphClient.Users[senderMail]
.SendMail(message, saveToSentItems)
.Request()
.PostAsync();

One or more errors occurred. (ROPC does not support MSA accounts. See https://aka.ms/msal-net-ropc for details. )

I invited some users to use my Web API.
The invitation mails were sent successfully and the users are shown in the users list in Azure AD.
When users try to login to my Web API they receive the following error:
One or more errors occurred. (ROPC does not support MSA accounts. See
https://aka.ms/msal-net-ropc for details. )
The code below sends the invitations
[EnableCors("CorsPolicy")]
[HttpPost, Route("invite")]
[AllowAnonymous]
[ProducesResponseType(200)]
[ProducesResponseType(400)]
[Produces("application/json")]
public ActionResult SendInvitation(UserModel user)
{
try
{
string clientId = Configuration["AzureAd:ClientId"];
string tenantID = Configuration["AzureAd:TenantId"];
string authority = Configuration["AzureAd:Authority"];
IPublicClientApplication app = PublicClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantID)
.WithAuthority(authority)
.Build();
string[] scopes = new string[] { "User.Invite.All" };
// Build the Microsoft Graph client. As the authentication provider, set an async lambda
// which uses the MSAL client to obtain an app-only access token to Microsoft Graph,
// and inserts this access token in the Authorization header of each API request.
GraphServiceClient graphServiceClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
{
var securePassword = new SecureString();
foreach (char c in user.Password.ToCharArray()) // you should fetch the password
securePassword.AppendChar(c); // keystroke by keystroke
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await app
.AcquireTokenByUsernamePassword(scopes, user.UserName, securePassword).ExecuteAsync();
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
})
);
var invitation = new Invitation
{
InvitedUserEmailAddress = "user#email.com",
InviteRedirectUrl = "https://webapi.azurewebsites.net",
SendInvitationMessage = true
};
graphServiceClient.Invitations
.Request()
.AddAsync(invitation);
return Ok("Invitation sent.");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
I'm afraid that your design cannot be implemented.
Please see the Important tip in ROPC flow document.
MSA (personal accounts) can't use ROPC no matter whether it is invited into AAD tenant or not.
ROPC flow only works for work accounts.
It is also stated in the link https://aka.ms/msal-net-ropc.
You can consider using Client credentials flow (application permission) or Auth code flow (delegated permission, requires interactively login).
Find the related auth provider examples in this link.

How to reset password on Azure AD B2C user account using MSAL C#, .net core?

Is it possible to reset the user password created on my b2c tenant?
Trying to find something on the documentation here https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-overview, but I couldn't find it. Maybe I am blind, so can someone point how to do it?
You could reset the password with this Microsoft Graph API.
When updating the passwordProfile property, the following permission is required: Directory.AccessAsUser.All.
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var user = new User
{
BusinessPhones = new List<String>()
{
"+1 425 555 0109"
},
OfficeLocation = "18/2111"
};
// If authorize without user, you need to add application permission. graphClient.Users[user-object-id].Request().UpdateAsync(user);
await graphClient.Me
.Request()
.UpdateAsync(user);

How to sent invitation email using Microsoft Graph API

I want to invite an user in our Active Directory/Tenant. For this using Micorosoft Graph API. Code is used as below
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantID)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var invitation = new Invitation
{
InvitedUserEmailAddress = "myemailaddress#gmail.com",
InviteRedirectUrl = "https://myapp.com"
};
await graphClient.Invitations
.Request()
.AddAsync(invitation);
After this, I can see the user in Azure's Active directory portal. But don't get an invitation email.
However, when I click on Resend Invite from Azure Portal then the invite email is coming.
Can you please guide, why the invite email is not coming when sending invite from API?
You need to set SendInvitationMessage to true in your Invitation object:
var invitation = new Invitation
{
InvitedUserEmailAddress = "myemailaddress#gmail.com",
InviteRedirectUrl = "https://myapp.com",
SendInvitationMessage = true
};
For more info you can read the Docs
sendInvitationMessage Boolean Indicates whether an email should be
sent to the user being invited or not. The default is false.

Categories