Loupe

Injecter des images dans ses mails SendGrid avec un MailService dans une API .NET Core

Bonjour à tous ! 

Je vais vous montrer aujourd'hui comment mettre des images dans ses mails SendGrid en les ajoutant à l'objet Mail (SendGrid.Helpers.Mail). 

Préparer son template

Si vous avez votre template de mail, tant mieux, sinon vous en trouverez facilement sur le net.

Dans toutes vos balises <img /> vous allez renseigner la source de l'image avec un "identifiant" du style: 

<img src="cid:{logo}" />

"cid" c'est pour contentId, vous verrez par la suite que nous allons créer ce contentId puis l'injecter dans le template !

Avant toute chose, vous allez indiquer à votre assembly que template.html est une ressource embarquée (cela permet de l'embarquer dans la build et donc de l'utiliser). Pour ce faire, cliquons droit sur "template.html" > Properties > Build Action = Embedded resource. Maintenant notre ressource est embarqué dans notre dll donc accessible après build ! 

Je vous invite à consulter cette page pour mieux comprendre les builds actions: https://docs.microsoft.com/fr-fr/visualstudio/ide/build-actions?view=vs-2019

Annotation 2020-03-04 140017.png

Vous allez faire exactement pareil pour toutes vos images, d'ailleurs ! 

Dans votre class MailService, vous allez avoir une méthode CreateEmailBody() qui va ressembler à ça :

public string CreateEmailBody()
        {
            var assembly = this.GetType().Assembly;
            var resourceName = "VJ.MonApp.Services.MailTemplate.template.html";

            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

Ici, on récupère le stream de notre ressource embarqué dans la dll, on le lit puis renvoie le résultat sous forme de string.

Maintenant, vous avez une méthode qui va chercher le fichier template.html et le transformer en string. On va pouvoir remplacer les identifiants que l'on a définis dans notre template grâce à la méthode String.Replace().

Vous allez maintenant créer une seconde méthode, toujours dans votre MailService, qui aura un nom du style "EmbedImageToBody".

public AlternateView EmbedLogoToBody(string htmlContent) {
            var assembly = this.GetType().Assembly;
            var resourceName = "VJ.MonApp.Services.MailTemplate.img.logo.png";
            Stream stream = assembly.GetManifestResourceStream(resourceName);

            LinkedResource logo = new LinkedResource(stream, System.Net.Mime.MediaTypeNames.Image.Jpeg);
            logo.ContentId = Guid.NewGuid().ToString();

            htmlContent = htmlContent.Replace("{logo}", logo.ContentId);

            AlternateView alternateView = AlternateView.CreateAlternateViewFromString(htmlContent, null, System.Net.Mime.MediaTypeNames.Text.Html);
            alternateView.LinkedResources.Add(logo);
            return alternateView;
        }

Ok ! Maintenant dans cette méthode, on prend notre htmlContent (que l'on vient de créer grâce à la méthode juste avant) et on va y injecter notre image. Pour ce faire, on va lire le stream de notre ressource que l'on a embarquée dans notre dll, on créé une LinkedResource de type Jpeg, on assigne un Guid à son ContentId et on va remplacer notre identifiant "{logo}" par ce ContentId. Maintenant que notre "htmlContent" contient le lien vers notre image,  on créé une AlternateView de type Html et on y ajoute comme LinkedResources notre logo !

Intégrer son template dans le corps du mail 

On est prêt pour envoyer notre mail ! Dans notre MailService.cs on va rajouter une fonction SendMailAsync() qui ressemblera à ça: 

public async Task SendMailAsync(string email, string htmlContent)
        {
            try
            {
                var client = new SmtpClient(host: _settings.Value.Host, _settings.Value.Port);
                client.Credentials = new System.Net.NetworkCredential(_settings.Value.Username, _settings.Value.Password);
                var msg = new MailMessage()
                {
                    IsBodyHtml = true,
                    From = new MailAddress(_settings.Value.EmailFrom),
                    Subject = _settings.Value.Subject
                   
                };
                msg.To.Add(new MailAddress(email));

                msg.AlternateViews.Add(EmbedLogoToBody(htmlContent));

                await client.SendMailAsync(msg);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

Et voilà ! Vous avez plus qu'à essayer et savourer votre victoire. 

Si jamais vous avez la moindre question, n'hésitez pas à la poser dans l'espace commentaire ci-dessous ! 

Happy Coding comme on dit ! 

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus