Extending the EmailSender to Include a Text View
In the previous article ASP.NET Core 2.2 - SMTP EmailSender Implementation the EmailSender was sending just html message emails. This article will demonstrate how to add a text view.
I will add a second SendEmailAsync method with parameters for text and html messages. A good explanation of why and how to verify the text view can be found in Plain text versions of html emails. If you followed the previous article, you have a page configured to test the email settings. I will use the same example to demonstrate the added function.
Edit EmailSender.cs, add a new SendEmailAsync method.
public async Task SendEmailAsync(string email, string subject, string textMessage, string htmlMessage)
{
try
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress(_emailSettings.SenderName, _emailSettings.Sender));
message.To.Add(new MailboxAddress(email));
message.Subject = subject;
var builder = new BodyBuilder
{
TextBody = textMessage,
HtmlBody = htmlMessage
};
// Now we just need to set the message body and we're done
message.Body = builder.ToMessageBody();
using (var client = new SmtpClient())
{
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
if (_env.IsDevelopment())
{
// The third parameter is useSSL (true if the client should make an SSL-wrapped
// connection to the server; otherwise, false).
await client.ConnectAsync(_emailSettings.MailServer, _emailSettings.MailPort, true);
}
else
{
await client.ConnectAsync(_emailSettings.MailServer);
}
// Note: only needed if the SMTP server requires authentication
await client.AuthenticateAsync(_emailSettings.Sender, _emailSettings.Password);
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
}
catch (Exception ex)
{
// TODO: handle exception
throw new InvalidOperationException(ex.Message);
}
}
Notice the new method uses the MimeKit.BodyBuilder class to add a TextBody and a HtmlBody.
Add the new method signature to IEmailSender.
public interface IEmailSender
{
Task SendEmailAsync(string email, string subject, string message);
Task SendEmailAsync(string email, string subject, string textMessage, string htmlMessage);
}
In the previous article ASP.NET Core 2.2 - SMTP EmailSender Implementation we setup a test from a razor page.
Add this label and form to Index.cshtml.
<div class="row">
<div class="col-6">
<label class="alert alert-success">@Model.EmailStatusMessage</label>
</div>
</div>
<div class="row">
<div class="col-6">
<form method="post">
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Email Test</button>
</form>
</div>
</div>
Edit Index.cshtml.cs.
public class IndexModel : PageModel
{
private readonly IEmailSender _emailSender;
public IndexModel(IEmailSender emailSender)
{
_emailSender = emailSender;
}
public string EmailStatusMessage { get; set; }
[Required]
[BindProperty]
public string Email { get; set; }
public void OnGet()
{
}
public async Task OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var email = Email;
var subject = "Email Test";
var message = "This is a test message.";
await _emailSender.SendEmailAsync(email, subject, message);
EmailStatusMessage = "Send test email was successful.";
return Page();
}
}
I will use this page to test the new method which also has a text formatted message.
Edit Index.cshtml.cs > OnPostAsync().
public async TaskOnPostAsync() { if (!ModelState.IsValid) { return Page(); } var email = Email; var subject = "New Email Test"; //var message = "This is a test message."; //await _emailSender.SendEmailAsync(email, subject, message); var textMessage = "This is the text message."; var htmlMessage = "This is the <strong>html</strong> message."; await _emailSender.SendEmailAsync(email, subject, textMessage, htmlMessage); EmailStatusMessage = "Send new test email was successful."; return Page(); }
If you search for SendEmailAsync you will find the default implementation in the Register.cshtml.cs and ForgotPassword.cshtml.cs pages in the Account folder and the Index.cshtml.cs page in the Account\Manage folder. I will add a text formatted message to each.
Edit Register.cshtml.cs > OnPostAsync().
Replace
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
With
var subject = "Confirm your email";
var htmlMessage = "Please confirm your account by " +
$"<a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.";
var textMessage = "Please confirm your account by coping and pasting this link: \r\n \r\n" +
$"{callbackUrl} \r\n \r\nto the address bar of your browser.";
await _emailSender.SendEmailAsync(Input.Email, subject, textMessage, htmlMessage);
Edit ForgotPassword.cshtml.cs > OnPostAsync().
Replace
await _emailSender.SendEmailAsync(
Input.Email,
"Reset Password",
$"Please reset your password by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
With
var subject = "Reset password";
var htmlMessage = "Please reset your password by " +
$"<a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.";
var textMessage = "Please reset your password by coping and pasting this link: \r\n \r\n" +
$"{callbackUrl} \r\n \r\nto the address bar of your browser.";
await _emailSender.SendEmailAsync(Input.Email, subject, textMessage, htmlMessage);
Edit Account\Manage\Index.cshtml.cs > OnPostAsync().
Replace
await _emailSender.SendEmailAsync(
email,
"Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
With
var subject = "Confirm your email";
var htmlMessage = "Please confirm your account by " +
$"<a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.";
var textMessage = "Please confirm your account by coping and pasting this link: \r\n \r\n" +
$"{callbackUrl} \r\n \r\nto the address bar of your browser.";
await _emailSender.SendEmailAsync(Input.Email, subject, textMessage, htmlMessage);
If you have implemented SendEmailAsync anywhere else in your project, you can update those following this pattern. This is a good practice for all new implementations.
Look for my next couple of articles where I will demonstrate how to add a html template and an admin notification email.
Comments(0)