mirror of https://github.com/abpframework/abp.git
20 changed files with 350 additions and 11 deletions
@ -0,0 +1,12 @@ |
|||||
|
namespace Volo.Abp.Emailing.Templates |
||||
|
{ |
||||
|
public class EmailTemplate |
||||
|
{ |
||||
|
public string Content { get; } |
||||
|
|
||||
|
public EmailTemplate(string content) |
||||
|
{ |
||||
|
Content = content; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<string, object> Properties { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets/sets a key-value on the <see cref="Properties"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="name">Name of the property</param>
|
||||
|
/// <returns>
|
||||
|
/// Returns the value in the <see cref="Properties"/> dictionary by given <see cref="name"/>.
|
||||
|
/// Returns null if given <see cref="name"/> is not present in the <see cref="Properties"/> dictionary.
|
||||
|
/// </returns>
|
||||
|
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<string, object>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Emailing.Templates |
||||
|
{ |
||||
|
public class EmailTemplateDefinitionDictionary : Dictionary<string, EmailTemplateDefinition> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Emailing.Templates.Virtual; |
||||
|
|
||||
|
namespace Volo.Abp.Emailing.Templates |
||||
|
{ |
||||
|
public class EmailTemplateOptions |
||||
|
{ |
||||
|
public List<IEmailTemplateProvider> Providers { get; } |
||||
|
|
||||
|
public EmailTemplateDefinitionDictionary Templates { get; } |
||||
|
|
||||
|
public EmailTemplateOptions() |
||||
|
{ |
||||
|
Providers = new List<IEmailTemplateProvider> |
||||
|
{ |
||||
|
new VirtualFileEmailTemplateProvider() |
||||
|
}; |
||||
|
|
||||
|
Templates = new EmailTemplateDefinitionDictionary(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<EmailTemplateOptions> options, IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
ServiceProvider = serviceProvider; |
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public async Task<EmailTemplate> 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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Emailing.Templates |
||||
|
{ |
||||
|
public interface IEmailTemplateProvider |
||||
|
{ |
||||
|
Task ProvideAsync(EmailTemplateProviderContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Emailing.Templates |
||||
|
{ |
||||
|
public interface IEmailTemplateStore |
||||
|
{ |
||||
|
Task<EmailTemplate> GetAsync(string name); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Emailing.Templates.Virtual |
||||
|
{ |
||||
|
public class VirtualFileEmailTemplateOptions |
||||
|
{ |
||||
|
public IDictionary<string, string> Templates { get; } |
||||
|
|
||||
|
public VirtualFileEmailTemplateOptions() |
||||
|
{ |
||||
|
Templates = new Dictionary<string, string>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<IOptions<EmailTemplateOptions>>() |
||||
|
.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<IVirtualFileProvider>(); |
||||
|
|
||||
|
var fileInfo = virtualFileProvider.GetFileInfo(virtualFilePath); |
||||
|
if (fileInfo?.Exists != true) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return fileInfo; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp2.1</TargetFramework> |
||||
|
<LangVersion>latest</LangVersion> |
||||
|
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="Volo\Abp\Emailing\TestTemplates\*.*" /> |
||||
|
<None Remove="Volo\Abp\Emailing\TestTemplates\*.*" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\Volo.Abp.Emailing\Volo.Abp.Emailing.csproj" /> |
||||
|
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -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<VirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpEmailingTestModule>(); |
||||
|
}); |
||||
|
|
||||
|
context.Services.Configure<EmailTemplateOptions>(options => |
||||
|
{ |
||||
|
options.Templates["template1"] = |
||||
|
new EmailTemplateDefinition("template1") |
||||
|
.SetVirtualFilePath("/Volo/Abp/Emailing/TestTemplates/template1.html"); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<AbpEmailingTestModule> |
||||
|
{ |
||||
|
private readonly IEmailTemplateStore _emailTemplateStore; |
||||
|
|
||||
|
public EmailTemplateStore_Tests() |
||||
|
{ |
||||
|
_emailTemplateStore = GetRequiredService<IEmailTemplateStore>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Get_Registered_Template() |
||||
|
{ |
||||
|
var template = await _emailTemplateStore.GetAsync("template1"); |
||||
|
template.Content.ShouldContain("This is a test template!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> |
||||
|
<head> |
||||
|
<meta charset="utf-8" /> |
||||
|
</head> |
||||
|
<body> |
||||
|
This is a test template! |
||||
|
</body> |
||||
|
</html> |
||||
Loading…
Reference in new issue