diff --git a/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj b/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
index 71955ca500..b2394ea229 100644
--- a/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
+++ b/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
@@ -18,6 +18,10 @@
+
+
+
+
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/ITemplateRender.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/ITemplateRender.cs
new file mode 100644
index 0000000000..35ac14c8fd
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/ITemplateRender.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public interface ITemplateRender
+ {
+ Task RenderAsync(string template, object model = null);
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/TemplateRender.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/TemplateRender.cs
new file mode 100644
index 0000000000..8c4e24017c
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/TemplateRender.cs
@@ -0,0 +1,15 @@
+using System.Threading.Tasks;
+using Scriban;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.Emailing.Templates
+{
+ public class TemplateRender : ITemplateRender, ITransientDependency
+ {
+ public async Task RenderAsync(string template, object model = null)
+ {
+ var scribanTemplate = Template.Parse(template);
+ return await scribanTemplate.RenderAsync(model);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateRender_Tests.cs b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateRender_Tests.cs
new file mode 100644
index 0000000000..403aaad0bd
--- /dev/null
+++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateRender_Tests.cs
@@ -0,0 +1,64 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Emailing.Templates;
+using Xunit;
+
+namespace Volo.Abp.Emailing
+{
+ public class EmailTemplateRender_Tests : AbpIntegratedTest
+ {
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+
+ private readonly ITemplateRender _templateRender;
+
+ public EmailTemplateRender_Tests()
+ {
+ _templateRender = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task RenderAsync()
+ {
+ var template = "Hello {{email}} {{ for order in orders }}{{ order.id }}:{{ order.name }},{{ end }}";
+
+ var model = new ModelClass
+ {
+ Email = "john@abp.io",
+ Orders = new List
+ {
+ new ModelClass.Order
+ {
+ Id = "1",
+ Name = "iphone"
+ },
+ new ModelClass.Order
+ {
+ Id = "2",
+ Name = "ipad"
+ }
+ }
+ };
+
+ var result = await _templateRender.RenderAsync(template, model);
+ result.ShouldBe("Hello john@abp.io 1:iphone,2:ipad,");
+ }
+
+ public class ModelClass
+ {
+ public string Email { get; set; }
+
+ public List Orders { get; set; }
+
+ public class Order
+ {
+ public string Id { get; set; }
+
+ public string Name { get; set; }
+ }
+ }
+ }
+}
\ No newline at end of file