Email Sending

ABP Framework provides various services, settings and integrations for sending emails;

Installation

This package is already installed if you are using the application startup template.

It is suggested to use the ABP CLI to install this package. Open a command line window in the folder of the project (.csproj file) and type the following command:

  1. abp add-package Volo.Abp.Emailing

If you haven’t done it yet, you first need to install the ABP CLI. For other installation options, see the package description page.

Sending Emails

IEmailSender

Inject the IEmailSender into any service and use the SendAsync method to send emails.

Example

  1. using System.Threading.Tasks;
  2. using Volo.Abp.DependencyInjection;
  3. using Volo.Abp.Emailing;
  4. namespace MyProject
  5. {
  6. public class MyService : ITransientDependency
  7. {
  8. private readonly IEmailSender _emailSender;
  9. public MyService(IEmailSender emailSender)
  10. {
  11. _emailSender = emailSender;
  12. }
  13. public async Task DoItAsync()
  14. {
  15. await _emailSender.SendAsync(
  16. "[email protected]", // target email address
  17. "Email subject", // subject
  18. "This is email body..." // email body
  19. );
  20. }
  21. }
  22. }

SendAsync method has overloads to supply more parameters like;

  • from: You can set this as the first argument to set a sender email address. If not provided, the default sender address is used (see the email settings below).
  • isBodyHtml: Indicates whether the email body may contain HTML tags. Default: true.

IEmailSender is the suggested way to send emails, since it makes your code provider independent.

MailMessage

In addition to primitive parameters, you can pass a standard MailMessage object (see) to the SendAsync method to set more options, like adding attachments.

ISmtpEmailSender

Sending emails is implemented by the standard SmtpClient class (see) by default. The implementation class is the SmtpEmailSender. This class also expose the ISmtpEmailSender service (in addition to the IEmailSender).

Most of the time you want to directly use the IEmailSender to make your code provider independent. However, if you want to create an SmtpClient object with the same email settings, you can inject the ISmtpEmailSender and use its BuildClientAsync method to obtain a SmtpClient object and send the email yourself.

Queueing Emails / Background Jobs

IEmailSender has a QueueAsync method that can be used to add emails to the background job queue to send them in a background thread. In this way, you don’t take time of the user by waiting to send the email. QueueAsync method gets the same arguments with the SendAsync method.

Queueing emails tolerates errors since the background job system has re-try mechanism to overcome temporary network/server problems.

See the background jobs document for more about the background job system.

Email Settings

Email sending uses the setting system to define settings and get the values of these settings on the runtime. Volo.Abp.Emailing.EmailSettingNames defines constants for the setting names, just listed below:

  • Abp.Mailing.DefaultFromAddress: Used as the sender’s email address when you don’t specify a sender when sending emails (just like in the example above).
  • Abp.Mailing.DefaultFromDisplayName: Used as the sender’s display name when you don’t specify a sender when sending emails (just like in the example above).
  • Abp.Mailing.Smtp.Host: The IP/Domain of the SMTP server (default: 127.0.0.1).
  • Abp.Mailing.Smtp.Port: The Port of the SMTP server (default: 25).
  • Abp.Mailing.Smtp.UserName: Username, if the SMTP server requires authentication.
  • Abp.Mailing.Smtp.Password: Password, if the SMTP server requires authentication. **This value is encrypted **(see the section below).
  • Abp.Mailing.Smtp.Domain: Domain for the username, if the SMTP server requires authentication.
  • Abp.Mailing.Smtp.EnableSsl: A value that indicates if the SMTP server uses SSL or not (“true” or “false”. Default: “false”).
  • Abp.Mailing.Smtp.UseDefaultCredentials: If true, uses default credentials instead of the provided username and password (“true” or “false”. Default: “true”).

The easiest way to define these settings it to add them to the appsettings.json file. The application startup template already has these settings in the appsettings.json:

  1. "Settings": {
  2. "Abp.Mailing.Smtp.Host": "127.0.0.1",
  3. "Abp.Mailing.Smtp.Port": "25",
  4. "Abp.Mailing.Smtp.UserName": "",
  5. "Abp.Mailing.Smtp.Password": "",
  6. "Abp.Mailing.Smtp.Domain": "",
  7. "Abp.Mailing.Smtp.EnableSsl": "false",
  8. "Abp.Mailing.Smtp.UseDefaultCredentials": "true",
  9. "Abp.Mailing.DefaultFromAddress": "[email protected]",
  10. "Abp.Mailing.DefaultFromDisplayName": "ABP application"
  11. }

