Unable to send email via Office 365 C# client library - c#

I'm trying to send an email with the Office 365 C# client library. I've successfully performed other operations with it, i.e. getting a folder and getting messages, but am unable to send an email.
I'm using a MailHelper class provided in a Microsoft sample. This is the method:
internal async Task<String> ComposeAndSendMailAsync(string subject,
string bodyContent,
string recipients)
{
// The identifier of the composed and sent message.
string newMessageId = string.Empty;
// Prepare the recipient list
var toRecipients = new List<Recipient>();
string[] splitter = { ";" };
var splitRecipientsString = recipients.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
foreach (string recipient in splitRecipientsString)
{
toRecipients.Add(new Recipient
{
EmailAddress = new EmailAddress
{
Address = recipient.Trim(),
Name = recipient.Trim(),
},
});
}
// Prepare the draft message.
var draft = new Message
{
Subject = subject,
Body = new ItemBody
{
ContentType = BodyType.HTML,
Content = bodyContent
},
ToRecipients = toRecipients
};
try
{
// Make sure we have a reference to the Outlook Services client.
var outlookClient = await AuthenticationHelper.GetOutlookClientAsync("Mail");
//Send the mail.
await outlookClient.Me.SendMailAsync(draft, true);
return draft.Id;
}
//Catch any exceptions related to invalid OData.
catch (Microsoft.OData.Core.ODataException ode)
{
throw new Exception("We could not send the message: " + ode.Message);
}
catch (Exception e)
{
throw new Exception("We could not send the message: " + e.Message);
}
}
My arguments are not null and seem to be correct. The error I'm getting is: "Cannot read the request body.".
I've made sure my application is registered with the right permissions so I'm at a loss. Does anyone know what's going on with my code?

Try capturing a Fiddler trace of the request and check the Content-Type header.

Related

Sending emails between accounts using Microsoft Graph using Azure AD produces invalid IP error

I registered a daemon app in Azure AD and am creating a class to do some basic things like send and delete emails but I get an error when trying to send between two #*.onmicrosoft.com email boxes. I am able to send from Gmail to these emails for example but not between the two emails for some reason.
Error:
The way I am sending emails is as follows:
public async Task Send(string[] to, string subject, string body, FileInfo[] attachments = null, bool saveToSentItems = true, bool isBodyHTML = false)
{
var msg = new Message
{
Subject = subject,
Body = new ItemBody { ContentType = (isBodyHTML) ? BodyType.Html : BodyType.Text, Content = body },
ToRecipients = to.ToList().Select(x => new Recipient() { EmailAddress = new EmailAddress { Address = x } })
};
await graphClient.Users[email].SendMail(msg, saveToSentItems).Request().PostAsync();
}
So I think it's because of trial licenses and couldn't figure out way yet to turn off the IP filtering:

Microsoft.Graph SDK SendMail As User - 400 - Unexpected Exception or Open navigation properties are not supported

I'm working on an application that needs to send email notifications and reminders to users when they have actions to complete. A user submits data, then the app notifies other users to perform actions in a specific order (i.e. User 1: Task 1, after Task 1 is complete, User 2: Task 2, etc.) - if a user is taking too long to perform their action, the system will remind them then defer to their manager (via a Windows service or similar). Due to this, I can't send messages on behalf of the current signed in user - it needs to be able to send messages on its own. It is preferred to send on behalf of the user that submitted the data, so subsequent users can reply directly to them.
I'm using the Microsoft Graph Client Library v1.10.0. Running my code yields an aggregate exception ultimately boiling down to a code 400, code "generalException", message "Unexpected exception returned from the service." I've used LinqPad to look into the Graph objects, and attempted to reproduce the call in Postman, which yields a 400 with a message of "Open navigation properties are not supported on OpenTypes. Property name: 'microsoft.graph.sendmail'."
More thorough details:
Application has Microsoft Graph -> Send mail as any user, Read all groups, Read all users' full profiles permissions.
Calling GraphServiceClient.Client.Users["MyUPN"].SendMail(email, true).Request().PostAsync() yields a 400 general exception with Unexpected exception returned from the service. (Full code below)
Looking at the request, I found it's calling https://graph.windows.net:443/{{tenantId}}/users/{{MyUPN}}/microsoft.graph.sendMail?api-version=1.6 and attempted to make the same call via Postman (with a valid token), which yielded a 400 bad request with message Open navigation properties are not supported on OpenTypes. Property name: 'microsoft.graph.sendMail'.
Full Code:
String MyEmailAddress = "";
String MyUpn = "";
String TenantId = "";
String AppGuid = "";
String AppKey = "";
var sender = new Microsoft.Graph.Recipient()
{
EmailAddress = new Microsoft.Graph.EmailAddress() { Address = MyEmailAddress }
};
var email = new Microsoft.Graph.Message
{
Sender = sender,
From = sender,
Subject = "Test",
Body = new Microsoft.Graph.ItemBody()
{
Content = "Test Body",
ContentType = Microsoft.Graph.BodyType.Text
}
};
email.ToRecipients = new List<Microsoft.Graph.Recipient>(){ sender };
email.BodyPreview = "Test Summary";
GraphSdk _Sdk = new GraphSdk(TenantId, AppGuid, AppKey);
// Where the error throws
await _Sdk.Client.Users[MyUpn].SendMail(email, true).Request().PostAsync();
As a test, I also tried await _Sdk.Client.Users[MyUpn].Messages.Request().Top(20).GetAsync(); which yielded the same error. Other Graph calls, like getting a user's groups or manager, work fine - this error only appears on email-related calls.
Update 9/19/2018 AM
It looks like I can get emails working if I use a certificate to generate the token instead of the Key -> Password; and call the Outlook API instead. Unfortunately, that doesn't work through the GraphServiceClient and Graph API - it can use the certificate, and use the Outlook API base URL, but the microsoft.graph.sendMail action is just sendMail in the Outlook API.
For maintainability, I'd still like to get it all working under the Graph API so I'm still looking for an answer to the original question.
At some point I had set the BaseUrl for the client to https://graph.windows.net:443/{{tenantId}}, possibly due to the varying branding over the past few years (Microsoft Graph vs Azure Graph). Under current recommendations for the Microsoft.Graph it should be https://graph.microsoft.com/v1.0/ - which also appears to be the default value.
Additionally, I had to switch to using a certificate instead of the Azure-generated Key -> Password for the app.
Total working code is:
String AADTenantId = "";
String AppGuid = "";
String SenderAddress = "";
String SenderId = "";
String ToAddress = "";
String SubjectText = "";
String BodyText = "";
Byte[] Certificate = ...GetCertBytes...
String CertPassword = "";
var client = new GraphServiceClient(new DelegateAuthenticationProvider(
async requestMessage =>
{
var authContext = new AuthenticationContext($"https://login.microsoftonline.com/{AADTenantId}");
var cert = new X509Certificate2(Certificate, CertPassword);
var clientAssertion = new ClientAssertionCertificate(AppGuid, cert);
AuthenticationResult authresult = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientAssertion);
// Append the access token to the request
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authresult.AccessToken);
}));
var sender = new Recipient()
{
EmailAddress = new EmailAddress() { Address = SenderAddress }
};
var email = new Message
{
Sender = sender,
From = sender,
Subject = SubjectText,
Body = new ItemBody()
{
Content = BodyText,
ContentType = BodyType.Text
},
ToRecipients = new List<Recipient>() {
new Recipient() { EmailAddress = new EmailAddress { Address = ToAddress }}
}
};
await client.Users[SenderId].SendMail(email, true).Request().PostAsync();
According to your description, you want send an email but get an 400 error.
Based on my test, we can use the following steps to send an email.
step1, we should get a graphClient which is a authenticated HttpClient.
The code like this:
GraphServiceClient graphServiceClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
string accessToken = await MsalAuthProvider.Instance.GetUserAccesstokenAsync();
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessToken);
}));
return graphServiceClient;
We can refer to the simple code in the official document.
step2, we can use the following code to send a mail:
public async Task<bool> SendAsync(EmailAddress toaddress)
{
var email = new Message
{
Body = new ItemBody
{
Content = "Test for sending eamil ",
ContentType = BodyType.Text,
},
Subject = "Test for sending eamil",
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = toaddress
}
},
};
try
{
await _serviceClient.Me.SendMail(email).Request().PostAsync(); // the _serviceClient is the result in the step1.
return true;
}
catch (Exception ex)
{
return false;
}

SendGrid V3 api with C# not able to send mail

This is the code I am using. For some reason it gives an error: 'UnAuthorised'. Any ideas why this may be happening. The Api-key is correctly configured.
String apiKey = Environment.GetEnvironmentVariable("SG.7cSY-INMQnCwIzmonlgZvA.zNtNDycx......", EnvironmentVariableTarget.User);
dynamic sg = new SendGrid.SendGridAPIClient(apiKey, "https://api.sendgrid.com");
Email from = new Email("account#id.com");
String subject = "Hello World from the SendGrid CSharp Library";
Email to = new Email("someone#gmail.com");
Content content = new Content("text/plain", "Textual content");
Mail mail = new Mail(from, subject, to, content);
//Email email = new Email("test2#example.com");
//mail.Personalization[0].AddTo(email);
String ret = mail.Get();
string requestBody = ret;
Console.WriteLine(ret);
try
{
dynamic response = sg.client.mail.send.beta.post(requestBody: requestBody);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Body.ReadAsStringAsync().Result);
Console.WriteLine(response.Headers.ToString());
}
catch (Exception ex) {
Console.WriteLine("SendGrid Error: {0}",ex.Message);
}
In this line of code:
String apiKey = Environment.GetEnvironmentVariable("SG.7cSY-INMQnCwIzmonlgZvA.zNtNDycx......", EnvironmentVariableTarget.User);
the first parameter is the name of the environment variable that holds the value of your SendGrid API Key, scoped to the user's account. If you are not using environment variables and are comfortable with putting your API Key in your code (not recommended, but this will allow you test that it works), you would do:
String apiKey = "SG.7cSY-INMQnCwIzmonlgZvA.zNtNDycx......";

