C# asp.net mail.body text - c#

Situation:
1)I want to send a email with body text, like below.
Problem:
1)I have different variables that need to insert into the mail.body. But it can only show the first variable "name".
2)How can I leave the space or shift between lines in mail.body text?
mail.Body = string.Format("Thank you for online maintanence {0}. Your details is as following: Model:{0} colour:{0}Storage:{0}type of maintanence:Also , Your choose {0} for your phone retake location Any queries , Please contact 16681668 to our office! ", name ,clientid,model,colour,storage,type,Location,contactno);

Because you say so. You always used {0} for every variable that's why it always shows the first one.
Increase your {0} index every time by 1. Like;
mail.Body = string.Format("Thank you for online maintanence {0}. Your details is as following: Model:{1} colour:{2} Storage:{3} type of maintanence: Also, Your choose {4} for your phone retake location Any queries , Please contact 16681668 to our office! ",
name ,clientid,model,colour,storage,type,Location,contactno);
In such a case, your type,Location,contactno variables will be unnecessary since you didn't define them any {} in your string.

I would take a different approach if I were you. Generating formatted emails from code like that is just ugly. And using String.Format() to insert your values into your template? Ugh, that's a mess if you ever need to change the order or add new items!
There is a tool called Postal that allows you to use the Razor layout syntax to generate emails. This promotes separation of concerns, your logic for sending the email is no longer coupled to the logic that determines the layout for the email body. It's easier to write, because you won't need to write HTML inside a string inside C#. I'll show you how to do it with a strongly typed model.
public class MailInfo : Email
{
public string Name {get; set;}
public string ClientId {get; set;}
public string Model {get; set;}
public string Colour {get; set;}
public string Storage {get; set;}
public string Type {get; set;}
public string Location {get; set;}
public string ContactNo {get; set;}
}
The MailInfo will hold all the data we want to use to generate the email. We would create an instance of the class and populate it.
var email = new MailInfo();
email.Name = "Bob";
email.ClientId = "A57C";
//set rest of properties
Then we create the Razor layout (.cshtml) file, and the layout file is going to declare that it needs an instance of our MailInfo class on the first line. Sine we did that, we can embed properties from MailInfo class into your email by using the #Model.PropertyName syntax.
#model MailInfo
<p>Thank you for online maintanence #Model.Name. Your details are as follows:</p>
<ul>
<li>Model: #Model.Model</li>
<li>Colour: #Model.Colour</li>
<li>Storage: #Model.Storage</li>
<li>Type: #Model.Type</li>
</ul>
<p>Also, you choose #Model.Location for your phone retake location. Any questions, please contact our office at 16681668!</p>
All that's left is to create the MailMessage, passing the instance of MailInfo that we created above, and send it.
MailMessage mail = new EmailService().CreateMailMessage(email);
//send mail like you would any other MailMessage, populating To, From, Subject etc.
(I did simplify the code slightly, not showing using declarations, where to put the .cshtml file, or how to install Postal via NuGet. Let me know if you want me to flesh the answer out more.)

What you can do is using '#' character before the string in order to split the text on multiple lines.
string mailTemplate = #"Thank you for online maintanence {0}. <br />
Your details is as following: <br />
Model:{0} <br />
colour:{0} <br />
Storage:{0} <br />
type of maintanence: <br />
Also , Your choose {0} for your phone retake location Any queries ,
Please contact 16681668 to our office! ";
mail.Body = string.Format(
mailTemplate,
name,
clientid,
model,
colour,
storage,
type,
Location,
contactno);
make sure that you set the IsBodyHtml property to true.
mail.IsBodyHtml = true;

You can also use this approach:
mail.IsBodyHtml = true;
mail.Body += "This is some text";
mail.Body += "<br />";
mail.Body += "This a variable: " + variableName;
<br /> would insert the line break.

Related

Sendgrid - How do I access the "to" email address object to personalize dynamic template in v3 api C#

