Sending email via AWS Lambda with SES into C# - c#

I have created one AWS Lambda function using Visual Studio and C# with .net core1.0
I have to send an email after doing some operation on my Lambda function.
My code is as below. taken from AWS Doc
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Lambda.Core;
using System;
using System.Collections.Generic;
using Amazon.SimpleEmail;
using Amazon.SimpleEmail.Model;
using Amazon;
namespace MyProject
{
public class AddAlarms
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
public string AddAlarmsHandler(GetUserAlerts input, ILambdaContext context)
{
var client = new AmazonSimpleEmailServiceClient(RegionEndpoint.USEast1);
List<string> toAddress = new List<string>();
toAddress.Add("ToEmail#domain.com");
var sendRequest = new SendEmailRequest
{
Source = "sourceEmail#domain.com",
Destination = new Destination
{
ToAddresses = toAddress
},
Message = new Message
{
Subject = new Content("Subject of email"),
Body = new Body
{
Html = new Content
{
Charset = "UTF-8",
Data = "Hello Email, HTML Body"
},
Text = new Content
{
Charset = "UTF-8",
Data = "Hello email, Text Body"
}
}
},
ConfigurationSetName = "ConfigSet"
};
string returnval = string.Empty;
try
{
Console.WriteLine("Sending email using Amazon SES...");
returnval += "Sending email using Amazon SES...";
var response = client.SendEmailAsync(sendRequest);
System.Threading.Thread.Sleep(5000);
returnval += ", Response Status - " + response.Status.ToString() + " - ";
Console.WriteLine("The email was sent successfully.");
returnval += "The email was sent successfully.....";
}
catch (Exception ex)
{
returnval += "The email was not sent.";
Console.WriteLine("The email was not sent.");
returnval += "Error message: " + ex.Message;
Console.WriteLine("Error message: " + ex.Message);
}
return returnval;
}
}
}
so Lambda function created successfully and it shows in section of Lambda into AWS
so while testing this function i get response that after sending - "Faulted"
and email not received by receiver.
I have verified both email TO and FROM into email verification of AWS SES.
I get one Node.Js code which runs successfully and also receiving email and node.js code i have taken from link
I have checked ROLE and using same role for Node.Js code and works fine, but for C# lambda function i am getting response "Faulted".
Please help to solve this problem in AWS Lambda

Related

How to send existing email from shared mailbox to other email address using graph API c#

How to send existing email from inbox to other email address using graph API c#
I have tried sending the existing email but Im not able to send it.
It is throwing error -Code: generalException Message: Unexpected exception returned from the service.
Below is the code snippet:
internal static async Task<System.Collections.Generic.IEnumerable<Message>> Sendemail(List<MM_Mailbox_Forward> toAddress, string smptpadd)
{
string from ="xyz#gmail.com"``your text``
var Toptenmessages1 = graphClient.Users["xyz#gmail.com"].MailFolders["Inbox"].Messages.Request().Top(1);
var task = System.Threading.Tasks.Task.Run(async () => await Toptenmessages1.GetAsync());
var authResult2 = task.Result;
foreach (var message in authResult2)
{
try
{
var messages = new Message
{
Subject = message.Subject,
Body = message.Body,
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "abc#gmail.com"
}
}
},
};
await graphClient
.Users[from]
.SendMail(messages, true)
.Request()
.PostAsync();
}
}
catch (Exception ex)
{
Console.WriteLine("error:" + ex);
}
Make sure you are not using a shared email box, you can't (by default) send email with a shared email box.

