diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md index fa5806c488..3b1c95452c 100644 --- a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md +++ b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md @@ -1,12 +1,24 @@ -# Replacing Email Template and Sending Emails +# Replacing Email Templates and Sending Emails ## Introduction -Hi, in this step by step article, I will show you how you can replace the existing templates and how you can send emails by using the replaced templates. +Hi, in this step by step article, we will send an email by using standard email template and then we will replace the standard email template with our new created template, thanks to [Text Templating System](https://docs.abp.io/en/abp/latest/Text-Templating#replacing-the-existing-templates) and [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). + +* ABP framework provides a strong and flexible [Text Templating System](https://docs.abp.io/en/abp/latest/Text-Templating). So, we can use the text templating system to create dynamic email contents on a template and a model. + +* In this article, we will use `StandardEmailTemplates.Message` as standard email template. Then we will create a new template and replace the standard email template with our new template by using [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). + +* The `Virtual File System` makes it possible to manage files that do not physically exist on the file system. That means we can override `StandardEmailTemplates.Message` template by changing it's path with our new template's path. ## Creating the Solution -Before starting to development, we need to create a solution named `TemplateReplace` (or whatever you want). We can download a new startup template by using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) : +> ABP Framework offers startup templates to get into the business faster. + +In this article, I will create a new startup template and perform the operations on this template. But if you have already a project you don't need to create a new startup template, you can implement the following steps to your existing project. (These steps can be applied to any project. (MVC, Angular etc.)) + +> If you have already a project you can skip this section. + +Before starting to development, we will create a solution named `TemplateReplace` (or whatever you want). We can create a new startup template by using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) : ````bash abp new TemplateReplace @@ -18,7 +30,7 @@ Run the `TemplateReplace.DbMigrator` application as below to create the database ![db-migrator-1](db-migrator-1.jpg) -* Left click to `TemplateReplace.DbMigrator` and choose the `Debug`. +* Right click to `TemplateReplace.DbMigrator` and choose the `Debug`. ![db-migrator-2](db-migrator-2.jpg) @@ -36,23 +48,7 @@ First thing we need to do is, creating a email service to sending emails. ABP Fr ### Step - 1 -Create an `Email` folder in the `TemplateReplace.Application.Contracts` project and add a interface named `IEmailService` inside of it : - -```csharp -using System.Threading.Tasks; - -namespace TemplateReplace.Email -{ - public interface IEmailService - { - Task SendAsync(); - } -} -``` - -### Step - 2 - -Create an `Email` folder in the `TemplateReplace.Application` project and add a class named `EmailService` inside of it to implement the `IEmailService` interface. +Create an `Emailing` folder in the `TemplateReplace.Domain` project and add a class named `EmailService` inside of it. ```csharp using System.Threading.Tasks; @@ -61,9 +57,9 @@ using Volo.Abp.Emailing; using Volo.Abp.Emailing.Templates; using Volo.Abp.TextTemplating; -namespace TemplateReplace.Email +namespace TemplateReplace.Emailing { - public class EmailService : IEmailService, ITransientDependency + public class EmailService : ITransientDependency { private readonly IEmailSender _emailSender; private readonly ITemplateRenderer _templateRenderer; @@ -74,36 +70,32 @@ namespace TemplateReplace.Email _templateRenderer = templateRenderer; } - public async Task SendAsync() + public async Task SendAsync(string targetEmail) { var emailBody = await _templateRenderer.RenderAsync( StandardEmailTemplates.Message, new { - message = "This is email body..." + message = "ABP Framework provides IEmailSender service that is used to send emails." } ); await _emailSender.SendAsync( - "from_email@abp.io", - "target_email@abp.io", + targetEmail, "Subject", emailBody ); - - return emailBody; } } -} +} ``` -* ABP framework provides a strong and flexible [text templating system](https://docs.abp.io/en/abp/latest/Text-Templating). So, we can use the text templating system to create dynamic email contents. - * To create an email content, we need to inject `ITemplateRenderer` and use the `RenderAsync` method to render a template. * We've used `StandardEmailTemplates.Message` as standart email template. This provides us a standard and simple message template to send mails. * The resulting email body should be like shown below: + ```html @@ -111,96 +103,118 @@ namespace TemplateReplace.Email - This is email body... + ABP Framework provides IEmailSender service that is used to send emails. ``` -### Step - 3 +### Step - 2 (Configuring Email Settings) -* Now we need to create a user interface to be able to see the standard email template. To do this quickly, open your existing `Index.cshtml.cs` in your `TemplateReplace.Web` project. It's under the **Pages** folder. And copy-paste the below content. +* Now, we need to configure some email settings by following [settings documentation](https://docs.abp.io/en/abp/latest/Settings). For achieve this, create a class named `EmailSettingProvider` in `Emailing` folder and set the content as below. ```csharp -using TemplateReplace.Email; +using Volo.Abp.Emailing; +using Volo.Abp.Settings; -namespace TemplateReplace.Web.Pages +namespace TemplateReplace.Emailing { - public class IndexModel : TemplateReplacePageModel + public class EmailSettingProvider : SettingDefinitionProvider { - private readonly IEmailService _emailService; - public string EmailBody { get; set; } - - public IndexModel(IEmailService emailService) + public override void Define(ISettingDefinitionContext context) { - _emailService = emailService; - } - - public async void OnGet() - { - if(CurrentUser.IsAuthenticated) - { - EmailBody = await _emailService.SendAsync(); - } + //Google's SMTP settings: + context.Add( + new SettingDefinition(EmailSettingNames.Smtp.Host, "smtp.gmail.com"), + new SettingDefinition(EmailSettingNames.Smtp.Port, "587"), + new SettingDefinition(EmailSettingNames.Smtp.UserName, "your_email@gmail.com"), //smtp username: your email address + new SettingDefinition(EmailSettingNames.Smtp.Password, "your_password", isEncrypted: false), //smtp password: your email password to auth + new SettingDefinition(EmailSettingNames.Smtp.EnableSsl, "true"), + new SettingDefinition(EmailSettingNames.Smtp.UseDefaultCredentials, "false") //set as false to auth + ); } } } ``` -* Then, open your `Index.cshtml` file and set the content as below. +* ABP was designed to be modular, so different modules can have different settings. A module must create a class derived from the `SettingDefinitionProvider` in order to define its settings. Therefore in here we created a class named `EmailSettingProvider` and inherit from `SettingDefinitionProvider` to define email settings. -```html -@page -@using Microsoft.AspNetCore.Mvc.Localization -@using TemplateReplace.Localization -@using Volo.Abp.Users -@model TemplateReplace.Web.Pages.IndexModel -@inject IHtmlLocalizer L -@inject ICurrentUser CurrentUser -@section styles { - - - -} -@section scripts { - - - -} -
-

