jeudi 1 avril 2010

Asp.net 3.5 - Helper de Manipulation de template de Mail

Ce dont nous allons avoir besoins :
-          Un Objet pour stocker un mail
-          Un Objet pour stocker un template de mail
-          Une classe HelperMail qui va faire toute les manipulations sur les templates de mail
-          Un Controller Business pour finaliser l'envoie de mail, ajouter en sgbd avant envoie, et tout ce que voulais (non traité ici et visible dans le code)
Les explications seront présentées dans les commentaires.
Le principe de base utilise les HashTable. On peut facilement associer un token dans un template à une clef dans une HashTable pour en récuperer la valeur. La seul complication viendra des « Boucles de Token », c'est-à-dire des emplacements ou l’on va remplacer en boucle des Tokens. Une hashtable pouvant contenir toute sorte d'objet, on peut dans la même liste avoir des associations "Clef/String" ou "Clef/List<Hashtable>". List<Hashtable> sur lequel on bouclera pour afficher tous les paramètres voulus.
 
SendMail : Objet de stockage de Mail
    /// <summary>
    /// Objet de stockage des informations d'un mail
    /// </summary>
    public class SendMail
    {
        private string  m_SendMail_From;
        private string m_SendMail_To;
        private string m_SendMail_Copy;
        private string m_SendMail_Subject;
        private string m_SendMail_Body;
 
        /// <summary>
        /// Email expediteur
        /// </summary>
        public string SendMail_From
        {
            get { return m_SendMail_From; }
            set { m_SendMail_From = value; }
        }
       
        /// <summary>
        /// Email destinataire
        /// </summary>
        public string SendMail_To
        {
            get { return m_SendMail_To; }
            set { m_SendMail_To = value; }
        }
 
        /// <summary>
        /// Email des destinataires en copie : Séparation par ;
        /// </summary>
        public string SendMail_Copy
        {
            get { return m_SendMail_Copy; }
            set { m_SendMail_Copy = value; }
        }     
 
        /// <summary>
        /// Sujet du message
        /// </summary>
        public string SendMail_Subject
        {
            get { return m_SendMail_Subject; }
            set { m_SendMail_Subject = value; }
        }
       
        /// <summary>
        /// Corps du message
        /// </summary>
        public string SendMail_Body
        {
            get { return m_SendMail_Body; }
            set { m_SendMail_Body = value; }
        }
 
     
           
    }
TemplateMail : Objet de stockage de template de mail
/// <summary>
    /// Objet de gestion des templates de mail
    /// </summary>
    public class TemplateMail
    {
        private int m_Id;
        private string m_TemplateName;
        private string m_Body;
        private string m_Subject;
 
        /// <summary>
        /// Identifiant du mail
        /// </summary>
        public int Id
        {
            get { return m_Id; }
            set { m_Id = value; }
        }
 
        /// <summary>
        /// Nom du template
        /// </summary>
        public string TemplateName
        {
            get { return m_TemplateName; }
            set { m_TemplateName = value; }
        }
 
        /// <summary>
        /// Corps du message, contient en général les tokens à remplacer
        /// </summary>
        public string Body
        {
            get { return m_Body; }
            set { m_Body = value; }
        }    
 
        /// <summary>
        /// Sujet du mail
        /// </summary>
        public string Subject
        {
            get { return m_Subject; }
            set { m_Subject = value; }
        }
 
    }
HelperMail
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Collections;
using Business.Controller; // Votre Couche Business
 
 
namespace Helper
{
    /// <summary>
    /// Classe de gestion des mails
    /// </summary>
    public class HelperMail
    {
           #region public
       