Sending email with OAUTH2 and smtp.gmail (C#)

I need to send a simple email, but using authentication. Using AppPasswords is not an option.
My difficulty is to retrieve the response after sending the authorization and at what point should I generate the email. I know that to send the email I must use the password and authentication user identity.
Here's what I've done.
Credentials are read from a file
ClientSecrets varClientSecrets = new ClientSecrets();
UserCredential credential;
using (var stream =
new FileStream(pathFile, FileMode.Open, FileAccess.Read,FileShare.Read))
{
varClientSecrets = GoogleClientSecrets.FromStream(stream).Secrets;
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
varClientSecrets,
new[] { "email", "profile", "https://mail.google.com/" },
"use",
CancellationToken.None,
new FileDataStore(credPath, true)
).Result;
strCLIENT_ID = varClientSecrets.ClientId;
strCLIENT_SECRET = varClientSecrets.ClientSecret;
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "XXX"
});
Get credential data
// Define parameters of request.
UsersResource.LabelsResource.ListRequest request = service.Users.Labels.List("me");
ConsultaWeb CW = new ConsultaWeb();
IRestResponse irrRetornoServidor = null;
strSCOPE = credential.Token.Scope;
strREDIRECT_URI = "https://accounts.google.com/o/oauth2/v2/auth";
strTokenURL = "https://www.googleapis.com/oauth2/v4/token";
/// model: {Authorization: token_type base64(userEmail:userPassword)}
strHeader = "Authorization: " + credential.Token.TokenType + " "
+ Base64.EncodeToBase64(userEmail + ":" + userPassword);
strURL = "https://accounts.google.com/o/oauth2/v2/auth"
+ "?scope=" + strSCOPE
+ "&access_type=offline"
+ "&include_granted_scopes=true"
+ "&response_type=code"
+ "&state=state_parameter_passthrough_value"
+ "&redirect_uri=" + strREDIRECT_URI
+ "&client_id=" + strCLIENT_ID;
strServidorRetorno = CW.RequisicaoWebREST(strURL, GET, JSON
, out irrRetornoServidor, "", "", "", "", strHeader);
// Return from OAuth 2.0 server
// OAuth 2.0 server responds to your application's access request
// using the URL specified in the request.
////If the user approves the access request, the response
//will contain an authorization code. If the user does not approve the request,
//the response will contain an error message.
//The authorization code or error message that is returned to the web server
//appears on the query string, as shown below:
strAuthCode = "";
Get response from server
if ((short)irrRetornoServidor.StatusCode == (short)RegrasGlobais.HTTPStatusCode.OK)
{
if (irrRetornoServidor.ResponseUri.AbsolutePath.Contains("error"))
{
// An error response:
// https://oauth2.example.com/auth?error=access_denied
return -1;
}
else if (irrRetornoServidor.ResponseUri.AbsolutePath.Contains("ServiceLogin"))
{
//An authorization code response
// https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
// strAuthCode = "P7q7W91a-oMsCeLvIaQm6bTrgtp7";
// how to get the autorization response, if this open in the browser
strAuthCode = irrRetornoServidor.ResponseUri.Query.ToString();
}
}
else
{
return -1;
}
send the email
// Gmail API server address
//MailMessage msg = new MailMessage();
// build mail
thks
my problem was and how to do the authentication before sending the email. Now I got it. Thanks.
Im a little confused as to what it is you are trying to do. You say you want to send an email using the SMTP server yet you are connecting to the gmail api. Why not just send your emails via the gmail api then?
Assuming you have just gone in the wrong direction. You should know that the SmtpClient can handle the client from the google .Net client library directly. Just let it get its access token when needed.
await client.AuthenticateAsync (oauth2, CancellationToken.None);
If all you want to do is send an email from the smtp server. Try the following sample.
Full sample
using Google.Apis.Auth.OAuth2;
using Google.Apis.Util.Store;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
var to = "test#Gmail.com";
var from = "test#gmail.com";
var path = #"C:\YouTube\dev\credentials.json";
var scopes = new[] { "https://mail.google.com/" };
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromFile(path).Secrets,
scopes,
"GmalSmtpUser",
CancellationToken.None,
new FileDataStore(Directory.GetCurrentDirectory(), true)).Result;
var message = new EmailMessage()
{
From = from,
To = to,
MessageText = "This is a test message using https://developers.google.com/gmail/imap/xoauth2-protocol",
Subject = "Testing GmailSMTP with XOauth2"
};
try
{
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 465, true);
var oauth2 = new SaslMechanismOAuth2 (message.From, credential.Token.AccessToken);
await client.AuthenticateAsync (oauth2, CancellationToken.None);
client.Send(message.GetMessage());
client.Disconnect(true);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
public class EmailMessage
{
public string To { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string MessageText { get; set; }
public MimeMessage GetMessage()
{
var body = MessageText;
var message = new MimeMessage();
message.From.Add(new MailboxAddress("From a user", From));
message.To.Add(new MailboxAddress("To a user", To));
message.Subject = Subject;
message.Body = new TextPart("plain") { Text = body };
return message;
}
}

using async/await send email and delete the resource checking condition

I want to send email using c# async/await and the program deletes the attached file from computer depending on the flag "deleteFile". Whatever the value of deleteFile flag the email is delivered successfully but when I set deleteFile to true I am getting the following exception. I have to send two separate emails and I need to delete the file only after second mail.
An unhandled exception of type 'System.IO.IOException' occurred in
mscorlib.dll
Additional information: The process cannot access the file
'C:\Uploads\TestFile.txt' because it is being used by another process.
Could you please help me to resolve the issue?
My console application code is:
using System;
namespace SendMailAsyncDemo
{
class Program
{
private static string filePath = #"C:\Uploads\";
static void Main(string[] args)
{
Sender mailSender = new Sender();
mailSender.SendEmail("myemail#gmail.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt", false);
mailSender.SendEmail("anotheremail#gmail.com.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt", true);
Console.WriteLine("Email sent successfully!!!");
Console.ReadLine();
}
}
}
I have a Sender class to send email:
using System;
using System.IO;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace SendMailAsyncDemo
{
public class Sender
{
public void SendEmail(string toEmail, string title, string body, string attachmentPath, bool deleteFile = false)
{
Task.Factory.StartNew(() =>
{
SendEmailAsync(toEmail, title, body, attachmentPath, deleteFile);
});
}
private async void SendEmailAsync(string toEmail, string title, string body, string attachmentPath, bool deleteFile)
{
Attachment attachment = null;
try
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
if (deleteFile)
{
smtpClient.SendCompleted += (s, e) =>
{
attachment.Dispose();
File.Delete(attachmentPath);
};
}
await smtpClient.SendMailAsync(mailMsg);
}
}
}
catch (Exception ex)
{
Console.WriteLine("SendEmail exception: " + ex);
}
finally
{
Console.WriteLine("SendEmail done");
}
}
}
}
As discussed in the comments, there's no simple way to fix this while maintaining this same program structure. In particular, since you've currently got two ongoing email send calls with no knowledge of each other, there's no way to determine when it's safe to perform the delete. The second Send could finish first.
Changes I would make - I'd delete SendEmail and make SendEmailAsync public and Task returning. I'd also remove the concept of deleting after:
public async Task SendEmailAsync(string toEmail, string title, string body, string attachmentPath)
{
try
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
Attachment attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
await smtpClient.SendMailAsync(mailMsg);
}
}
}
catch (Exception ex)
{
Console.WriteLine("SendEmail exception: " + ex);
}
finally
{
Console.WriteLine("SendEmail done");
}
}
I'd then change Main as follows:
static void Main(string[] args)
{
Sender mailSender = new Sender();
var send1 = mailSender.SendEmailAsync("myemail#gmail.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
var send2 = mailSender.SendEmailAsync("anotheremail#gmail.com.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
Task.WaitAll(send1,send2);
File.Delete(filePath + "TestFile.txt");
Console.WriteLine("Email sent successfully!!!");
Console.ReadLine();
}
If this wasn't Main/if you're using bleeding-edge C#, I'd make it async also and use a couple of awaits at the current point I've got the WaitAll. It's the earliest piece of code common to both sends and so the only piece of code that can actually determine when it's safe to perform the delete.

Send email using Html template with MailKit in .net core application

I am sending an email from .net core application using MailKit, and it will sent it successfully.
But I want to use HTML template to send email with MailKit in .Net core.
Here are the code currently sending email with static body part
var emailMessage = new MimeMessage();
if (!string.IsNullOrWhiteSpace(cc))
{
emailMessage.Cc.Add(new MailboxAddress(cc));
}
else if (!string.IsNullOrWhiteSpace(EmailUserNameCC))
{
emailMessage.Cc.Add(new MailboxAddress(EmailUserNameCC));
}
if (!string.IsNullOrWhiteSpace(EmailUserNameBCC))
{
emailMessage.Bcc.Add(new MailboxAddress(EmailUserNameBCC));
}
emailMessage.From.Add(new MailboxAddress(mailFrom));
emailMessage.To.Add(new MailboxAddress(mailTo));
emailMessage.Subject = subject;
if (!string.IsNullOrWhiteSpace(replyTo))
{
emailMessage.InReplyTo = replyTo;
}
var builder = new BodyBuilder();// { TextBody = message };
builder.HtmlBody = message;
if (attachments != null && attachments.Count > 0)
{
foreach (var item in attachments)
{
builder.Attachments.Add(item.Key, item.Value);
}
builder.HtmlBody = builder.HtmlBody + " \n" + " PFA";
}
var multipart = new Multipart("mixed");
multipart.Add(new TextPart("html") { Text = message });
emailMessage.Body = builder.ToMessageBody();
using (var client = new SmtpClient())
{
var credentials = new NetworkCredential
{
UserName = EmailUserName,
Password = EmailPassword
};
if (!client.IsConnected)
{
client.Connect(SmtpHost, Convert.ToInt32(EmailHostPort));
client.Authenticate(EmailUserName, EmailPassword);
}
client.MessageSent += c_EmailReached;
client.Send(emailMessage);
}
Now, I want to use HTML template to replace body part.
So how can I use HTML Template with MailKit in .Net Core ?
Additional:
-> Also the special characters are not showing in actual email after sending email with html template. For some special characters it is displaying � . So how can I resolved this, to show special characters also.
Thanks.
You can use StreamReader to read the source file and assign it to your builder.HtmlBody.
using (StreamReader SourceReader = System.IO.File.OpenText(path to your file))
{
builder.HtmlBody = SourceReader.ReadToEnd();
}

SendGrid email using MailHelper

I am using SendGrid mailhelper (as part of C# SDK) to send email. I need to send to multiple users, and hence I am using Personalization.
I get an error : Bad Request
This is my code:
static async Task Execute(string sub, string body, List<Recipient> recipients)
{
string apiKey = Environment.GetEnvironmentVariable("SendGrid_ApiKey", EnvironmentVariableTarget.User);
dynamic sg = new SendGridAPIClient(apiKey);
SendGrid.Helpers.Mail.Email from = new SendGrid.Helpers.Mail.Email("test1#gmail.com");
string subject = sub;
Personalization personalization = new Personalization();
SendGrid.Helpers.Mail.Email emails = new SendGrid.Helpers.Mail.Email();
var i = 0;
foreach (var recp in recipients)
{
emails.Address = recp.Email;
emails.Name = recp.FirstName + " " + recp.LastName;
personalization.AddTo(emails);
i++;
}
SendGrid.Helpers.Mail.Email to = new SendGrid.Helpers.Mail.Email("test1#gmail.com");
Content content = new Content("text/plain", body);
Mail mail = new Mail(from, subject, to, content);
mail.AddPersonalization(personalization);
dynamic response = await sg.client.mail.send.post(requestBody: mail.Get());
}
I appreciate if someone could advise me what am I doing incorrect.
Sendgrid API responds with bad request when there are more than 1 email address that is the same in the Personalization object. Make sure all the emails are unique

Categories

Resources