@L["Welcome"]

-
-
-

@L["LongWelcomeMessage"]

-
-
-
- abp.io - @if (!CurrentUser.IsAuthenticated) +* Here, I used Google's SMTP settings to send emails via Gmail. You can change these setting values by your need. It's a good idea to define a const string for a setting name instead of using a magic string. The ABP framework has a class named `EmailSettingNames`, we can just change the values of these settings by using these pre-defined class properties as key. + +> **Note:** If you want to use Google's SMTP server settings and send emails via Gmail, you should confirm [this](https://myaccount.google.com/u/0/lesssecureapps). + +* After that we need to open `TemplateReplaceDomainModule.cs` file and change its contents as below to sending real-time emails. + +```csharp +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using TemplateReplace.MultiTenancy; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.IdentityServer; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.IdentityServer; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace TemplateReplace +{ + [DependsOn( + typeof(TemplateReplaceDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpIdentityServerDomainModule), + typeof(AbpPermissionManagementDomainIdentityServerModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule) + )] + public class TemplateReplaceDomainModule : AbpModule { - @L["Login"] + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsEnabled = MultiTenancyConsts.IsEnabled; + }); + + // #if DEBUG + // context.Services.Replace(ServiceDescriptor.Singleton()); + // #endif + } } -
+} - ``` -* After all of this, we can run the `TemplateReplace.Web` application and logged in to see the standard email template. +* `NullEmailSender` is a built-in class that implements the `IEmailSender`, but writes email contents to the standard log system, rather than actually sending the emails. This class can be useful especially in development time where you generally don't want to send real emails. Therefore ABP framework defined this by default. But we want to send real emails, so we must remove these lines or we should take it to the comment line. -![standard-template](standard-template.jpg) +* The last thing we need to do is delete the default email settings from `appsettings.json` file in `TemplateReplace.Web`. -* As we see above, `StandardEmailTemplates.Message` template works as expected. But we need to be sure about the mail has been sent or not. To achieve this, we can examine the **logs**. So, open the `Logs` folder (It's under **TemplateReplace .Web** folder). Inside of this folder, there is a file named `logs.txt`. When we open this file and examine the lines, we can see our email details as below (target email address, subject of mail and email body). +![appsettings.json](settings.jpg) -![email-details](email-details.jpg) +> **Note:** In this article, we defined email settings in `EmailSettingProvider` class, but these settings could be defined in `appsettings.json` file. For more details about this, please check the [document](https://docs.abp.io/en/abp/latest/Settings#setting-values-in-the-application-configuration). -### Step - 4 +* After all of these steps, when we send an email we should see the following template. -* So far we've sent mail by using standard email template of ABP. But we can want to replace the email template with the new one. We can achieve this by following [the documentation](https://docs.abp.io/en/abp/latest/Text-Templating#replacing-the-existing-templates). +![email-message](message.jpg) -* First thing we need to do is creating our new **email template**. So, create a folder named `Templates` and add `EmailLayout.cshtml` file inside of it. And copy-paste the below content. +### Step - 3 -```html +* So far we've sent mail by using standard email template of ABP. But we may want to replace the email template with the new one. We can achieve this by following the `Text Templating` [documentation](https://docs.abp.io/en/abp/latest/Text-Templating#replacing-the-existing-templates). + +* In this article, I will create a email template by using free template generator named `Bee`. You can reach the free templates from [here](https://beefree.io/templates/free/). + +* After choosing our free template, we can create a new **email template**. So, create a folder named `Templates` under `Emailing` folder in `TemplateReplace.Domain` and add `EmailTemplate.tpl` file inside of it. And copy-paste the below content or your free template's content. + +```tpl @@ -232,11 +246,6 @@ namespace TemplateReplace.Web.Pages - - - - -

ABP Community

@@ -257,19 +266,6 @@ namespace TemplateReplace.Web.Pages - - - - - - - - - - - - - @@ -281,7 +277,7 @@ namespace TemplateReplace.Web.Pages * Then we need to make the template file as "Embedded Resource". We can do this as below. -* First left click to **EmailLayout.cshtml** and choose `Properties`. +* First right click to **EmailTemplate.tpl** and choose `Properties`. ![embedded-resource](embedded-resource.jpg) @@ -289,16 +285,16 @@ namespace TemplateReplace.Web.Pages ![embedded-resource-2](embedded-resource-2.jpg) -### Step - 5 (Replacing the Email Template) +### Step - 4 (Replacing the Email Template) -* To replace the current email template with our new email template, we need to override it. To achieve this, create a class in `TemplateReplace.Web` and fill it with the below content. +* To replace the current email template with our new email template, we need to override it. To achieve this, create a class named `EmailTemplateDefinitionProvider` under `Emailing` folder in `TemplateReplace.Domain` and fill it with the below content. ```csharp using Volo.Abp.DependencyInjection; using Volo.Abp.Emailing.Templates; using Volo.Abp.TextTemplating; -namespace TemplateReplace.Web +namespace TemplateReplace.Emailing { public class EmailTemplateDefinitionProvider : TemplateDefinitionProvider, ITransientDependency { @@ -308,7 +304,7 @@ namespace TemplateReplace.Web emailLayoutTemplate .WithVirtualFilePath( - "/Templates/EmailLayout.cshtml", + "/Emailing/Templates/EmailTemplate.tpl", isInlineLocalized: true ); } @@ -316,32 +312,66 @@ namespace TemplateReplace.Web } ``` -* In here we've created a template definition provider class that gets the email layout template and changes the virtual file path for the template. +* In here we've created a template definition provider class that gets the email layout template and change the virtual file path for the template. -* This approach allows us to locate templates in any folder instead of the folder defined by the depended module. +* This approach allows us to locate templates in any folder instead of the folder defined by the depended module. For more detail, check the [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). -### Step - 6 +### Step - 5 -* Lastly, we need to configure the [virtual file system](https://docs.abp.io/en/abp/latest/Virtual-File-System). To do this open your `TemplateReplaceWebModule` in `TemplateReplace.Web` and update the `ConfigureVirtualFileSystem` method as below. +* Lastly, we need to configure the [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). To do this open your `TemplateReplaceDomainModule.cs` in `TemplateReplace.Domain` and update the content as below. ```csharp -//... -private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment) +using TemplateReplace.MultiTenancy; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.IdentityServer; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.IdentityServer; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.VirtualFileSystem; + +namespace TemplateReplace { - if (hostingEnvironment.IsDevelopment()) + [DependsOn( + typeof(TemplateReplaceDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpIdentityServerDomainModule), + typeof(AbpPermissionManagementDomainIdentityServerModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule) + )] + public class TemplateReplaceDomainModule : AbpModule { - Configure(options => + public override void ConfigureServices(ServiceConfigurationContext context) { - options.FileSets.AddEmbedded(); //to replace the standard email template + Configure(options => + { + options.IsEnabled = MultiTenancyConsts.IsEnabled; + }); - //... - }); + //Add this configuration + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + } } } -//... + ``` -* And now when we start the application, we need to see the new email template like as below. +* And now when we want to send a new email, we should see the our new defined template as the message like below. ![email-last](email-last.jpg) diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-details.jpg b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-details.jpg deleted file mode 100644 index df23bcc8e0..0000000000 Binary files a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-details.jpg and /dev/null differ diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-last.jpg b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-last.jpg index 4f8c90e3cd..9170d16163 100644 Binary files a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-last.jpg and b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-last.jpg differ diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource-2.jpg b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource-2.jpg index 81592fb69a..1abdba48cb 100644 Binary files a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource-2.jpg and b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource-2.jpg differ diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource.jpg b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource.jpg index 9d437790b1..b03739e6c0 100644 Binary files a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource.jpg and b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource.jpg differ diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/message.jpg b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/message.jpg new file mode 100644 index 0000000000..fe80c2ac0c Binary files /dev/null and b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/message.jpg differ diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/settings.jpg b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/settings.jpg new file mode 100644 index 0000000000..6f45ac48eb Binary files /dev/null and b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/settings.jpg differ diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/standard-template.jpg b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/standard-template.jpg deleted file mode 100644 index 68f4dc4834..0000000000 Binary files a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/standard-template.jpg and /dev/null differ