I am working on sending out order confirmations on a web site with a shop functionality - all pretty much custom designed. I would like an email to be sent out once the order has been placed, ideally with a brief summary/overview of the ordered items.
I have managed to get to the point where the submission of the order triggers an email to be sent to the user, so that is all good. However, my question is how can I customize the email body in a way so it would include the list of ordered items?
Happy to add code from my controller, although I don't really think this is adding much value as this is more of a how-to-question rather than an issue I am encountering.
int orderID = order.ID;
var lineItems = DATADB.LineItemList.Where(x => x.OrderNumber == 0 && x.UserID == userID);
lineItems.ForEach(l => l.OrderNumber = orderID);
DATADB.SaveChanges();
// send order confirmation email
var orderConfirmation = DATADB.LineItemList.Where(x => x.OrderNumber == orderID).ToList();
var ordered = string.Join(",", lineItems);
var msg = new SendGridMessage();
msg.From = new System.Net.Mail.MailAddress("orders#freshNclean.ch", "freshNclean");
msg.AddTo(UserManager.FindById(userID).Email);
msg.Subject = "Deine Bestellung bei freshNclean";
msg.Text = "Hi " + UserManager.FindById(userID).FirstName.ToString() + "! Vielen Dank für Deine Bestellung." + ordered;
// SendGrid credentials
var credentials = new NetworkCredential(ConfigurationManager.AppSettings["SGaccount"], ConfigurationManager.AppSettings["SGpassword"]);
var transportWeb = new Web(credentials);
if (transportWeb != null)
{
transportWeb.DeliverAsync(msg);
}
else
{
Trace.TraceError("Web Transport konnte nicht generiert werden - die Nachricht wurde nicht versandt.");
Task.FromResult(0);
}
Step 1: Get the data in form of objects (if possible in XML format).
Step 2: Create XSLT template to convert this XML format into HTML
Reference: Simplest way to transform XML to HTML with XSLT in C#?
public static string TransformXMLToHTML(string inputXml, string xsltString)
{
XslCompiledTransform transform = new XslCompiledTransform();
using(XmlReader reader = XmlReader.Create(new StringReader(xsltString))) {
transform.Load(reader);
}
StringWriter results = new StringWriter();
using(XmlReader reader = XmlReader.Create(new StringReader(inputXml))) {
transform.Transform(reader, null, results);
}
return results.ToString();
}
STEP 3: Set HTML contents to output of previous method:
var apiKey = some-api-key;
var client = new SendGridClient(apiKey);
var from = new EmailAddress("test#example.com", "Example User");
var subject = "Sending with SendGrid is Fun";
var to = new EmailAddress("test#example.com", "Example User");
var plainTextContent = "and easy to do anywhere, even with C#";
var htmlContent = GetHTMLFromXML();
var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg);
Hope this helps.
Related
I am trying to send the same automatic email to multiple email addresses but I can't get it to work.
[HttpGet("largeorderemail")]
public IActionResult LargeOrderEmail()
{
try
{
//var bodyString = $"<h3>{msg}</h3><br/><p> Visit the site <a href='{Startup.appSettings.AllowOrigin}/lidarweb'> LiDAR GIS portal.</a></p>";
var bodyString = $"<h3>email body</h3>" +
<br/>" +
var emailService = new Email { To = "info#tel.net" };
var response = emailService.ExecuteLargeOrder(bodyString);
return Ok();
}
catch (Exception e)
{
Log.Error(e);
return NotFound();
}
}
public async Task<Response> ExecuteLargeOrder(string bodyString)
{
var fromAddr = new EmailAddress(from, "Info");
subject = "large order";
var toAddr = new EmailAddress(to, "User");
plainTextContent = "";
htmlContent = bodyString;
var msg = MailHelper.CreateSingleEmail(fromAddr, toAddr, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg);
return response;
}
When I send an email to a single address, it works. Like so: var emailService = new Email { To = "info#tel.net" };
but when I try something like this, it doesn't send the email var emailService = new Email { To = "info#tel.net, info#gmail.com" };
I also tried separating the address like so var emailService = new Email { To = "info#tel.net; info#gmail.com" }; but this also doesn't work.
Any suggestions?
Instead of putting Email addresses, try doing this way. Keep all your Email address in Array and try looping through the Array so that you can achieve your goal.
I am using SendGrid, and I want to add one or more category to the email, but the added category hadn't been sent!
This is the code:
internal class Example
{
private static void Main()
{
Execute().Wait();
}
static async Task Execute()
{
//FYI, the following three variables are not real
var apiKey = "SG.XXX";
var fromEmail = "";
var toEmail = "";
var client = new SendGridClient(apiKey);
var from = new EmailAddress(fromEmail);
var subject = "Sending with SendGrid is Fun";
var to = new EmailAddress(toEmail);
var plainTextContent = "and easy to do anywhere, even with C#";
var htmlContent = "<strong>and easy to do anywhere, even with C#</strong>";
var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
msg.AddHeader("category", "cat1"); //This line does nothing!
var response = await client.SendEmailAsync(msg);
}
}
Thanks Kami, I tried your answer and it worked properly.
I replaced this line msg.AddHeader("category", "cat1"); with msg.AddCategory("cat1");
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();
}
Situation: When a user registers for a bot (by entering a message to the bot, I store the information of that user in a database:
- UserId
- UserName,
- ServiceURL
At some point in time I want to have my bot broadcast a message to all the users in that table.
foreach (var bUsers in users)
{
MicrosoftAppCredentials.TrustServiceUrl(bUsers.ServiceUrl);
MicrosoftAppCredentials creds = new MicrosoftAppCredentials("<<appid>>", "<<secret>>");
var connector = new ConnectorClient(new Uri(bUsers.ServiceUrl), creds);
var conversationId = await connector.Conversations.CreateDirectConversationAsync(new ChannelAccount(), new ChannelAccount(bUsers.UserId, bUsers.UserName));
message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(id: conversationId.Id);
message.Text = "Hello from " + context.Activity.From.Name;
message.Locale = "en-Us";
var reply = await connector.Conversations.SendToConversationAsync((Activity) message);
}
With this code, I get a message saying:
Invalid conversation ID in teamsChannelId
I don't understand this message, and is it even possible to do what I want?
I was doing almost the same thing as you do but it stopped working suddenly. I could see the same error message.
But in my case it was just wrong and maybe it's strange it worked in the first place. Because I used client.UserId which was set to activity.Conversation.Id. If I changed the code to use it as conversationId it works.
Here is my code which is working right now and old pieces are commented out:
public static async Task SendMessageToClient(ServerClient client, string messageText)
{
var connector = new ConnectorClient(new Uri(client.BotServiceUrl), new MicrosoftAppCredentials());
var userAccount = new ChannelAccount(name: client.UserName, id: client.UserId);
var botAccount = new ChannelAccount(name: client.BotName, id: client.BotId);
// this worked before but not anymore
//var conversationId = await connector.Conversations
// .CreateDirectConversationAsync(botAccount, userAccount).Id;
// because client.UserId was set in a MessageController to activity.Conversation.Id we can use this
var conversationId = client.UserId;
var message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(false, conversationId);
message.Locale = "en-Us";
if (client.ReplaceFrom != null && client.ReplaceTo != null)
{
messageText = messageText.Replace(client.ReplaceFrom, client.ReplaceTo);
}
message.Text = messageText;
await connector.Conversations.SendToConversationAsync((Activity) message);
}
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