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 TaskOnPostAsync() { 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)