# C# / .NET SDK

The official .NET wrapper for the Mailjet API is published on NuGet as **`Mailjet.Api`** and developed on GitHub at [mailjet/mailjet-apiv3-dotnet](https://github.com/mailjet/mailjet-apiv3-dotnet).

Current release: **4.0.1**

## Compatibility

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.3
- `Newtonsoft.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.

## Installation

```
PM> Install-Package Mailjet.Api
```

Or clone the repository directly if you need to build from source.

## Authentication

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"
```

```csharp
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](#sms-api).

## Send your first email

`TransactionalEmailBuilder` builds a strongly typed message, so you get compile-time checking instead of hand-assembled JSON.

```csharp
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}");
    }
}
```

## Client and call configuration

### API versioning

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.

### Base URL

The default base domain is `https://api.mailjet.com`. Override it with the `BaseAdress` property:

```csharp
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`.

### Dependency injection

`MailjetClient` supports `IHttpClientFactory` and can be registered as a typed client:

```csharp
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:

```csharp
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.

### Proxy

Pass a configured `HttpClientHandler` to the constructor:

```csharp
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);
```

## Request examples

Every request is a `MailjetRequest` carrying a `Resource`, an optional `ResourceId`, properties and filters. The full list of resources lives in [`/Mailjet.Client/Resources`](https://github.com/mailjet/mailjet-apiv3-dotnet/tree/master/Mailjet.Client/Resources).

### POST — create an object

```csharp
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()}");
}
```

### POST — endpoints with an action

Action endpoints have their own resource object. `/contact/{id}/managecontactslists` maps to `ContactManagecontactslists`:

```csharp
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);
```

### GET — all objects

```csharp
var request = new MailjetRequest
{
    Resource = Contact.Resource,
};

MailjetResponse response = await client.GetAsync(request);
```

### GET — with filters

```csharp
var request = new MailjetRequest
{
    Resource = Contact.Resource,
}
    .Filter(Contact.IsExcludedFromCampaigns, "false");

MailjetResponse response = await client.GetAsync(request);
```

### GET — a single object

Set `ResourceId` to target one object. Numeric IDs use `ResourceId.Numeric`, and resources that accept an email address (such as `contact`) use `ResourceId.Alphanumeric`:

```csharp
var byId = new MailjetRequest
{
    Resource = Contact.Resource,
    ResourceId = ResourceId.Numeric(contactId)
};

var byEmail = new MailjetRequest
{
    Resource = Contact.Resource,
    ResourceId = ResourceId.Alphanumeric("passenger@example.com")
};
```

### PUT — update an object

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.

```csharp
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);
```

### DELETE — remove an object

A successful `DELETE` returns `204 No Content` with no response body.

```csharp
var request = new MailjetRequest
{
    Resource = Template.Resource,
    ResourceId = ResourceId.Numeric(templateId)
};

MailjetResponse response = await client.DeleteAsync(request);
```

## Response object

`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 API

SMS endpoints authenticate with a bearer token generated in the [SMS section](https://app.mailjet.com/sms) of your account. Pass the token as the only constructor argument:

```csharp
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);
```

## Release notes

| 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 |


## More examples

- [Send with attached files](https://dev.mailjet.com/email/guides/send-api-v31/#send-with-attached-files)
- [GDPR delete contacts](https://dev.mailjet.com/email/guides/contact-management/#gdpr-delete-contacts)
- [All email guides](https://dev.mailjet.com/email/guides/)


## Contribute

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](https://github.com/mailjet/mailjet-apiv3-dotnet). Documentation improvements belong in the [API documentation repo](https://github.com/mailjet/api-documentation).