2011-07-24 18 views
7

Tengo una aplicación web asp.net, que envía varios correos electrónicos a los usuarios durante el procedimiento de registro. En este momento los tengo en línea con el código, pero me gustaría tenerlos en una ubicación central donde pueda editarlos sin tener que ingresar a VS.Donde almacenar plantillas de correo electrónico

¿Cuál sería el mejor lugar/formato para almacenar estas plantillas HTML?

Respuesta

13

almaceno todos mis plantillas de correo electrónico para mi web-app como ASP.NET MVC Razor Vistas, sino como incrustado recursos en un montaje de luz que pueda crear fácilmente una referencia de cualquier proyecto.

Una plantilla se parece a esto (nótese la localización):

@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> 

} 

entonces tengo una plantilla de "maestro", llamado _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> 

Para enviar realmente el e-mail, me RazorEngine utilizar para la representación:

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); 
} 

El código anterior utiliza mi propia objec EmailDto t. Aquí puede crear fácilmente una instancia [MailMessage][2] directamente y enviarla usando [SmtpClient][3].

Además, para obtener la mejor representación en todos los clientes de correo electrónico, utilizo mi propia biblioteca PreMailer.Net para mover todo el CSS en línea. Lea my blog post here para obtener más información.(Código está en Github)

El GetEmailTemplate hace esto:

/// <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

Eso depende de la frecuencia con la que cambien las plantillas y de quiénes serán modificadas. Por ejemplo:

cambiado por los usuarios de la aplicación, los cambios son urgentes y potencialmente frecuente:

  • Probablemente la mejor almacenan en la base de datos y se carga cada vez que se envía un correo electrónico.

cambiado por los desarrolladores (es decir, usted), los cambios son poco frecuentes y no Jürgen:

  • archivos de texto en el servidor web, cargarlos en la memoria caché y almacenarlos allí, sólo volver a cargarlas cuando el caché de gotas o la aplicación se reinicia.
0

Puede almacenar plantillas de correo electrónico en .html file. A continuación, formatéelo de manera que admita los parámetros que desee incluir. p.ej.

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

Cada vez que se envía un correo electrónico al usuario, que desea establecer la plantilla como usuario específico, para que pueda reemplazar el parámetro en tiempo de ejecución.

1

Recomendaría almacenar las plantillas de correo electrónico en un archivo XML que permitirá la escalabilidad en el futuro agregando atributos a la plantilla de correo y también permitirá una fácil edición.

+0

He utilizado archivos xml en mi sitio web y me ha permitido escalar las características compatibles con las plantillas de correo electrónico de forma espectacular. –

0

Gracias a todos por dar una visión sobre cómo están manejando. He reunido muchos conocimientos desde aquí. Me gustó @MartinHN usando el analizador Razor con el Modelo de datos concreto.

Sin embargo, algo no funcionó muy bien para mí.

Requisito:

  • tengo para almacenar plantillas de correo electrónico de tal manera que puedo mostrar la misma a
    Los interesados ​​en cualquier momento. Por lo tanto, debe estar disponible para navegar a través de la Intranet , preferiblemente a través del sitio web de sae como API alojada.

  • Los diseñadores de front-end deberían poder modificar las plantillas fácilmente. Por lo tanto, quiero almacenarlo en formato HTML sin formato para que el diseñador no tenga que pasar por demasiados detalles técnicos.

  • Las plantillas de correo electrónico deben estar fácilmente disponibles para las modificaciones de los administradores (necesidad futura). En un futuro próximo, habrá notificaciones diferentes para SMS, Pantalla. Por lo tanto, las plantillas son diferentes.

Sobre la base de estos requisitos, hice lo siguiente:

  1. Desde que estaba usando MVC, he creado una carpeta llamada "estático" que es disponibles para ser navegado directamente (y el motor MVC/el controlador http excluye esta carpeta de realizar sus actividades de MVC).

    Con este enfoque podría fácilmente lograr primer requisito y yo podría enviar mi enlace a las partes interesadas como http://api.aksdfjl.com/static/welcomeemailtemplate.html

  2. Cada plantilla de correo electrónico ha dado su propio código HTML, por lo que fue fácil para el diseñador a acceda a lo mismo y remítalo en su repositorio como un atajo a mi carpeta de repositorio. El HTML tiene CSS en línea y es completamente un html independiente - por correo electrónico.

  3. El último requisito principal era mantener estos diseños y el usuario puede modificarlos. Bueno, entonces definitivamente no quiero tratar a través del sistema de archivos. Lo que hice ahora es que estas notificaciones se almacenan en la base de datos y las inicializo una vez. Después de eso, el panel de administración tiene un editor wysiwyg html que puede darles una vista previa rápida y controlar a qué se debe enviar.

Ahora quería asegurarse de que los futuros requisitos son manejados fácilmente y ya que mi empresa fue la introducción de diferentes notificaciones de modo diferente, como el correo electrónico, pantalla, notificaciones por SMS. Decidí ampliar el diseño del software con la ayuda del XML de inicializador de plantilla que almacena estas respuestas.

La madre de toda la plantilla llamada - MessageTemplates.xml almacena información diferente que necesito para inicializar diferentes tipos de plantillas, por ejemplo, correo electrónico, sms, pantalla y demás.

enter image description here

Aquí es cómo el código es el mismo.

[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 tiene la siguiente definición:

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); 
     } 

Así es como mi modelo parece que es igual que el modelo de base de datos (código de primera - enfoque FE).

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, 
    } 

Por primera vez, cuando instalo mi solicitud me llaman inicializar llamada a la API que se instalan mis plantillas de notificación a la base de datos y todas las demás opciones están disponibles y listos para usar.

Ahora con este enfoque hice que todos estuvieran contentos en la organización y tiene una gran fortaleza para extender esto aún más, por lo que es fácil para mí presentar también nuevas plantillas.

Cuestiones relacionadas