我有一個asp.net的Web應用程序,它在註冊過程中向用戶發送幾封電子郵件。現在我讓他們內嵌代碼,但是我想把它們放在一箇中心位置,我可以編輯它們而不必進入VS.哪裏存儲電子郵件模板
什麼是最好的地方/格式來存儲這些HTML模板?
我有一個asp.net的Web應用程序,它在註冊過程中向用戶發送幾封電子郵件。現在我讓他們內嵌代碼,但是我想把它們放在一箇中心位置,我可以編輯它們而不必進入VS.哪裏存儲電子郵件模板
什麼是最好的地方/格式來存儲這些HTML模板?
我存儲我的所有電子郵件模板,我的web應用程序作爲ASP.NET MVC剃刀訪問量,但作爲在燈組件,我可以輕鬆地從任何項目中引用嵌入的資源。
模板看起來是這樣的(注意本地化):
@model Milkshake.Commerce.Model.Users.UserDto
@using Milkshake.Core.Internationalization;
@using Milkshake.Commerce.Model.Meta;
@if (Language.CurrentForInterface.TwoLetterISOLanguageName.Equals("da"))
{
<h1>Hej @Model.FirstName</h1>
<p>
Din nye brugerkonto til Milkshake Commerce er blevet oprettet.
</p>
<p>
Gå til dine <a href="http://@ShopSettings.Instance.Domain.TrimEnd('/')/Account">konto indstillinger</a>, brug din e-mail adresse som adgangskode og du vil blive videreført til dine konto indstillinger, hvor du kan ændre din adgangskode.
</p>
<p>Ha' en god dag!</p>
<h2>The Milkshake Commerce Team!</h2>
}
else
{
<h1>Hi @Model.FirstName</h1>
<p>
Your new user account for Milkshake Commerce has been created for you.
</p>
<p>
Go to your <a href="http://@ShopSettings.Instance.Domain.TrimEnd('/')/Account">user account page</a>, use your e-mail address as password and you'll be taken directly to your account page where you can change your password.
</p>
<p>Have a nice day!</p>
<h2>The Milkshake Commerce Team!</h2>
}
然後我有了 「主人」 的模板,稱爲_AppEmailTemplate.cshtml
:
@using Milkshake.Commerce.Model.Resources
<!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style type="text/css">
body
{
font-family: Arial, Helvetica;
}
.layout-wrapper
{
width: 600px;
}
.header
{
background-color: #242225;
}
.header img
{
display: block;
}
.content
{
background-color: #ffffff; padding: 10px 20px; border: 10px solid #eaeaea; border-top: none;
}
.footer
{
padding: 20px; padding-top: 5px; font-size: 10px; color: #cccccc;
}
p
{
font-size: 14px;
}
p.company-details
{
font-size: 12px;
}
h1
{
font-size: 20px;
}
h2
{
font-size: 16px;
}
</style>
<style type="text/css" id="mobile">
@@media only screen and (max-device-width: 480px) {
body
{
}
.layout-wrapper
{
width: 480px !important;
}
.header
{
background-color: transparent !important;
}
.header img
{
width: 480px !important;
}
.content
{
border: none !important;
}
.footer
{
padding-top: 15px !important;
}
p
{
font-size: 22px !important;
}
h1
{
font-size: 28px !important;
}
h2
{
font-size: 24px !important;
}
}
</style>
</head>
<body leftmargin="0" marginwidth="0" topmargin="0" marginheight="0" offset="0" bgcolor="#f1f1f1">
<table width="100%" cellpadding="0" cellspacing="0" bgcolor="#f1f1f1">
<tr>
<td valign="top" align="center">
<table cellpadding="0" cellspacing="0" width="100%" height="80">
<tr>
<td class="header" align="center">
<table cellpadding="0" cellspacing="0" width="600" height="80" class="layout-wrapper" style="width: 600px;">
<tr>
<td>
<img src="http://example.com/email-header.png" alt="Milkshake Commerce" />
</td>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" width="600" class="layout-wrapper">
<tr>
<td class="content" align="left">
#¤#¤CONTENTSECTION#¤#¤
</td>
</tr>
<tr>
<td class="footer" align="left">
<p>@Text.appEmailDisclaimer</p>
<p>@Text.appEmailFooterAd.UrlDecode()</p>
<p class="company-details"><i>Company name etc.</i></p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
實際發送電子郵件,我使用RazorEngine進行渲染:
public void SendSystemEmail<T>(string templateName, string subject, string fromName, string recipientEmail, T model)
{
dynamic template = this.GetEmailTemplate(templateName);
string layoutBody = RazorEngine.Razor.Parse(template.Layout as string, model);
string emailBody = RazorEngine.Razor.Parse(template.Template as string, model);
emailBody = layoutBody.Replace(CONTENTSECTIONREPLACETOKEN, emailBody);
PreMailer.Net.PreMailer pm = new PreMailer.Net.PreMailer();
emailBody = pm.MoveCssInline(emailBody, true);
EmailDto email = new EmailDto();
email.Body = emailBody;
email.IsBodyHtml = true;
email.FromEmail = "[email protected]";
email.ReplyToEmail = email.FromEmail;
email.FromName = fromName;
email.RecipientEmail = recipientEmail;
email.Subject = subject;
email.Type = EmailTypes.Transactional;
if (String.IsNullOrWhiteSpace(email.FromName))
{
email.FromName = "Milkshake Software";
}
this.SendMailMessages(new List<EmailDto>() { email }, false);
}
上述代碼使用我自己的EmailDto對象噸。在這裏,您可以直接輕鬆創建[MailMessage][2]
實例,並使用[SmtpClient][3]
發送它。
此外,爲了在所有電子郵件客戶端中獲得最佳呈現效果,我使用自己的PreMailer.Net庫將所有CSS內嵌。閱讀my blog post here,瞭解更多信息。(代碼是在Github上)
的GetEmailTemplate做到這一點:
/// <summary>
/// Gets the email template.
/// </summary>
/// <param name="templateName">Name of the template.</param>
/// <returns>Returns the e-mail template.</returns>
private dynamic GetEmailTemplate(string templateName)
{
string masterTemplateContents = this.GetTemplateFileContents("_AppEmailTemplate.cshtml");
string templateContents = this.GetTemplateFileContents(templateName + ".html.cshtml");
return new { Layout = masterTemplateContents, Template = templateContents };
}
/// <summary>
/// Gets the template file contents.
/// </summary>
/// <param name="templateFileName">The name of the template file.</param>
/// <returns>Returns the contents of the template file.</returns>
private string GetTemplateFileContents(string templateFileName)
{
return this.GetEmailFileContents("Templates", templateFileName);
}
/// <summary>
/// Gets the email file contents.
/// </summary>
/// <param name="lastNamespaceToken">The last namespace token.</param>
/// <param name="templateFileName">The name of the template file.</param>
/// <returns>
/// Returns the contents of the template file.
/// </returns>
private string GetEmailFileContents(string lastNamespaceToken, string templateFileName)
{
var assembly = Assembly.GetExecutingAssembly();
if (assembly != null)
{
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(assembly.GetManifestResourceStream(String.Format("MyApp.BusinessLogic.Communication.{0}.{1}", lastNamespaceToken, templateFileName))))
{
while (!sr.EndOfStream)
{
var line = sr.ReadLine();
if (!line.StartsWith("@model"))
{
sb.AppendLine(line);
}
}
}
return sb.ToString();
}
return null;
}
這取決於模板改變的頻率以及改變的模式。 E.g:
改變應用程序的用戶來說,變化是迫切的和潛在頻繁:
開發商(也就是你)的改變而改變是罕見的,而不是urgen:
您可以將電子郵件模板存儲在.html file
中。然後將其格式化,以支持您想要包含的參數。例如
<head>
<title></title>
</head>
<body>
Hello <!--Name--> ,
This is a test template
User Name: <!--UserName-->
.............................
.............................
</body>
</html>
每當您發送電子郵件給用戶,你要設置的模板,用戶特定的,所以你可以在運行時替換參數。
我建議將電子郵件模板存儲在XML文件中,這樣可以通過向郵件模板添加屬性來實現將來的可伸縮性,並且還可以輕鬆進行編輯。
謝謝大家提供有關他們是如何處理的見解。我從這裏收集了大量的知識。我喜歡@MartinHN使用Razor分析器和具體的數據模型。
但是,它沒有爲我工作得很好。
要求:
我必須存儲電子郵件模板,這樣我可以隨時顯示相同的,以
利益相關者。因此,它應該可以瀏覽通過 內聯網 - 最好通過sae網站作爲託管的API。
前端設計人員應該能夠輕鬆修改模板。 因此,我想將它以純HTML格式存儲,以便設計人員不需要通過太多的技術細節來獲得 。
電子郵件模板應易於修改 管理員(未來要求)。在不久的將來,將有 不同的通知短信,屏幕。因此模板是 不同。
基於這些要求,我做了以下:由於我使用MVC
,我創建了一個名爲「靜態」文件夾是 可直接瀏覽(和MVC引擎/ http handler 排除此文件夾執行其MVC活動)。
採用這種方法,我可以很容易地實現第一個要求,我 可以把我的鏈接股份持有人 http://api.aksdfjl.com/static/welcomeemailtemplate.html
每個電子郵件模板給自己的HTML,這樣很容易爲 設計師訪問相同的文件並將其作爲存儲庫文件夾的快捷方式 。 Html具有內聯CSS,並且它完全是一個獨立的HTML - 每個電子郵件。
最後一個主要要求是關於維護這些設計,用戶可以修改相同的設計。那麼我絕對不想通過文件系統來處理。我現在所做的是將這些通知存儲到數據庫中,並將其初始化一次。之後,管理面板上有一個wysiwyg html編輯器,可以讓他們快速預覽以及控制應該發送的內容。
現在,我想,以確保未來的需求好辦,因爲我的公司引入不同的通知不同的方式,如電子郵件,屏幕,短信通知。我決定使用存儲這些答案的模板初始化程序XML來擴展軟件設計。
所有模板的母親稱爲 - MessageTemplates。xml存儲我需要初始化不同類型的模板的不同信息,例如電子郵件,短信,屏幕等。
這是怎樣的代碼看起來像現在。
[HttpGet]
[Route("applications/initializenotificationtemplate")]
public IHttpActionResult InitializeNotificationTemplate()
{
return
InitializeNotificationTemplate(Path.Combine(HostingEnvironment.ApplicationPhysicalPath,
@"Static\InitializeData\MessageTemplates.xml"));
}
[NonAction]
public IHttpActionResult InitializeMailTemplate(string filePath)
{
try
{
_applicationService.InitializeTemplate(filePath);
return Ok("Application Notification templates are initialized.");
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
_applicationService.InitializeTemplate具有以下定義:
public bool InitializeTemplate(string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
throw new ArgumentNullException("File Path");
}
if (!File.Exists(filePath))
{
throw new FileNotFoundException(filePath);
}
var data = _notificationTemplateService.Get();
var exceptionMessages = string.Empty;
if (data != null)
{
var historicalTemplates = data.ToList();
historicalTemplates.ForEach((d) => _notificationTemplateService.Delete(d, out exceptionMessages));
}
XDocument xmlDocument = XDocument.Load(filePath);
IEnumerable<NotificationTemplate> templates = (from template in xmlDocument.Descendants("Template")
select new NotificationTemplate()
{
Title = template.Element("Subject").Value,
Description = template.Element("Body").Value,
Type = (NotificationTypeOptions)Enum.Parse(typeof(NotificationTypeOptions), template.Element("Type").Value, true),
Category = (NotificationCategoryOptions)Enum.Parse(typeof(NotificationCategoryOptions), template.Attribute("category").Value, true),
}).ToList();
foreach (var t in templates)
{
var path = Path.Combine(Path.GetDirectoryName(filePath), Regex.Replace(t.Description, @"\t|\n|\r| ", ""));
if (File.Exists(path))
{
StreamReader reader = new StreamReader(path);
t.Description = reader.ReadToEnd();
}
else
{
t.Description = string.Empty;
}
}
return _notificationTemplateService.InsertRange(templates, out exceptionMessages);
}
這是我的模型看起來像即相同的數據庫模型(代碼第一 - EF方法)。
public class NotificationTemplate : IdentityBase
{
public string Category { get; set; }
public NotificationTypeOptions Type { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public NotificationTemplate()
{
Type = NotificationTypeOptions.Email;
}
}
[Flags]
public enum NotificationTypeOptions
{
Email = 0,
Screen = 1,
}
對於第一次,當我安裝我的應用程序調用初始化安裝我的通知模板到數據庫中,所有其他選項可用,並準備使用API調用。
現在,通過這種方法,我使組織中的每個人都感到高興,並且它有很大的優勢來進一步擴展這一點,以便我也很容易引入新的模板。
我在我的網站中使用了xml文件,它使我能夠顯着地縮放電子郵件模板所支持的功能。 –