Dev Life
Envoyer un email avec C# et l’API de Mailgun
.NET est l’un des frameworks web les plus populaires, stables et appréciés que vous pouvez utiliser pour créer des applications web modernes. Les outils fournis par .NET vous aident à démarrer rapidement et à maintenir vos applications sur le long terme. Ils vous permettent de tout créer, des petits microservices ultra-ciblés aux applications web complètes.
Toutefois, chaque application réelle finit par avoir besoin d’envoyer les emails transactionnels (comme la vérification de compte, la réinitialisation de mot de passe, les rapports récapitulatifs quotidiens/mensuels automatisés, etc.). Bien que .NET propose des outils pour vous aider à envoyer des emails, il ne dispose pas de l’infrastructure de production nécessaire pour les envoyer de manière fiable et efficace.
Dans cet article, vous découvrirez comment utiliser l’API HTTP de Mailgun pour envoyer des emails transactionnels depuis vos applications .NET et garantir que votre intégration est fiable, évolutive et sécurisée.
Avant de commencer ce tutoriel, vous aurez besoin des prérequis suivants :
- Des connaissances de base en C# et .NET
- Un IDE moderne comme Visual Studio, JetBrains Rider ou Visual Studio Code
Si vous choisissez de ne pas utiliser Visual Studio et que l’exécution de dotnet –info depuis un terminal échoue, vous devrez alors télécharger et installer le dernier SDK .NET.
Configurer votre compte Mailgun
Commencez par créer un compte Mailgun gratuit. Une fois la connexion établie, créez une nouvelle clé API et conservez-la pour l’utiliser plus tard.
Pour l’envoi d’emails en production, vous devez enregistrer un domaine qui vous appartient auprès de Mailgun. Dans ce tutoriel, vous utiliserez le domaine sandbox fourni par Mailgun.
Créer un nouveau projet C#
Une fois votre compte Mailgun configuré, vous devez créer une nouvelle solution web .NET MVC et configurer des outils supplémentaires pour vous aider à envoyer des emails transactionnels avec .NET.
Ouvrez un terminal et exécutez dotnet new mvc -n MailDemo. Cette commande crée un nouveau projet web .NET utilisant une architecture MVC dans un nouveau dossier /MailDemo. Ensuite, exécutez cd MailDemo pour accéder au nouveau dossier créé.
Une fois dans ce dossier, vous devez ajouter vos valeurs de configuration dans appsettings.json. Ajoutez une nouvelle entrée JSON nommée « Mailgun ». La valeur pour Mailgun:ApiKey est la clé API que vous avez créée dans la section précédente (vous découvrirez comment sécuriser vos clés API plus tard). Mailgun:Domain est le domaine sandbox qui a déjà été créé pour vous.
L’intégralité de votre fichier appsettings.json devrait ressembler à ceci :
{rn "Logging": {rn "LogLevel": {rn "Default": "Information",rn "Microsoft.AspNetCore": "Warning"rn }rn },rn "AllowedHosts": "*",rn "Mailgun": {rn "ApiKey": "<Your API Key>",rn "Domain": "<Your sandbox domain>"rn }rn}
Ensuite, vous devez configurer un HttpClient nommé pour réutiliser facilement les paramètres par défaut. Pour ce faire, ouvrez Program.cs. Le haut du fichier devrait ressembler à ceci :
using System.Net.Http.Headers;rnusing System.Text;rnrnvar builder = WebApplication.CreateBuilder(args);rnrn// Add services to the containerrnbuilder.Services.AddControllersWithViews();rnrn// Set up your named HttpClient for easy reusernbuilder.Services.AddHttpClient("Mailgun", client =>rn{rn // Grab values from the configurationrn var apiKey = builder.Configuration.GetValue<string>("Mailgun:ApiKey");rn var base64Auth = Convert.ToBase64String(Encoding.ASCII.GetBytes($"api:{apiKey}"));rn var domain = builder.Configuration.GetValue<string>("Mailgun:Domain");rnrn // Set default values on the HttpClientrn client.BaseAddress = new Uri($"https://api.mailgun.net/v3/{domain}/messages");rn client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64Auth);rn});rnrnvar app = builder.Build();rn
Puisque vous n’enverrez que des emails, votre HttpClient est configuré avec l’URL complète de l’API HTTP de Mailgun utilisée pour l’envoi d’emails.
À ce stade, tout est prêt pour envoyer votre premier email.
En savoir plus sur les points de terminaison de l’API de Mailgun
Le HttpClient est configuré pour envoyer des requêtes HTTP au point de terminaison https://api.mailgun.net/v3/{domain}/messages. Mailgun propose également d’autres points de terminaison pour vous offrir un outil robuste et complet permettant de gérer et d’envoyer des emails transactionnels :
- Envoyer un email : POST /v3/{domain_name}/messages
- Envoyer un email au format MIME : POST /v3/{domain_name}/messages.mime
- Récupérer un email stocké : GET /v3/domains/{domain_name}/messages/{storage_key}
- Afficher vos domaines : GET /v4/domains
- Créer un nouveau domaine : POST /v4/domains
- Afficher une liste paginée de tous les événements entrants et sortants : GET /v3/{domain_name}/events
- Afficher une liste paginée de tous les rebonds : GET /v3/{domainID}/bounces
Envoyer votre premier email avec l’API de Mailgun
Avant d’envoyer votre premier email transactionnel, assurez-vous que l’adresse email du destinataire que vous utilisez fait partie des destinataires autorisés pour votre domaine sandbox. Dans votre compte Mailgun, affichez vos domaines, ouvrez votre domaine sandbox, puis sur la droite, ajoutez votre adresse email personnelle comme destinataire autorisé :