        /// <summary>
        /// Helper d'envoie de mail
        /// </summary>
        /// <param name="pMail">Objet de mail ne contenant ni body ni sujet</param>
        /// <param name="pTemplateName">Nom du template</param>
        /// <param name="Params">Paramètres dans une liste de string association NomParam/Valeur</param>
        /// <remarks>
        /// Explication de la méthode :
        /// La HashTable Params contient deux types d'objets
        ///  - Des associations Clés / objet de type : string
        ///  - Des accociations Clés / objet de type : List de Hashtable
        ///  Explication du principe de création de mail à partir de template :
        ///  Un template de mail contient des tokens : #params# , @LoopName@ , &LoopParams&
        ///  **Les tokens #params# sont remplacés suivant le principe :
        ///     - cle = params ex : #UserName# aura pour cle UserName
        ///     - Value = Un string
        ///  Exemple :
        ///  " Salutations distinguées #USER_Name# "
        ///  Cherchera la cle USER_Name : Params["USER_Name"] et remplacera #USER_Name# par la valeur associé à la clef
        ///  **Les tokens @LoopName@ sont remplacés par le principe : LoopName = Cle
        ///     - Cle = LoopName ex : #LoopName# aura pour cle LoopName
        ///     - Value = Une list de HastTable. Chaque HashTable contenant une association cle / valeur(string) ex : &LoopParams& aura pour cle LoopParams
        ///   Présentation d'une loop :
        ///     @MYLOOPPANEL@  
        ///     Affichage en boucle d'une donnée 1 : &MyData1&
        ///     Affichage en boucle d'une donnée 2 : &MyData2&
        ///     @ENDMYLOOPPANEL@  
        ///   On récupere la liste des hashtable possédant les clefs dans Params[MYLOOPPANEL].
        ///   Cette liste contient des hashtable contenant les valeurs de &MyData1& et &MyData2&
        ///   Exemple de création du paramètre : Hashtable Params
        ///   Hashtable Params = new Hashtable();
        ///   Params.Add("USER_Name","DOE John");
        ///  
        ///   Hashtable l_hashLoop1 = new Hashtable();
        ///   l_hashLoop1.Add("MyData1", "Donnée 1");
           ///   l_hashLoop1.Add("MyData2", "Donnée 2");
        ///  
        ///   Hashtable l_hashLoop2 = new Hashtable();
        ///   l_hashLoop2.Add("MyData1", "Donnée 1");
           ///   l_hashLoop2.Add("MyData2", "Donnée 2");
        ///  
        ///   List<Hashtable> l_lTmp = new List<Hashtable>();
        ///   l_lTmp.Add(l_hashLoop1);
        ///   l_lTmp.Add(l_hashLoop2);
        ///  
        ///   Params .Add("LOOPPANEL", l_l);   
        /// </remarks>
        public void sendmail(Signalisation.Objects.Objects.SendMail pMail ,string pTemplateName,Hashtable Params)
        {
 
            Signalisation.Objects.Objects.TemplateMail l_Template = getTemplate(pTemplateName);
            pMail.SendMail_Subject = l_Template.Subject;
            pMail.SendMail_Body = ReplaceParams(l_Template.Body, Params);
            //Controller.SendMail().sendMail(pMail);
        }
 
        #endregion
 
        #region private
 
        #region GetTemplate from BDD
        /// <summary>
        /// Récupére un template de mail en base en fonction de son nom
        /// </summary>
        /// <param name="TemplateName"></param>
        /// <returns></returns>
        private Signalisation.Objects.Objects.TemplateMail getTemplate(string TemplateName)
        {
 
           return  Controller.TemplateMail().Find(TemplateName);
 
        }
        #endregion
 
        #region ReplaceParams from Template
        /// <summary>
        /// Remplace les params d'un template
        /// </summary>
        /// <param name="pTemplate">Template</param>
        /// <param name="Params">Paramètres dans une liste de string association NomParam/Valeur</param>
        /// <returns></returns>
        private string ReplaceParams(string pTemplate, Hashtable Params)
        {
            string l_TempRes = ReplaceSimpleParams(pTemplate, Params);
            return ReplaceLoopParams(l_TempRes, Params);
        }
 
