2011-07-24 186 views
7

我有一個asp.net的Web應用程序,它在註冊過程中向用戶發送幾封電子郵件。現在我讓他們內嵌代碼,但是我想把它們放在一箇中心位置,我可以編輯它們而不必進入VS.哪裏存儲電子郵件模板

什麼是最好的地方/格式來存儲這些HTML模板?

回答

13

我存儲我的所有電子郵件模板,我的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; 
} 
0

這取決於模板改變的頻率以及改變的模式。 E.g:

改變應用程序的用戶來說,變化是迫切的和潛在頻繁:

  • 可能是最好存儲在數據庫中,並且每個電子郵件發送時加載。

開發商(也就是你)的改變而改變是罕見的,而不是urgen:

  • 在Web服務器上的文本文件,它們加載到高速緩存,並將其存儲在那裏,當緩存下降或只有重裝他們應用程序重新啓動。
0

您可以將電子郵件模板存儲在.html file中。然後將其格式化,以支持您想要包含的參數。例如

<head> 
<title></title> 
</head> 
<body> 
    Hello <!--Name--> , 
    This is a test template 
    User Name: <!--UserName--> 
    ............................. 
    ............................. 
</body> 
</html> 

每當您發送電子郵件給用戶,你要設置的模板,用戶特定的,所以你可以在運行時替換參數。

1

我建議將電子郵件模板存儲在XML文件中,這樣可以通過向郵件模板添加屬性來實現將來的可伸縮性,並且還可以輕鬆進行編輯。

+0

我在我的網站中使用了xml文件,它使我能夠顯着地縮放電子郵件模板所支持的功能。 –

0

謝謝大家提供有關他們是如何處理的見解。我從這裏收集了大量的知識。我喜歡@MartinHN使用Razor分析器和具體的數據模型。

但是,它沒有爲我工作得很好。

要求:

  • 我必須存儲電子郵件模板,這樣我可以隨時顯示相同的,以
    利益相關者。因此,它應該可以瀏覽通過 內聯網 - 最好通過sae網站作爲託管的API。

  • 前端設計人員應該能夠輕鬆修改模板。 因此,我想將它以純HTML格式存儲,以便設計人員不需要通過太多的技術細節來獲得 。

  • 電子郵件模板應易於修改 管理員(未來要求)。在不久的將來,將有 不同的通知短信,屏幕。因此模板是 不同。

基於這些要求,我做了以下:由於我使用MVC

  1. ,我創建了一個名爲「靜態」文件夾是 可直接瀏覽(和MVC引擎/ http handler 排除此文件夾執行其MVC活動)。

    採用這種方法,我可以很容易地實現第一個要求,我 可以把我的鏈接股份持有人 http://api.aksdfjl.com/static/welcomeemailtemplate.html

  2. 每個電子郵件模板給自己的HTML,這樣很容易爲 設計師訪問相同的文件並將其作爲存儲庫文件夾的快捷方式 。 Html具有內聯CSS,並且它完全是一個獨立的HTML - 每個電子郵件。

  3. 最後一個主要要求是關於維護這些設計,用戶可以修改相同的設計。那麼我絕對不想通過文件系統來處理。我現在所做的是將這些通知存儲到數據庫中,並將其初始化一次。之後,管理面板上有一個wysiwyg html編輯器,可以讓他們快速預覽以及控制應該發送的內容。

現在,我想,以確保未來的需求好辦,因爲我的公司引入不同的通知不同的方式,如電子郵件,屏幕,短信通知。我決定使用存儲這些答案的模板初始化程序XML來擴展軟件設計。

所有模板的母親稱爲 - MessageTemplates。xml存儲我需要初始化不同類型的模板的不同信息,例如電子郵件,短信,屏幕等。

enter image description here

這是怎樣的代碼看起來像現在。

[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​​調用。

現在,通過這種方法,我使組織中的每個人都感到高興,並且它有很大的優勢來進一步擴展這一點,以便我也很容易引入新的模板。