The official .NET wrapper for the Mailjet API is published on NuGet as Mailjet.Api and developed on GitHub at mailjet/mailjet-apiv3-dotnet.
Current release: 4.0.1
Since 4.0.0 the library targets .NET Standard 2.0, which reduces the dependency surface and removes the security warnings raised by the older .NET Framework target.
| Runtime | Minimum version |
|---|---|
| .NET | 5.0 |
| .NET Core | 2.0 |
| .NET Framework | 4.6.2 |
| Mono | 5.4 |
| Xamarin.iOS | 10.14 |
| Xamarin.Android | 8.0 |
| Universal Windows Platform | 10.0.16299 |
Dependencies:
NETStandard.Library>= 2.0.3Newtonsoft.Json>= 13.0.4
Note: release 4.0.1 fixes a MissingMethodException on PostAsync / PutAsync that occurred when an older Newtonsoft.Json (13.0.0–13.0.3) was resolved at runtime instead of 13.0.4. If you pin Newtonsoft.Json in your project, make sure the runtime actually loads 13.0.4 or later.
PM> Install-Package Mailjet.ApiOr clone the repository directly if you need to build from source.
The Email API authenticates with your API key and secret. Store them outside of your code — for example as machine-level environment variables:
setx -m MJ_APIKEY_PUBLIC "your API key"
setx -m MJ_APIKEY_PRIVATE "your API secret"MailjetClient client = new MailjetClient(
Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"),
Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE"));The SMS API uses a bearer token instead — see SMS API.
TransactionalEmailBuilder builds a strongly typed message, so you get compile-time checking instead of hand-assembled JSON.
using Mailjet.Client;
using Mailjet.Client.TransactionalEmails;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var client = new MailjetClient(
Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"),
Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE"));
var email = new TransactionalEmailBuilder()
.WithFrom(new SendContact("pilot@example.com", "Mailjet Pilot"))
.WithTo(new SendContact("passenger@example.com", "Passenger 1"))
.WithSubject("Your email flight plan!")
.WithHtmlPart("<h3>Dear passenger, welcome to Mailjet!</h3>")
.WithTextPart("Dear passenger, welcome to Mailjet!")
.Build();
var response = await client.SendTransactionalEmailAsync(email);
Console.WriteLine($"Messages accepted: {response.Messages.Length}");
}
}The Mailjet API spans three versions:
| Version | Scope |
|---|---|
v3 | Email API |
v3.1 | Send API v3.1 (latest send version) |
v4 | SMS API, contact delete API |
You do not need to configure this. Since 2.0.0 the client derives the required version from the resource you call.
The default base domain is https://api.mailjet.com. Override it with the BaseAdress property:
var client = new MailjetClient(
Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"),
Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE"))
{
BaseAdress = "https://api.us.mailjet.com",
};Accounts on Mailjet's US architecture must set https://api.us.mailjet.com.
MailjetClient supports IHttpClientFactory and can be registered as a typed client:
services.AddHttpClient<IMailjetClient, MailjetClient>(client =>
{
// sets BaseAddress, MediaType and UserAgent
client.SetDefaultSettings();
client.UseBasicAuthentication("apiKey", "apiSecret");
// or, for the SMS API:
// client.UseBearerAuthentication("access_token");
});Then inject IMailjetClient where you need it:
public class EmailService : IEmailService
{
private readonly IMailjetClient _mailjetClient;
public EmailService(IMailjetClient mailjetClient)
{
_mailjetClient = mailjetClient;
}
}Because sending lives on the client itself (rather than on extension methods), IMailjetClient can be mocked in unit tests.
Pass a configured HttpClientHandler to the constructor:
var proxy = new WebProxy
{
// even for an HTTPS proxy the address starts with http
Address = new Uri("http://51.79.0.0:8080"),
UseDefaultCredentials = false,
// Credentials = new NetworkCredential("user", "password"),
};
var handler = new HttpClientHandler { Proxy = proxy };
var client = new MailjetClient(
Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"),
Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE"),
handler);Every request is a MailjetRequest carrying a Resource, an optional ResourceId, properties and filters. The full list of resources lives in /Mailjet.Client/Resources.
var request = new MailjetRequest
{
Resource = Contact.Resource,
}
.Property(Contact.Email, "passenger@example.com")
.Property(Contact.IsExcludedFromCampaigns, "false")
.Property(Contact.Name, "New Contact");
MailjetResponse response = await client.PostAsync(request);
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"Total: {response.GetTotal()}, Count: {response.GetCount()}");
Console.WriteLine(response.GetData());
}
else
{
Console.WriteLine($"StatusCode: {response.StatusCode}");
Console.WriteLine($"ErrorInfo: {response.GetErrorInfo()}");
Console.WriteLine($"ErrorMessage: {response.GetErrorMessage()}");
}Action endpoints have their own resource object. /contact/{id}/managecontactslists maps to ContactManagecontactslists:
var request = new MailjetRequest
{
Resource = ContactManagecontactslists.Resource,
ResourceId = ResourceId.Numeric(contactId)
}
.Property(ContactManagecontactslists.ContactsLists, new JArray {
new JObject {
{ "ListID", listId1 },
{ "Action", "addnoforce" }
},
new JObject {
{ "ListID", listId2 },
{ "Action", "addforce" }
}
});
MailjetResponse response = await client.PostAsync(request);var request = new MailjetRequest
{
Resource = Contact.Resource,
};
MailjetResponse response = await client.GetAsync(request);var request = new MailjetRequest
{
Resource = Contact.Resource,
}
.Filter(Contact.IsExcludedFromCampaigns, "false");
MailjetResponse response = await client.GetAsync(request);Set ResourceId to target one object. Numeric IDs use ResourceId.Numeric, and resources that accept an email address (such as contact) use ResourceId.Alphanumeric:
var byId = new MailjetRequest
{
Resource = Contact.Resource,
ResourceId = ResourceId.Numeric(contactId)
};
var byEmail = new MailjetRequest
{
Resource = Contact.Resource,
ResourceId = ResourceId.Alphanumeric("passenger@example.com")
};A PUT in the Mailjet API behaves like a PATCH: only the properties you send are updated, everything else is left untouched, and non-mandatory properties can be omitted.
var request = new MailjetRequest
{
Resource = Contactdata.Resource,
ResourceId = ResourceId.Numeric(contactId)
}
.Property(Contactdata.Data, new JArray {
new JObject {
{ "first_name", "John" },
{ "last_name", "Smith" }
}
});
MailjetResponse response = await client.PutAsync(request);A successful DELETE returns 204 No Content with no response body.
var request = new MailjetRequest
{
Resource = Template.Resource,
ResourceId = ResourceId.Numeric(templateId)
};
MailjetResponse response = await client.DeleteAsync(request);GetAsync, PostAsync, PutAsync and DeleteAsync all return a MailjetResponse:
| Member | Returns |
|---|---|
IsSuccessStatusCode | whether the call succeeded |
StatusCode | HTTP status code (200, 400, …) |
GetData() | the Data property of the JSON payload, or the full payload if there is none |
GetTotal() | total number of matching objects |
GetCount() | number of objects returned in this response |
GetErrorInfo() | HTTP reason phrase ("OK", "Bad Request", …) |
GetErrorMessage() | error reason from the API response payload |
SMS endpoints authenticate with a bearer token generated in the SMS section of your account. Pass the token as the only constructor argument:
using Mailjet.Client;
using Mailjet.Client.Resources.SMS;
var client = new MailjetClient(Environment.GetEnvironmentVariable("MJ_API_TOKEN"));
var request = new MailjetRequest
{
Resource = Send.Resource,
}
.Property(Send.From, "MJPilot")
.Property(Send.To, "+33600000000")
.Property(Send.Text, "Have a nice SMS flight with Mailjet!");
MailjetResponse response = await client.PostAsync(request);| Version | Changes |
|---|---|
| 4.0.1 | Fixes MissingMethodException on PostAsync/PutAsync with Newtonsoft.Json 13.0.0–13.0.3 loaded at runtime |
| 4.0.0 | Breaking: target framework moved to .NET Standard 2.0 |
| 3.0.1 | Renames TemplateErrorDelivery to TemplateErrorDeliver; fixes TransactionalEmailBuilder validation; handles a null Messages property |
| 3.0.0 | Breaking: removes extension methods such as SendTransactionalEmailAsync from the extension class |
| 2.1.0 | Bumps Newtonsoft.Json; drops the .NET Framework target; moves SendTransactionalEmailAsync onto the client so it can be mocked |
| 2.0.0 | Adds TransactionalEmailBuilder and typed models, the GDPR contact delete API, automatic version resolution, and a strong-named assembly |
The wrapper is open source. Fork the repository, branch, implement your fix or feature, document it, and open a pull request at mailjet/mailjet-apiv3-dotnet. Documentation improvements belong in the API documentation repo.