[C#/HTML] Formater un email via HTML

Formater un email via HTML [C#/HTML] - C#/.NET managed - Programmation

Marsh Posté le 16-11-2016 à 22:30:06    

Bonjour tout le monde,
 
Je suis en train de créer une application qui permet de vérifier les membres d'un groupe Active Directory, exporter la liste des utilisateurs et leur managers en utilisant un Dictionary<string utilisateur, string manager>.
 
Le but étant ensuite de formater le corps d'un email en y insérant un tableau contenant le nom du manager et les utilisateurs qui sont liés a ce même manager. Chaque manager recevra un email séparément avec un tableau contenant uniquement ses utilisateurs.
 
Mon application est composées de deux fichiers class Program.cs (pour l’exécution du code) et Emails.cs (pour la création de l'email avec le paramètre IsBodyHTML = True; et la configuration SMTP) ainsi que d'un fichier HTML BodyEmailFormat.html.
 
Jusqu'ici j'arrive a exporter la liste des utilisateurs/manager et l’envoyer via email. Sauf que le résultat n'est pas tip top sans aucun formatage. L’idée serait donc de formater le corps de l'email en HTML. Et c'est la que mes problèmes commencent...
 
J'ai réussi a faire un formatage basique en utilisant StringBuilder() de la façon suivante:
 

Code :
  1. StringBuilder myStringBuilder = new StringBuilder();
  2.                 myStringBuilder.AppendFormat("<head>" );
  3.                 myStringBuilder.Append("<style>" );
  4.                 myStringBuilder.Append("table, th {" );
  5.                 myStringBuilder.Append("border: 1px solid black;" );
  6.                 myStringBuilder.Append("border-collapse: collapse;}" );
  7.                 myStringBuilder.Append("</style>" );
  8.                 myStringBuilder.Append("</head>" );
  9.                 myStringBuilder.Append("<table>" );
  10.                 myStringBuilder.Append("<tr>" );
  11.                 myStringBuilder.Append("<th>Manager</th>" );
  12.                 myStringBuilder.Append("</tr>" );
  13.                 myStringBuilder.Append("<tr>" );
  14.                 myStringBuilder.Append("<td>" + man.Key + "</td>" );
  15.                 myStringBuilder.Append("</tr>" );
  16.                 myStringBuilder.Append("<tr>" );
  17.                 myStringBuilder.Append("<th>members</th>" );
  18.                 myStringBuilder.Append("</tr>" );
  19.                 myStringBuilder.Append("<tr>" );
  20.                 myStringBuilder.Append("<td>" + foo.Key + "</td>" );
  21.                 myStringBuilder.Append("</tr>" );
  22.                 myStringBuilder.AppendFormat("</table>" );
  23.                 string bodyEmail = myStringBuilder.ToString();
  24.                 newEmail.sendEmail(bodyEmail);


 
Et le résultat donne ça (Pas ce qu'on fait de mieux en terme d’esthétique  :sweat: ) :
 
http://reho.st/medium/self/5a36ec01ca48d1ad13f82e8e8dd6e890512e766b.png
 
 
Ce que je souhaiterais faire c'est de pouvoir appliquer du CSS a ma table/autres via mon fichier HTML et utiliser ce fichier HTML directement pour le corps du message en y insérant les données. Ce qui me permettrait aussi d'avoir un code plus propre.
 
J'ai vu qu'il était possible d'utiliser la façon suivante affin de remplacer du texte directement dans le fichier HTML:
 

Code :
  1. string bodyEmail = System.IO.File.ReadAllText(@"C:\Users\User\Documents\Visual Studio 2015\Projects\TestEmail\TestEmail\BodyEmailFormat.html" );
  2. string tableStrMem = "<tr><td>"+myValue+"</td></tr>";
  3. bodyEmail.Replace("tableStrMember", tableStrMem);


 
Sauf que cette méthode remplace du texte déjà existant et ne sachant pas a l'avance combien d'utilisateurs le groupe contient, je ne vois pas comment faire pour ajouter x utilisateurs en même temps.
 
Est-ce que vous auriez une idée/conseil pour pouvoir formater mon email en HTML directement via le fichier HTML sans tout écrire via StringBuilder() ?
 
Merci d'avance :jap:
 
Voici le code un peu plus complet:
 

Code :
  1. Dictionary<string, string> myDict = new Dictionary<string, string>();
  2. var groupedDict = myDict.GroupBy(d => d.Value);
  3. foreach (var dictEntries in groupedDict)
  4.             {
  5.                 StringBuilder myStringBuilder= new StringBuilder();
  6.                 myStringBuilder.AppendFormat("<head>" );
  7.                 myStringBuilder.Append("<style>" );
  8.                 myStringBuilder.Append("table, th, td {" );
  9.                 myStringBuilder.Append("border: 1px solid black;" );
  10.                 myStringBuilder.Append("border-collapse: collapse;}" );
  11.                 myStringBuilder.Append("</style>" );
  12.                 myStringBuilder.Append("</head>" );
  13.                 myStringBuilder.Append("<table>" );
  14.                 myStringBuilder.Append("<tr>" );
  15.                 myStringBuilder.Append("<th>Manager</th>" );
  16.                 myStringBuilder.Append("</tr>" );
  17.                 myStringBuilder.Append("<tr>" );
  18.                 myStringBuilder.Append("<td>" + dictEntries.Key + "</td>" );
  19.                 myStringBuilder.Append("</tr>" );
  20.                 myStringBuilder.Append("<tr>" );
  21.                 myStringBuilder.Append("<th>members</th>" );
  22.                 myStringBuilder.Append("</tr>" );
  23.                 myStringBuilder.Append("<tr>" );
  24.                 foreach (var users in dictEntries )
  25.                 {
  26.                     myStringBuilder.Append("<td>" + users.Key + "</td>" );
  27.                     myStringBuilder.Append("</tr>" );
  28.                 }
  29.                 myStringBuilder.Append("</table>" );
  30.                 string bodyEmail = myStringBuilder.ToString();
  31.                 mail.sendEmail(bodyEmail);
  32.             }


Message édité par Slayer_hc le 16-11-2016 à 22:33:25

---------------
BattleTag : Xephon#2299
Reply

Marsh Posté le 16-11-2016 à 22:30:06   

Reply

Marsh Posté le 17-11-2016 à 09:24:22    

Bonjour,

 

Effectivement le StringBuilder est une façon affreuse de faire : c'est illisible et chiant à maintenir. Le premier objectif est donc de séparer le template html dans un fichier BodyEmailFormat.html comme tu as fait.

 

Si tu restes sur du fait maison, tu peux garder les String.Replace mais pour ton tableau, au lieu de remplacer une seule ligne tu injectes le tableau entier d'un coup (l'ensemble des tr) à la place de la balise tableStrMember.
Comme ça tu auras quand même l'essentiel de ton gabarit dans le .html.

 

Si tu veux un truc plus poussé, utilise un vrai moteur de templating, là le choix va dépendre de ce que tu maitrises déjà et du temps que tu veux y consacrer, parce que ton besoin est super basique, donc si tu mets une grosse solution en place ça te prendra du temps qui ne sera pas forcément rentabilisé mais ce sera enrichissant pour toi.

 

Tu y gagnes la possibilité de faire par exemple des vraies boucles, des tests conditionnels (ex : si ligne paire alors fond gris sinon fond blanc, si valeur = "ERREUR" alors afficher en rouge, etc), directement dans le template...

 

Il y a plusieurs solutions :
- Si tu maitrises MVC, tu peux utiliser par exemple https://github.com/Antaris/RazorEngine C'est très puissant vu que ça utilise Razor, mais sans doute un peu lourd et il faut un framework récent

 

- Dans le temps il y avait NVelocity : https://sourceforge.net/projects/nvelocity/ , ça a un peu vieilli mais ça peut être un avantage si ton environnement aussi.
Quick start : https://chrisseroka.wordpress.com/2 [...] nvelocity/
Comme tu peux voir en quelques lignes ça fait déjà bcp de choses et sans embarquer un truc monstrueux derrière. T'as juste à remettre dans un fichier .html distinct le contenu de la variable "template" de l'exemple.

 

- Sans doute plein d'autres moteurs

 

- Une approche différente mais supportée en natif par .Net : utiliser un fichier XLST et un XML. Mais il faut maitriser XSLT et tu n'as plus de vrai .html pour ton template.

Message cité 1 fois
Message édité par TotalRecall le 17-11-2016 à 09:27:22

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 23-11-2016 à 21:47:21    

TotalRecall a écrit :

Bonjour,

 

Effectivement le StringBuilder est une façon affreuse de faire : c'est illisible et chiant à maintenir. Le premier objectif est donc de séparer le template html dans un fichier BodyEmailFormat.html comme tu as fait.

 

Si tu restes sur du fait maison, tu peux garder les String.Replace mais pour ton tableau, au lieu de remplacer une seule ligne tu injectes le tableau entier d'un coup (l'ensemble des tr) à la place de la balise tableStrMember.
Comme ça tu auras quand même l'essentiel de ton gabarit dans le .html.

 

Si tu veux un truc plus poussé, utilise un vrai moteur de templating, là le choix va dépendre de ce que tu maitrises déjà et du temps que tu veux y consacrer, parce que ton besoin est super basique, donc si tu mets une grosse solution en place ça te prendra du temps qui ne sera pas forcément rentabilisé mais ce sera enrichissant pour toi.

 

Tu y gagnes la possibilité de faire par exemple des vraies boucles, des tests conditionnels (ex : si ligne paire alors fond gris sinon fond blanc, si valeur = "ERREUR" alors afficher en rouge, etc), directement dans le template...

 

Il y a plusieurs solutions :
- Si tu maitrises MVC, tu peux utiliser par exemple https://github.com/Antaris/RazorEngine C'est très puissant vu que ça utilise Razor, mais sans doute un peu lourd et il faut un framework récent

 

- Dans le temps il y avait NVelocity : https://sourceforge.net/projects/nvelocity/ , ça a un peu vieilli mais ça peut être un avantage si ton environnement aussi.
Quick start : https://chrisseroka.wordpress.com/2 [...] nvelocity/
Comme tu peux voir en quelques lignes ça fait déjà bcp de choses et sans embarquer un truc monstrueux derrière. T'as juste à remettre dans un fichier .html distinct le contenu de la variable "template" de l'exemple.

 

- Sans doute plein d'autres moteurs

 

- Une approche différente mais supportée en natif par .Net : utiliser un fichier XLST et un XML. Mais il faut maitriser XSLT et tu n'as plus de vrai .html pour ton template.


Salut,

 

Merci pour ta réponse.

 

Du coup j'ai fais comme tu disais en passant directement le tableau dans ma string.

 

Par contre ne connaissant pas MVC, je ne me suis pas lancé dedans... mais de ce que j'en ai lu sur internet ça m'a l'air un peu "overkill" comme solution :D


---------------
BattleTag : Xephon#2299
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed