SendGrid V3 api with C# not able to send mail - c#

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......";

Related

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;
}

How to send secure email through Send Grid?

I am sending Email with the help of SendGrid. Below is the code for that.
var client = new SendGridClient(apiKey);
EmailAddress from = new
EmailAddress("a.b#mycompany.com", "Ashutosh");
List<EmailAddress> tos = new List<EmailAddress>
{
new EmailAddress("a.b#mycompany.com",
"Ashutosh"),
};
StringBuilder emailBodyContent = new StringBuilder();
var textContent = "Hi, ";
emailBodyContent.AppendFormat("<p>Hi, </p>");
emailBodyContent.AppendFormat("<p>This is your email.</p>");
var emailSubject = "Attachment names are not unique";
msg = MailHelper.CreateSingleEmailToMultipleRecipients(from,
tos, emailSubject, textContent, emailBodyContent.ToString());
var response = await client.SendEmailAsync(msg);
Now I want to send Secure Email. I go through the below link
https://sendgrid.com/docs/Classroom/Basics/Email_Infrastructure/smtp_ports.html
But I have not understood how to set port 587 through code or enable secure email setting for send grid.
If you're using the SendGrid v3 API you need not worry about SMTP at all. You simply call a web API to send e-mail. All calls are HTTPS.
Check out the source code, note the https.
private void InitiateClient(string apiKey, string host, ...)
{
...
var baseAddress = host ?? "https://api.sendgrid.com";
...
I also found below url which says that by default SendGrid uses TLS.
https://sendgrid.com/blog/sendgrid-and-the-future-of-email-security/

Unable to send emails on Azure Web App using Sendgrid

I am unable to send emails on a MVC4 Web App that I configured on Azure. I am being able to send emails locally on my machine, but when I upload the code to my azure app in the cloud, the mail delivery doesn't say it fails, but emails are not delivered, SendGrid doesn't report that the mail was sent on its dashboard either.
Has someone ran into similar issues? Have looked into similar questions with no exact answer.
I did follow the instructions of this article (https://azure.microsoft.com/en-us/documentation/articles/sendgrid-dotnet-how-to-send-email/#reference) without success. Have tried also to the send the emails thru the SendGrid class libraries and by using plain System.Net.Mail.
Any help is appreciated.
Code:
Thanks for the reply. I am using Web.DeliverAsync, this is the code I am using:
// Create network credentials to access your SendGrid account
var username = System.Configuration.ConfigurationManager.AppSettings["smtpUser"];
var pswd = System.Configuration.ConfigurationManager.AppSettings["smtpPass"];
var credentials = new NetworkCredential(username, pswd);
// Create an Web transport for sending email.
SendGrid.Web transportWeb = new SendGrid.Web(credentials);
//var apiKey = System.Configuration.ConfigurationManager.AppSettings["sendgrid_api_key"];
var apiKey = "apikey";
SendGridMessage msg = new SendGridMessage();
msg.Subject = "...";
msg.AddTo(model.Email);
msg.Html = body;
msg.From = new MailAddress("...");
try
{
await transportWeb.DeliverAsync(msg);
}
catch (Exception e)
{
e.ToExceptionless().Submit();
ViewBag.ErrorMsg = e.Message;
return View("Error");
}
Try this:
var apiKey = System.Configuration.ConfigurationManager.AppSettings["sendgrid_api_key"];
// Create an Web transport for sending email.
SendGrid.Web transportWeb = new SendGrid.Web(apiKey);
SendGridMessage msg = new SendGridMessage();
msg.Subject = "...";
msg.AddTo(model.Email);
msg.Html = body;
msg.From = new MailAddress("...");
try
{
await transportWeb.DeliverAsync(msg);
}
catch (Exception e)
{
//e.ToExceptionless().Submit();
ViewBag.ErrorMsg = e.Message;
return View("Error");
}
Also what version of the SendGrid C# library are you using? Make sure it's version 6.3.x or later.

Unable to send email via Office 365 C# client library

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.

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