diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index 07a67830be..a45a1a958e 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -200,15 +200,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundWorkers"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.Tests", "test\Volo.Abp.BackgroundJobs.Tests\Volo.Abp.BackgroundJobs.Tests.csproj", "{D86548EA-7047-4623-8824-F6285CD254AA}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BackgroundJobs.Abstractions", "src\Volo.Abp.BackgroundJobs.Abstractions\Volo.Abp.BackgroundJobs.Abstractions.csproj", "{EB9C3B4D-FEBD-4691-8F34-AAC2C13F6F2F}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.Abstractions", "src\Volo.Abp.BackgroundJobs.Abstractions\Volo.Abp.BackgroundJobs.Abstractions.csproj", "{EB9C3B4D-FEBD-4691-8F34-AAC2C13F6F2F}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BackgroundJobs.HangFire", "src\Volo.Abp.BackgroundJobs.HangFire\Volo.Abp.BackgroundJobs.HangFire.csproj", "{35AC93EF-E383-4F4E-839D-6EE1C62681F1}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.HangFire", "src\Volo.Abp.BackgroundJobs.HangFire\Volo.Abp.BackgroundJobs.HangFire.csproj", "{35AC93EF-E383-4F4E-839D-6EE1C62681F1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.HangFire", "src\Volo.Abp.HangFire\Volo.Abp.HangFire.csproj", "{EE01E964-E60E-4C3C-BCF0-AF1A0C0A3DC9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.HangFire", "src\Volo.Abp.HangFire\Volo.Abp.HangFire.csproj", "{EE01E964-E60E-4C3C-BCF0-AF1A0C0A3DC9}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BackgroundJobs.RabbitMQ", "src\Volo.Abp.BackgroundJobs.RabbitMQ\Volo.Abp.BackgroundJobs.RabbitMQ.csproj", "{DA7A2C04-E8C4-48AA-A37E-27C25BCE280A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.RabbitMQ", "src\Volo.Abp.BackgroundJobs.RabbitMQ\Volo.Abp.BackgroundJobs.RabbitMQ.csproj", "{DA7A2C04-E8C4-48AA-A37E-27C25BCE280A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RabbitMQ", "src\Volo.Abp.RabbitMQ\Volo.Abp.RabbitMQ.csproj", "{D91DE561-F403-416F-BD0B-DBF0BA1C4447}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.RabbitMQ", "src\Volo.Abp.RabbitMQ\Volo.Abp.RabbitMQ.csproj", "{D91DE561-F403-416F-BD0B-DBF0BA1C4447}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Emailing.Tests", "test\Volo.Abp.Emailing.Tests\Volo.Abp.Emailing.Tests.csproj", "{D3E07597-BB3D-4249-B873-607E2C128C0E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -592,6 +594,10 @@ Global
{D91DE561-F403-416F-BD0B-DBF0BA1C4447}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D91DE561-F403-416F-BD0B-DBF0BA1C4447}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D91DE561-F403-416F-BD0B-DBF0BA1C4447}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D3E07597-BB3D-4249-B873-607E2C128C0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D3E07597-BB3D-4249-B873-607E2C128C0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D3E07597-BB3D-4249-B873-607E2C128C0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D3E07597-BB3D-4249-B873-607E2C128C0E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -693,6 +699,7 @@ Global
{EE01E964-E60E-4C3C-BCF0-AF1A0C0A3DC9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DA7A2C04-E8C4-48AA-A37E-27C25BCE280A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{D91DE561-F403-416F-BD0B-DBF0BA1C4447} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
+ {D3E07597-BB3D-4249-B873-607E2C128C0E} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs
index 14d7b5d1e2..90e4b8bcd6 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs
@@ -1,9 +1,5 @@
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.FileProviders;
-using Microsoft.Extensions.Options;
+using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.VirtualFileSystem;
-using Volo.Abp.VirtualFileSystem;
namespace Microsoft.AspNetCore.Builder
{
diff --git a/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj b/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
index c711697c91..a91be8faf5 100644
--- a/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
+++ b/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
@@ -15,6 +15,7 @@
+
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
index afaf0b92fa..d4b6c4e2e8 100644
--- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
@@ -1,9 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
+using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Emailing
{
+ [DependsOn(
+ typeof(AbpSettingsModule),
+ typeof(AbpVirtualFileSystemModule)
+ )]
public class AbpEmailingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs
new file mode 100644
index 0000000000..1d4c29053f
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs
@@ -0,0 +1,12 @@
+namespace Volo.Abp.Emailing.Templates
+{
+ public class EmailTemplate
+ {
+ public string Content { get; }
+
+ public EmailTemplate(string content)
+ {
+ Content = content;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs
new file mode 100644
index 0000000000..d852070e8a
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using JetBrains.Annotations;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public class EmailTemplateDefinition
+ {
+ public string Name { get; }
+
+ public Dictionary Properties { get; }
+
+ ///
+ /// Gets/sets a key-value on the .
+ ///
+ /// Name of the property
+ ///
+ /// Returns the value in the dictionary by given .
+ /// Returns null if given is not present in the dictionary.
+ ///
+ public object this[string name]
+ {
+ get => Properties.GetOrDefault(name);
+ set => Properties[name] = value;
+ }
+
+ public EmailTemplateDefinition([NotNull]string name)
+ {
+ Name = Check.NotNullOrWhiteSpace(name, nameof(name));
+ Properties = new Dictionary();
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs
new file mode 100644
index 0000000000..09bc33ec97
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public class EmailTemplateDefinitionDictionary : Dictionary
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs
new file mode 100644
index 0000000000..d9bf02aae9
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using Volo.Abp.Emailing.Templates.Virtual;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public class EmailTemplateOptions
+ {
+ public List Providers { get; }
+
+ public EmailTemplateDefinitionDictionary Templates { get; }
+
+ public EmailTemplateOptions()
+ {
+ Providers = new List
+ {
+ new VirtualFileEmailTemplateProvider()
+ };
+
+ Templates = new EmailTemplateDefinitionDictionary();
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs
new file mode 100644
index 0000000000..c1fbc311ba
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs
@@ -0,0 +1,20 @@
+using System;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public class EmailTemplateProviderContext : IServiceProviderAccessor
+ {
+ public string Name { get; }
+
+ public IServiceProvider ServiceProvider { get; }
+
+ public EmailTemplate Template { get; set; }
+
+ public EmailTemplateProviderContext(string name, IServiceProvider serviceProvider)
+ {
+ Name = name;
+ ServiceProvider = serviceProvider;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs
new file mode 100644
index 0000000000..231c86f653
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public class EmailTemplateStore : IEmailTemplateStore, ITransientDependency
+ {
+ protected IServiceProvider ServiceProvider { get; }
+ protected EmailTemplateOptions Options { get; }
+
+ public EmailTemplateStore(IOptions options, IServiceProvider serviceProvider)
+ {
+ ServiceProvider = serviceProvider;
+ Options = options.Value;
+ }
+
+ public async Task GetAsync(string name)
+ {
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ var context = new EmailTemplateProviderContext(name, scope.ServiceProvider);
+ foreach (var provider in Options.Providers)
+ {
+ await provider.ProvideAsync(context);
+ }
+
+ if (context.Template == null)
+ {
+ //TODO: Return a default email template!
+ throw new NotImplementedException();
+ }
+
+ return context.Template;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs
new file mode 100644
index 0000000000..4c05e04f30
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public interface IEmailTemplateProvider
+ {
+ Task ProvideAsync(EmailTemplateProviderContext context);
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs
new file mode 100644
index 0000000000..ae35725fff
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public interface IEmailTemplateStore
+ {
+ Task GetAsync(string name);
+ }
+}
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs
new file mode 100644
index 0000000000..2bcd3984d1
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs
@@ -0,0 +1,16 @@
+namespace Volo.Abp.Emailing.Templates.Virtual
+{
+ public static class EmailTemplateDefinitionExtensions
+ {
+ public static EmailTemplateDefinition SetVirtualFilePath(this EmailTemplateDefinition emailTemplateDefinition, string path)
+ {
+ emailTemplateDefinition[VirtualFileEmailTemplateProvider.VirtualFilePathKey] = path;
+ return emailTemplateDefinition;
+ }
+
+ public static string GetVirtualFilePathOrNull(this EmailTemplateDefinition emailTemplateDefinition)
+ {
+ return emailTemplateDefinition[VirtualFileEmailTemplateProvider.VirtualFilePathKey] as string;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateOptions.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateOptions.cs
new file mode 100644
index 0000000000..0103ac27dc
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateOptions.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace Volo.Abp.Emailing.Templates.Virtual
+{
+ public class VirtualFileEmailTemplateOptions
+ {
+ public IDictionary Templates { get; }
+
+ public VirtualFileEmailTemplateOptions()
+ {
+ Templates = new Dictionary();
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs
new file mode 100644
index 0000000000..f5c3dece34
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Options;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.Abp.Emailing.Templates.Virtual
+{
+ public class VirtualFileEmailTemplateProvider : IEmailTemplateProvider
+ {
+ public const string VirtualFilePathKey = "VirtualFilePath";
+
+ public Task ProvideAsync(EmailTemplateProviderContext context)
+ {
+ var templateDefinition = FindTemplateDefinition(context);
+ if (templateDefinition == null)
+ {
+ return Task.CompletedTask;
+ }
+
+ var fileInfo = FindVirtualFileInfo(context, templateDefinition);
+ if (fileInfo == null)
+ {
+ return Task.CompletedTask;
+ }
+
+ context.Template = new EmailTemplate(fileInfo.ReadAsString());
+ return Task.CompletedTask;
+ }
+
+ protected virtual EmailTemplateDefinition FindTemplateDefinition(EmailTemplateProviderContext context)
+ {
+ return context
+ .ServiceProvider
+ .GetRequiredService>()
+ .Value
+ .Templates
+ .GetOrDefault(context.Name);
+ }
+
+ protected virtual IFileInfo FindVirtualFileInfo(EmailTemplateProviderContext context, EmailTemplateDefinition templateDefinition)
+ {
+ var virtualFilePath = templateDefinition?.GetVirtualFilePathOrNull();
+ if (virtualFilePath == null)
+ {
+ return null;
+ }
+
+ var virtualFileProvider = context.ServiceProvider.GetRequiredService();
+
+ var fileInfo = virtualFileProvider.GetFileInfo(virtualFilePath);
+ if (fileInfo?.Exists != true)
+ {
+ return null;
+ }
+
+ return fileInfo;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs
index 74a4a48f6c..d65d143362 100644
--- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs
+++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs
@@ -28,7 +28,7 @@
///
/// Can be used to store a custom object related to this setting.
///
- public object CustomData { get; set; }
+ public object CustomData { get; set; } //TODO: Convert to dictionary!
//TODO: Add Properties dictionary for custom stuff (and remove CustomData)
diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj
new file mode 100644
index 0000000000..c3927589af
--- /dev/null
+++ b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ netcoreapp2.1
+ latest
+ true
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/AbpEmailingTestModule.cs b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/AbpEmailingTestModule.cs
new file mode 100644
index 0000000000..d45fab7d32
--- /dev/null
+++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/AbpEmailingTestModule.cs
@@ -0,0 +1,29 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Emailing.Templates;
+using Volo.Abp.Emailing.Templates.Virtual;
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.Abp.Emailing
+{
+ [DependsOn(
+ typeof(AbpEmailingModule),
+ typeof(AbpTestBaseModule))]
+ public class AbpEmailingTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ context.Services.Configure(options =>
+ {
+ options.Templates["template1"] =
+ new EmailTemplateDefinition("template1")
+ .SetVirtualFilePath("/Volo/Abp/Emailing/TestTemplates/template1.html");
+ });
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs
new file mode 100644
index 0000000000..023b6404f4
--- /dev/null
+++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs
@@ -0,0 +1,24 @@
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Emailing.Templates;
+using Xunit;
+
+namespace Volo.Abp.Emailing
+{
+ public class EmailTemplateStore_Tests : AbpIntegratedTest
+ {
+ private readonly IEmailTemplateStore _emailTemplateStore;
+
+ public EmailTemplateStore_Tests()
+ {
+ _emailTemplateStore = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task Should_Get_Registered_Template()
+ {
+ var template = await _emailTemplateStore.GetAsync("template1");
+ template.Content.ShouldContain("This is a test template!");
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/TestTemplates/template1.html b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/TestTemplates/template1.html
new file mode 100644
index 0000000000..5c98393c69
--- /dev/null
+++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/TestTemplates/template1.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+ This is a test template!
+
+
\ No newline at end of file