Ensuite, créez un nouveau fichier dans /Controllers/OrderController.cs et remplacez son contenu par ce qui suit :
using System.Diagnostics;rnusing Microsoft.AspNetCore.Mvc;rnusing MailDemo.Models;rnusing System.Text;rnusing System.Net.Mime;rnrnnamespace MailDemo.Controllers;rnrnpublic class OrderController : Controllerrn{rn private readonly HttpClient _httpClient;rn private readonly IConfiguration _config;rnrn public OrderController(IHttpClientFactory httpClientFactory, IConfiguration config)rn {rn // Get your named HttpClient that is preconfiguredrn this._httpClient = httpClientFactory.CreateClient("Mailgun");rn this._config = config;rn }rnrn public async Task<IActionResult> Confirm()rn {rn using MultipartFormDataContent form = new();rnrn // Local function keeps this code a bit clearerrn void SetFormParam(string key, string value) =>rn form.Add(new StringContent(value, Encoding.UTF8, MediaTypeNames.Text.Plain), key);rnrn SetFormParam("from", $"Test User <postmaster@{this._config.GetValue<string>("Mailgun:Domain")}>");rn SetFormParam("to", "your_authorized_recipient.com");rn SetFormParam("subject", "Hello World!");rn SetFormParam("text", "My first transactional email!");rn SetFormParam("html", @"<html><body><p style=""color:blue;"">My first transactional email!</p></body></html>");rnrn var result = await this._httpClient.PostAsync(string.Empty, form);rnrn if (!result.IsSuccessStatusCode)rn {rn return new JsonResult(await result.Content.ReadAsStringAsync());rn }rnrn return new JsonResult(@"Your order was confirmed. You should get an email soon!");rn }rn}rn
Exécutez dotnet run depuis votre terminal pour démarrer votre application web. Puis, ouvrez un navigateur web et accédez à /order/confirm. Vous devriez recevoir un email dans votre boîte de réception en quelques secondes :

Gérer les réponses et les erreurs
Malheureusement, il arrive que les choses tournent mal. Par exemple, votre clé API peut contenir une faute de frappe, vous n’avez peut-être pas ajouté tous les champs requis à la requête HTTP, ou vous pourriez avoir atteint la limite de taux de Mailgun.
L’échec d’une requête HTTP vers l’API de Mailgun renverra l’un des quatre codes d’erreur HTTP suivants :
- 400 : un problème de formatage est survenu dans la requête.
- 401 : l’authentification a échoué.
- 429 : vous avez atteint la limite de taux de Mailgun.
- 500 : un problème est survenu sur le réseau ou du côté de Mailgun.
Voyons comment vous pouvez gérer certains de ces scénarios d’échec.
Gérer les codes d’erreur 400
Chaque fois que vous recevez un code d’état HTTP 400, cela signifie que votre charge utile ou votre formatage était incorrect. Par exemple, Mailgun répondra avec un code d’état HTTP 400 si un champ obligatoire est manquant.
Dans ces cas-là, vous pouvez adopter une approche générale :
- Lever une exception, car il s’agit d’un scénario d’échec irrécupérable.
- Enregistrer l’exception et les raisons de celle-ci dans les journaux.
Voici à quoi pourrait ressembler le code pour cela :
if (!result.IsSuccessStatusCode)rn{rn var status = (int) result.StatusCode;rnrn if (status == 400)rn {rn var responseContent = await result.Content.ReadAsStringAsync();rn var exception = new BadHttpRequestException("Mailgun 400 HTTP status code");rnrn this._logger.LogError(exception, exception.Message, responseContent);rn throw exception;rn }rn}rn
Vous souhaiterez peut-être également adopter une approche similaire avec le code d’état HTTP 401.
Gérer les codes d’erreur 500
Lorsque vous recevez un code d’état HTTP 500, cela peut signifier qu’un problème est survenu du côté de Mailgun ou qu’un problème de réseau général a été détecté. Dans ces cas-là, vous pouvez envisager plusieurs approches différentes :
- Mettre l’email en file d’attente pour réessayer plus tard.
- Dans le même chemin de code, réessayer après une courte période.
- Employer une technique avancée comme un disjoncteur
Voici à quoi pourrait ressembler une approche de nouvelle tentative de base :
if (!result.IsSuccessStatusCode)rn{rn var status = (int) result.StatusCode;rnrn if (status == 500)rn {rn // Retry the email after 1 second in hopes that the error was transientrnrn await Task.Delay(1000);rn result = await _httpClient.PostAsync(string.Empty, form);rnrn if (!result.IsSuccessStatusCode)rn {rn // Log and throw an exception like you did in the previous examplern }rn }rn}rn
Dans ce scénario, si vous recevez un code d’état 500, vous attendrez une seconde avant de réessayer la requête HTTP. Si la nouvelle requête échoue également, vous enregistrerez et lèverez une exception de la même manière que pour le scénario du code d’état 400.
Pour vous donner une idée de ce à quoi pourrait ressembler le code global, voici un squelette montrant comment votre code pourrait commencer à gérer divers scénarios d’erreur :
if (!result.IsSuccessStatusCode)rn{rn var status = (int)result.StatusCode;rnrn if (status == 400)rn {rn // Log the error and notify the development team that thern // request was not formatted properly.rn }rn else if (status == 401)rn {rn // Log the error and notify the development team that thern // request's authentication failed.rn }rn else if (status == 429)rn {rn // Use a .NET library like Polly to throttle or try this requestrn // again with an exponential back-off, etc.rn }rn elsern {rn // Something went wrong: log the error and apply a distributed rn // error handling technique like a circuit breaker.rn // See https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker for more.rn }rn}rn
Intégration d’emails prête pour la production
À ce stade, vous avez envoyé un email avec .NET et C#, mais pour être prêt pour la production, il y a quelques éléments importants à prendre en compte.
Sécuriser votre clé API
Vous ne pouvez pas stocker votre véritable clé API de production dans le code source. De plus, elle ne doit pas être accessible par quiconque dans des fichiers en texte clair.
Il existe de nombreux outils que vous pouvez utiliser pour sécuriser votre clé API. Chaque fournisseur cloud possède son propre système de gestion de clés qui permet à votre application de récupérer vos secrets de manière sécurisée. Par exemple, Azure Key Vault ou AWS Secrets Manager fonctionnent très bien.
Autres fonctionnalités de niveau production
Mailgun prend également en charge de nombreuses fonctionnalités de niveau production dont vous pourriez avoir besoin, telles que :
- L’ajout de pièces jointes à vos emails
- La possibilité de créer des modèles d’emails réutilisables
- Des fonctionnalités de personnalisation telles que les variables et les balises
- Les en-têtes CC, CCI et reply-to
S’intégrer à l’écosystème .NET
Pour démontrer à quel point il est facile de s’intégrer aux outils prêts pour la production de l’écosystème .NET, n’hésitez pas à utiliser une bibliothèque open source comme Coravel pour améliorer la réutilisabilité et l’expérience développeur de votre solution.
Exécutez dotnet add package coravel.mailer depuis votre terminal en étant dans le dossier MailDemo.
Ensuite, ajoutez l’entrée JSON suivante à votre fichier appsettings.json :
"Coravel": {rn "Mail": {rn "From": {rn "Name": "Test User",rn "Email": "postmaster@<Your sandbox domain>"rn }rn }rn}rnNext, create a class file called MailgunMailer.cs that implements the ICanSendMail interface. You might notice that this is essentially the same logic you originally had in OrderController:rnusing System.Net.Mime;rnusing System.Text;rnusing Coravel.Mailer.Mail;rnrnnamespace MailDemo;rnrnpublic class MailgunMailer : ICanSendMailrn{rn private readonly HttpClient _httpClient;rn private readonly IConfiguration _config;rnrn public MailgunMailer(IHttpClientFactory httpClientFactory, IConfiguration config)rn {rn this._httpClient = httpClientFactory.CreateClient("Mailgun");rn this._config = config;rn }rnrn public async Task SendAsync(MessageBody message, string subject, IEnumerable<MailRecipient> to, MailRecipient from, MailRecipient replyTo, IEnumerable<MailRecipient> cc, IEnumerable<MailRecipient> bcc, IEnumerable<Attachment>? attachments = null, MailRecipient? sender = null)rn {rn using MultipartFormDataContent form = new();rnrn void SetFormParam(string key, string value) =>rn form.Add(new StringContent(value, Encoding.UTF8, MediaTypeNames.Text.Plain), key);rnrn if (from is not null)rn {rn SetFormParam("from", $"{from.Name} <{from.Email}>");rn }rn elsern {rn // This gives you a default "from" field if not defined by the callerrn SetFormParam("from", $"{this._config.GetValue<string>("Coravel:Mail:From:Name")} <{this._config.GetValue<string>("Coravel:Mail:From:Email")}>");rn }rnrn foreach (var recipient in to)rn {rn SetFormParam("to", recipient.Email);rn }rn SetFormParam("subject", subject);rnrn if (message.HasHtmlMessage())rn {rn SetFormParam("html", message.Html);rn }rnrn if (message.HasPlainTextMessage())rn {rn SetFormParam("text", message.Text);rn }rnrn var result = await _httpClient.PostAsync(string.Empty, form);rnrn // Error handling logic...rn }rn}rn
Ensuite, vous devez indiquer à Coravel d’utiliser ce mailer. Dans votre fichier Program.cs, avant que var app = builder.Build() ne soit appelé, ajoutez ce qui suit :
builder.Services.AddScoped<MailDemo.MailgunMailer>();rnbuilder.AddCustomMailer<MailDemo.MailgunMailer>();rnFinally, replace the code for OrderController with the following:rnusing Microsoft.AspNetCore.Mvc;rnusing Coravel.Mailer.Mail.Interfaces;rnusing Coravel.Mailer.Mail;rnrnnamespace MailDemo.Controllers;rnrnpublic class OrderController : Controllerrn{rn private readonly IMailer _mailer;rnrn public OrderController(IMailer mailer)rn {rn this._mailer = mailer;rn }rnrn public async Task<IActionResult> Confirm()rn {rn var mailable = Mailable.AsInline()rn .To("jamesmichaelhickey@gmail.com")rn .Subject("Hello World!")rn .Html(@"<html><body><p style=""color:blue;"">My first transactional email!</p></body></html>")rn .Text("My first transactional email!");rnrn await _mailer.SendAsync(mailable);rnrn return new JsonResult(@"Your order was confirmed. You should get an email soon!");rn }rn}rn
Après une petite configuration initiale, vous remarquerez que la logique d’envoi d’emails depuis le code de votre application est beaucoup plus facile à comprendre et moins verbeuse.
Vous avez également ajouté la prise en charge, via Mailgun et Coravel, de la définition des corps d’emails au format HTML et en texte brut. Mailgun recommande d’envoyer à la fois du HTML et du texte brut ensemble. Il est préférable d’envoyer des emails en plusieurs parties (multipart) contenant à la fois du texte et du HTML, ou uniquement du texte. L’envoi d’emails contenant uniquement du HTML n’est pas bien perçu par les services d’emailing (ESP).
Conclusion
Mailgun offre un moyen simple API HTTP d’envoyer des emails depuis vos solutions .NET de manière efficace et sécurisée. Dans cet article, vous avez appris à intégrer l’API HTTP de Mailgun dans une application web C# et à commencer à ajouter des outils de niveau production ainsi que les fonctionnalités prêtes pour la production de Mailgun.
En utilisant Mailgun et .NET conjointement, vos emails transactionnels peuvent évoluer efficacement grâce à la fonctionnalité async/await de .NET, à l’ensemble de son infrastructure web haute performance, , aux outils supplémentaires de l’écosystème .NET, et à l’API HTTP performante et simple de Mailgun.
Cet article vous a-t-il été utile ? Inscrivez-vous à notre newsletter pour recevoir des mises à jour sur les tutoriels, l’actualité des emails et les conseils de nos experts en emailing.
Comment envoyer un email avec l’API de Mailgun