Missing email from "name" when using AWS SES API in C#

When I send an email using AWS SES in a C# application the email names don't show in the received email - only the email addresses show.
The from/to emails I've added are strings in the form " Their Name". It's clearly understanding that as it's sending it to the right place, but just stripping out the names.
internal void SendEmail()
{
try
{
// Construct an object to contain the recipient address.
Destination destination = new Destination();
destination.ToAddresses = toList;
if (ccList.Count > 0) destination.CcAddresses = ccList;
if (bccList.Count > 0) destination.BccAddresses = bccList;
// Create the subject and body of the message.
Body bodyobj = new Body();
if(body!=null) bodyobj.Text = new Content(body);
if(html!=null) bodyobj.Html = new Content(html);
// Create a message with the specified subject and body.
Message message = new Message(new Content(subject), bodyobj);
// Assemble the email.
SendEmailRequest request = new SendEmailRequest();
request.Destination = destination;
request.Message = message;
request.Source = from;
AmazonSimpleEmailServiceClient client = new AmazonSimpleEmailServiceClient(Amazon.RegionEndpoint.EUWest1);
SendEmailResponse ser = client.SendEmail(request);
sent=true;
}
catch (Exception e)
{
errmsg = e.Message;
}
}
You can provide recipients with names in the standard email format
Fred Bloggs <fred.bloggs#exmaple.com>
If you specify your ToAddresses as a list of strings of that format, the name will be set properly.
This conforms to the Internet Message Format (rfc5322) spec. See section 3.4.

cannot send emails with Amazon SES .NET SDK

I can send emails with SMTP option in .Net but I need to use .NET SDK to send emails via Amazon. It gives me error that says "Email address is not verified", event though I am sure that it is verified. By the way, I am using a Test Account(SandBox).
What am I doing wrong? or am I missing anything?
here is my code,
var sesClient = new AmazonSimpleEmailServiceClient("AKIAJHXXXXXXXXXXX", "RVGdbCKXILwjUIKSexKlwXXXXXXXXXXXX",Amazon.RegionEndpoint.USEast1);
var dest = new Destination
{
ToAddresses = new List<string>() { "tayfun.ural#aryxxx.com" },
CcAddresses = new List<string>() { "arif.yilmaz#aryxxx.com" }
};
var from = "tayfun.ural#aryxxx.com";
var subject = new Content("You're invited to the meeting");
var body = new Body(new Content("Please join us Monday at 7:00 PM."));
var msg = new Message(subject, body);
var request = new SendEmailRequest
{
Destination = dest,
Message = msg,
Source = from
};
var verify = sesClient.VerifyEmailAddress(new VerifyEmailAddressRequest { EmailAddress = "tayfun.ural#aryada.com" });
try
{
var response = sesClient.SendEmail(request);
}
catch (Exception ex)
{
throw ex;
}
When using Amazon SES in sandbox/test mode, all from/to/cc addresses must be verified email addresses. The error "Email address is not verified" means that atleast one of the email addresses is not verified. It could be the TO, FROM, CC, or BCC.
In your case, ensure that both "tayfun.ural#aryxxx.com" and "arif.yilmaz#aryxxx.com" are verified and/or that "aryxxx.com" is a verified domain.
String FROM = "SENDER#EXAMPLE.COM"; // Replace with your "From" address. This address must be verified.
String TO = "RECIPIENT#EXAMPLE.COM"; // Replace with a "To" address. If you have not yet requested
// production access, this address must be verified.
String SUBJECT = "Amazon SES test (AWS SDK for .NET)";
String BODY = "This email was sent through Amazon SES by using the AWS SDK for .NET.";
// Construct an object to contain the recipient address.
Destination destination = new Destination();
destination.ToAddresses = (new List<string>() { TO });
// Create the subject and body of the message.
Content subject = new Content(SUBJECT);
Content textBody = new Content(BODY);
Body body = new Body(textBody);
// Create a message with the specified subject and body.
Message message = new Message(subject, body);
// Assemble the email.
SendEmailRequest request = new SendEmailRequest(FROM, destination, message);
// Choose the AWS region of the Amazon SES endpoint you want to connect to. Note that your production
// access status, sending limits, and Amazon SES identity-related settings are specific to a given
// AWS region, so be sure to select an AWS region in which you set up Amazon SES. Here, we are using
// the US East (N. Virginia) region. Examples of other regions that Amazon SES supports are USWest2
// and EUWest1. For a complete list, see http://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html
Amazon.RegionEndpoint REGION = Amazon.RegionEndpoint.USEast1;
// Instantiate an Amazon SES client, which will make the service call.
AmazonSimpleEmailServiceClient client = new AmazonSimpleEmailServiceClient(REGION);
// Send the email.
try
{
//("Attempting to send an email through Amazon SES by using the AWS SDK for .NET...");
client.SendEmail(request);
//("Email sent!");
}
catch (Exception ex)
{
//("The email was not sent.");
//("Error message: " + ex.Message);
}

Categories

Resources