You can set/change these settings using the ISettingManager and store values in a database. See the setting system document to understand the setting system better.

Encrypt the SMTP Password

Abp.Mailing.Smtp.Password must be an encrypted value. If you use the ISettingManager to set the password, you don’t have to worry. It internally encrypts the values on set and decrypts on get.

If you use the appsettings.json to store the password, you should manually inject the ISettingEncryptionService and use its Encrypt method to obtain an encrypted value. This can be done by creating a simple code in your application. Then you can delete the code. As better, you can create a UI in your application to configure the email settings. In this case, you can directly use the ISettingManager without worrying the encryption.

ISmtpEmailSenderConfiguration

If you don’t want to use the setting system to store the email sending configuration, you can replace the ISmtpEmailSenderConfiguration service with your own implementation to get the configuration from any other source. ISmtpEmailSenderConfiguration is implemented by the SmtpEmailSenderConfiguration by default, which gets the configuration from the setting system as explained above.

Text Template Integration

ABP Framework provides a strong and flexible text templating system. You can use the text templating system to create dynamic email contents. Inject the ITemplateRenderer and use the RenderAsync to render a template. Then use the result as the email body.

While you can define and use your own text templates, email sending system provides two simple built-in text templates.

Example: Use the standard and simple message template to send emails

  1. using System.Threading.Tasks;
  2. using Volo.Abp.DependencyInjection;
  3. using Volo.Abp.Emailing;
  4. using Volo.Abp.Emailing.Templates;
  5. using Volo.Abp.TextTemplating;
  6. namespace Acme.BookStore.Web
  7. {
  8. public class MyService : ITransientDependency
  9. {
  10. private readonly IEmailSender _emailSender;
  11. private readonly ITemplateRenderer _templateRenderer;
  12. public MyService(
  13. IEmailSender emailSender,
  14. ITemplateRenderer templateRenderer)
  15. {
  16. _emailSender = emailSender;
  17. _templateRenderer = templateRenderer;
  18. }
  19. public async Task DoItAsync()
  20. {
  21. var body = await _templateRenderer.RenderAsync(
  22. StandardEmailTemplates.Message,
  23. new
  24. {
  25. message = "This is email body..."
  26. }
  27. );
  28. await _emailSender.SendAsync(
  29. "[email protected]",
  30. "Email subject",
  31. body
  32. );
  33. }
  34. }
  35. }

The resulting email body will be shown below:

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta charset="utf-8" />
  5. </head>
  6. <body>
  7. This is email body...
  8. </body>
  9. </html>

Emailing system defines the built-in text templates with the given names:

Abp.StandardEmailTemplates.Message“ is simplest template that has a text message:

  1. {{model.message}}

This template uses the “Abp.StandardEmailTemplates.Layout” as its layout.

Abp.StandardEmailTemplates.Layout“ is a simple template to provide an HTML document layout:

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta charset="utf-8" />
  5. </head>
  6. <body>
  7. {{content}}
  8. </body>
  9. </html>

The final rendered message was shown above.

These template names are contants defined in the Volo.Abp.Emailing.Templates.StandardEmailTemplates class.

Overriding/Replacing the Standard Templates

You typically want to replace the standard templates with your own ones, so you can prepare a branded email messages. To do that, you can use the power of the virtual file system (VFS) or replace them in your own template definition provider.

Pathes of the templates in the virtual file system are shown below:

  • /Volo/Abp/Emailing/Templates/Layout.tpl
  • /Volo/Abp/Emailing/Templates/Message.tpl

If you add files to the same localization in the virtual file system, your files will override them.

Templates are inline localized, that means you can take the power of the localization system to make your templates multi-cultural.

See the text templating system document for details.

Notice that you can define and use your own templates for your application, rather than using the standard simple templates. These standard templates are mostly for reusable modules where they don’t define their own templates but rely on the built-in ones. This makes easy to customize emails sent by the used modules, by just overriding the standard email layout template.

NullEmailSender

NullEmailSender is a built-in class that implements the IEmailSender, but writes email contents to the standard log system, rathen than actually sending the emails.

This class can be useful especially in development time where you generally don’t want to send real emails. The application startup template already uses this class in the DEBUG mode with the following configuration in the domain layer:

  1. #if DEBUG
  2. context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>());
  3. #endif

So, don’t confuse if you don’t receive emails on DEBUG mode. Emails will be sent as expected on production (RELEASE mode). Remove these lines if you want to send real emails on DEBUG too.

See Also