We are using Sendgrid C# library created a stored dynamic template. It is working fine except we cannot figure out how to access the "to" object to display the user's name dynamically in the template. Here is the JSON being sent:
{
"from":{
"email":"fromemail#mydomain.com"
},
"personalizations":[
{
"to":[
{
"name":"test name",
"email":"test#testingmail.com"
}
],
"dynamic_template_data":{
"MailBody":"this is a \u003cstrong\u003eTEST!\u003c/strong\u003e",
"MailSalutation":"Best Regards,",
"MailGreeting":"Dear"
}
},{
"to":[
{
"name":"another name",
"email":"anothertest#testingmail.com"
}
],
"dynamic_template_data":{
"MailBody":"this is a \u003cstrong\u003eTEST!\u003c/strong\u003e",
"MailSalutation":"Best Regards,",
"MailGreeting":"Dear"
}
}
],
"template_id":"xxxxxxxxxx-ede3cd3f9b"
}
The template looks something like this:
<p> {{MailGreeting}} {{to.name}} or {{to[0].name}}???,</p>
<p>
{{{MailBody}}}
</p>
<p>
{{MailSalutation}}
</p>
The name property of the "to" object is what we want to display here {{to.name}}
We are using the recommended method from the sample code with our data being fed in.
Our class object:
public class EmailMergeSendDetails
{
public List<EmailAddress> MailToList { get; set; }
public string MailFrom { get; set; }
public string MailFromName { get; set; }
public string MailSubject { get; set; }
public string MailBody { get; set; }
}
Using Sendgrid C# to send
var from = new EmailAddress(d.MailFrom, d.MailFromName);
var tos = d.MailToList;
var dynamicTemplateData = new EmailMergeSendDetails
{
Subject = d.MailSubject,
MailSalutation = d.MailSalutation,
MailGreeting = d.MailGreeting,
MailBody = d.MailBody,
};
var msg = MailHelper.CreateSingleTemplateEmailToMultipleRecipients(from,
tos,
"d-xxxx-template-id-here",
dynamicTemplateData
);
var response = await client.SendEmailAsync(msg);
Why isn't this working for the {{to.name}}? I'm guessing that the only data available for the {{}} is the dynamic_template_data? If so, how do we display the to.name. It feels like such a basic thing to be able to do but we've literally spend hours on it :).
For the sake of clarity, we have a template for a newsletter which stores dynamic template data in our database. We want to query that data along with multiple name/email addresses to send it to (25k+ of them), fill in the template with the newsletter data and send it to each one of the recipients adding a "Dear _____" at the top. Seems super basic. How can we do this using the dynamic templates if CreateSingleTemplateEmailToMultipleRecipients is not the correct approach?
I don't think you can. You can add additional values to your dynamic_template_data though; e.g. "RecipientName", which you would then set to "test name", and then reference it in your template as {{RecipientName}}.
Or... the way you have done it, you could just add it to the end of MailGreeting; e.g. give it a value of "Dear test name" instead of just "Dear".
Edit (multiple emails):
From looking at the package code, I think CreateMultipleTemplateEmailsToMultipleRecipients() is what you want instead, and adding a different RecipientName (or similar) to each dynamicTemplateData, and ensuring you have the same number of items in tos as dynamicTemplateData.
SendGrid has a limit of 1000 personalizations per email, so you'd need to break up your 25k into batches.

How to add break line in string.Format