        /// <summary>
        /// Remplace les paramètres simple de type #Param#
        /// </summary>
        /// <param name="pTemplate"></param>
        /// <param name="Params">Paramètres dans une liste de string association NomParam/Valeur</param>
        /// <returns></returns>
        private string ReplaceSimpleParams(string pTemplate, Hashtable Params, String SplitChar)
        {
            StringCollection resultList = new StringCollection();
            try
            {
                Regex regexObj = new Regex(string.Format(@"{0}(\w*){0}", SplitChar));
                Match matchResult = regexObj.Match(pTemplate);
                while (matchResult.Success)
                {
                    resultList.Add(matchResult.Groups[1].Value);
                    matchResult = matchResult.NextMatch();
                }
            }
            catch (ArgumentException ex)
            {
                // Syntax error in the regular expression
            }
 
            //Remplacement des valeurs
            foreach (string val in resultList)
            {
                try
                {
                    pTemplate = pTemplate.Replace(string.Format("{0}{1}{0}", SplitChar,val), Params[val].ToString());
                }
                catch { }
            }
 
            return pTemplate;
        }
 
        /// <summary>
        /// Remplace les paramètres simple de type #Param#
        /// </summary>
        /// <param name="pTemplate"></param>
        /// <param name="Params">Paramètres dans une liste de string association NomParam/Valeur</param>
        /// <returns></returns>
        private string ReplaceSimpleParams(string pTemplate, Hashtable Params)
        {
           return ReplaceSimpleParams(pTemplate, Params, "#");           
        }
 
        /// <summary>
        /// Remplace les paramètres de type @Loop@
        /// </summary>
        /// <param name="pTemplate"></param>
        /// <param name="Params">Paramètres dans une liste de string association NomParam/Valeur</param>
        /// <returns></returns>
        private string ReplaceLoopParams(string pTemplate, Hashtable Params)
        {
            StringCollection resultListLoopName = new StringCollection();
            StringCollection resultListContent = new StringCollection();
            StringCollection resultListFullLoop = new StringCollection();
            try
            {
                Regex regexObj = new Regex(@"(?<FullLoop>@(?<LoopName>\w+)@(?<Content>.*)@END\2@)", RegexOptions.Singleline);
                Match matchResult = regexObj.Match(pTemplate);
                while (matchResult.Success)
                {
                    resultListLoopName.Add(matchResult.Groups["LoopName"].Value);
                    resultListContent.Add(matchResult.Groups["Content"].Value);
                    resultListFullLoop.Add(matchResult.Groups["FullLoop"].Value);
                    matchResult = matchResult.NextMatch();
                }
            }
            catch (ArgumentException ex)
            {
                // Syntax error in the regular expression
            }
 
            //Fabrication des boucles
 
            //Test présences données
            if(resultListLoopName.Count > 0 && resultListContent.Count  > 0 )
            {
                //Boucle de remplacement
                int l_count = resultListLoopName.Count;
                for(int i =0; i<l_count;i++)
                {
                    //Recupere la liste des hashtable contenant les valeurs à boucler
                    List<Hashtable> ToLoop = (List<Hashtable>)Params[resultListLoopName[i]];
                    if (ToLoop.Count > 0)
                    {
                        //Stockage des futurs resultats
                        string l_ResLoop = string.Empty;
                        //Pour chaque lot de parametres on fera un nouveau tour de boucle
                        foreach (Hashtable HashLoop in ToLoop)
                        {
                            //Génération d'une iteration de la boucle
                            l_ResLoop += ReplaceSimpleParams(resultListContent[i], HashLoop,"&");
                        }
 
                        //Remplacement de la boucle totale par le contenu de la boucle généré
                        pTemplate = pTemplate.Replace(resultListFullLoop[i], l_ResLoop);
                    }
                }
 
            }
            return pTemplate;
        }
        #endregion
        #endregion
    }
}

Aucun commentaire:

Enregistrer un commentaire