I was trying to add a break line in string.Format. However it didn't work no matter I added \r\n or Environment.NewLine. Can anyone advise what is the proper way to add a break line into the statement? Thanks.
public async Task<IViewComponentResult> InvokeAsync()
{
var claimsIdentity = (ClaimsIdentity) User.Identity;
var claim = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
var userFromDb = await _db.ApplicationUser.FirstOrDefaultAsync(u => u.Id == claim.Value);
var role = await _userManager.GetRolesAsync(userFromDb);
string r = string.Format("{0} \r\n ({1})", userFromDb.Name, role[0]);
return View("Default",r);
}
Your controller (or view component) shouldn’t actually be responsible for deciding how something is displayed. Whether you need for example a line break, a <br /> tag, or separate <p> tags is the responsibility of the view. So you should not attempt to solve this in the controller but instead pass the view just everything necessary to take care of the visual representation itself.
You can do that by create a custom view model that contains the values you need to pass the view. You then create this view model and set its properties and pass on the object to the view:
public async Task<IViewComponentResult> InvokeAsync()
{
var claimsIdentity = (ClaimsIdentity) User.Identity;
var claim = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
var userFromDb = await _db.ApplicationUser.FirstOrDefaultAsync(u => u.Id == claim.Value);
var role = await _userManager.GetRolesAsync(userFromDb);
// pass a complex object with separate properties to the view instead
return View("Default", new MyViewComponentModel
{
Name = userFromDb.Name,
Role = role[0],
});
}
public class MyViewComponentModel
{
public string Name { get; set; }
public string Role { get; set; }
}
Then, in the view, specify this MyViewComponentModel as the view model type and access the properties to render the values properly:
#model MyViewComponentModel
<div>
<strong>#Model.Name</strong><br />
#Model.Role
</div>
This approach has another huge benefit over creating the HTML code in the controller code: If you were to pass HTML to the view, then the view would have to render that text as raw HTML. This means that the code is taken as it is and no HTML encoding happens with the content. This may work with save values that are coming from your database but can get dangerous very quickly as soon as there is some user-defined content in there. Then, you are basically allowing malicious users to decide what kind of HTML gets rendered on your website which is a very common security issue. So it’s best to avoid that and have as little raw HTML in your views as absolutely necessary.
You are adding the line-break and sending the string to an HTML view. HTML is white space agnostic. Line-breaks are white space. Therefore the line-break has zero effect on the displayed string.
To place a line-break in HTML use the <br> tag. Or, better still send the string as two strings and let the view decide how it is displayed.
\r\n this work in C# code
string Name = "Alex";
var role = "manager";
string newString = string.Format("{0} \r\n ({1})", Name, role);
Console.WriteLine(newString);
however if you want to return view so it must be html break line <br />
public static class BreakLine
{
public const string LineBreak = #"<br />";
}
string htmlString = string.Format(#"{0} {1} ({2})", Name, BreakLine.LineBreak, role);
Console.WriteLine(htmlString);

How to clean parse HTML code to string

I need to parse html code into string, because i'm later using it as my body content of email message:
Is there a way to parse html code like this:
<div class="alert alert-success" role="alert">
<h4 class="alert-heading">Well done!</h4>
<p>You have successfully subscribed!</p>
<hr>
<p class="mb-0">We will be sending you newsletter on weekly basis.</p>
</div>
into string in a clean way, without doing it like this:
string body = #"<div class=""alert alert-success"" role=""alert"">" + "</div>"
so i could pass it to mail like this:
MailMessage mailMessage = new MailMessage();
mailMessage.Body = body;
instead of having a whole series of html code inside string there.
Is there maybe any other "way" to make "design" for email messages?
PS: i also do not want to load html from external file
I would like to use html code to have a decent design for subscribing to newsletter message on email.
Thank you!
/*
If they are static and don't need to be read from a file, as you've indicated, I would create a project->property->resource string for each message. You can paste the email body into a string variable and then just access it like this:
*/
string body = MyNamespace.Properties.Resources.emailBody1;
/* the string will be formatted with all the quotes and \r\n just as it was from what you pasted in. */
// you could even add some substitution to customize the email
body.Replace("{EmailRecipient}", strEmailRecipient);
Since you are using C#, you can use String interpolation. http://www.informit.com/articles/article.aspx?p=2422807
You can create a template object were you can pass all the necessary variables for your message.
e.g
class WelcomeEmail {
public WelcomeEmail(String message, String title) {
}
public override string ToString() {
}
}

Proper way to change DisplayName of Email in MVCMailer

I looking to change the display name in a Email using MVCMailer. Instead of the client seeing From: custmerservice#xyzCompany.com they will see "xyzCompany Customer Service".
I have looked all around the internet and can not find any documentation that explains how.
USERMAILER.CS
public virtual MvcMailMessage Welcome(string sentTo, string replyTo)
{
return Populate(x =>
{
x.Subject = "Welcome";
x.ViewName = "Welcome"; //View name of email going out.
x.ReplyToList.Clear();
x.ReplyToList.Add(replyTo);
x.To.Add(sentTo);
x.From.DisplayName("xyz Company Customer Service");
x.From = new MailAddress("customerservice#xyzCompany.com");
x.ViewName = "WelcomeEmail"; //View name of email going out.
});
}
The line 'x.From.DisplayName("xyz Company Customer Service")' gives me an error: system.net.mail.mailaddress.DisplayName can not be used as a method.
Can anyone please tell me how to properly change the displayname?
DisplayName is a property of the MailAddress class. You can use this overload of the constructor to specify it:
x.From = new MailAddress(address: "customerservice#xyzCompany.com", displayName: "xyz Company Customer Service");
Update based on comment:
The DisplayName property has no (or a private) setter, meaning you can only set it through the constructor of MailAddress, but not through the property itself.

RegularExpression validation not working on model

I have the following code:
public class Register
{
[RegularExpression(#"^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$", ErrorMessage = "eMail is not in proper format")]
[Required(ErrorMessageResourceName="Name Required"), ErrorMessageResourceType = typeof(ErrorMessages))]
public string Email{ get; set; }
}
Email that i tried: asd#asd.com is valid but it fail the validation.
The required is working, but the regular expression is failing. Even if I enter a valid email address, it will still say that email is not in proper format.
Anything I missed here? Thanks in advance!
EDIT
This regex validator is working on my other mvc application by using Resources.resx. So I think what is wrong here is how I declared it on my model class.
Regex regx = new Regex(#"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
+ #"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
+ #"#[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$");
/* declare in public and validate for your mail text box */
This is solved. I accidentally put the wrong regex on my code:
"^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$
instead of:
#"^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$
Now I will focus on to make the best email regex. Thanks!

Categories