# Ruby SDK

The official Ruby wrapper for the Mailjet API is published as the **`mailjet`** gem and developed at [mailjet/mailjet-gem](https://github.com/mailjet/mailjet-gem).

## Compatibility

- Ruby **2.2.x** or higher
- The ActionMailer integration targets **Rails >= 5**


## Installation

### RubyGems

```bash
gem install mailjet
```

### Bundler

```ruby
# Gemfile
gem 'mailjet'
```

To track the latest commit on GitHub instead of a released version:

```ruby
# Gemfile
gem 'mailjet', :git => 'https://github.com/mailjet/mailjet-gem.git'
```

Then:

```bash
bundle install
```

## Authentication

Configure the gem in an initializer:

```ruby
# config/initializers/mailjet.rb
Mailjet.configure do |config|
  config.api_key = ENV['MJ_APIKEY_PUBLIC']
  config.secret_key = ENV['MJ_APIKEY_PRIVATE']
  config.default_from = 'my_registered_sender@example.com'
end
```

On Rails you can generate the initializer:

```bash
rails generate mailjet:initializer
```

`default_from` is optional when you send through [Mailjet's SMTP relay with ActionMailer](#send-emails-with-actionmailer).

## Send your first email

```ruby
require 'mailjet'

Mailjet.configure do |config|
  config.api_key = ENV['MJ_APIKEY_PUBLIC']
  config.secret_key = ENV['MJ_APIKEY_PRIVATE']
  config.api_version = 'v3.1'
end

response = Mailjet::Send.create(messages: [{
  'From' => {
    'Email' => 'pilot@example.com',
    'Name' => 'Mailjet Pilot'
  },
  'To' => [
    {
      'Email' => 'passenger@example.com',
      'Name' => 'Passenger 1'
    }
  ],
  'Subject' => 'My first Mailjet Email!',
  'TextPart' => 'Greetings from Mailjet!',
  'HTMLPart' => '<h3>Dear passenger 1, welcome to Mailjet!</h3>'
}])

p response.attributes[:messages]
```

## Call configuration

### API versioning

| Version | Scope |
|  --- | --- |
| `v3` | Email API |
| `v3.1` | Send API v3.1 (latest send version) |
| `v4` | SMS API — **not yet supported by this library** |


Most Email API endpoints sit under `v3`, which is the default. For anything else, set `api_version`:

```ruby
Mailjet.configure do |config|
  config.api_key = ENV['MJ_APIKEY_PUBLIC']
  config.secret_key = ENV['MJ_APIKEY_PRIVATE']
  config.api_version = 'v3.1'
end
```

### Base URL

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

```ruby
Mailjet.configure do |config|
  config.api_key = ENV['MJ_APIKEY_PUBLIC']
  config.secret_key = ENV['MJ_APIKEY_PRIVATE']
  config.api_version = 'v3.1'
  config.end_point = 'https://api.us.mailjet.com'
end
```

Accounts on Mailjet's **US architecture** must set `https://api.us.mailjet.com`.

## Naming conventions

The gem follows Ruby conventions rather than the API's casing:

- **Class names** capitalise only the first letter of the resource name — `listrecipient` becomes `Mailjet::Listrecipient`.
- **Attribute names** are the underscored form of the API property — `IsActive` becomes `is_active`.
- **Action endpoints** join resource and action with an underscore — `/contact/{id}/managecontactslists` becomes `Mailjet::Contact_managecontactslists`.


The full resource list is in [`/lib/mailjet/resources`](https://github.com/mailjet/mailjet-gem/tree/master/lib/mailjet/resources).

## Request examples

### POST — create an object

```ruby
contact = Mailjet::Contact.create(email: 'passenger@example.com')
p contact.attributes['Data']
```

### POST — endpoints with an action

Use `id` to identify the object the action applies to:

```ruby
result = Mailjet::Contact_managecontactslists.create(id: contact_id, contacts_lists: [
  {
    'ListID' => list_id_1,
    'Action' => 'addnoforce'
  },
  {
    'ListID' => list_id_2,
    'Action' => 'addforce'
  }
])

p result.attributes['Data']
```

### GET — all objects

`.all` returns 10 objects by default. Pass `limit: 0` to retrieve everything, up to 1000 objects.

```ruby
recipients = Mailjet::Listrecipient.all(limit: 0)
```

### GET — with filters

Queries accept API filters plus these parameters:

| Parameter | Values | Default |
|  --- | --- | --- |
| `format` | `:json`, `:xml`, `:rawxml`, `:html`, `:csv`, `:phpserialized` | `:json` |
| `limit` | integer | `10` |
| `offset` | integer | `0` |
| `sort` | `[[:property, :asc], [:property, :desc]]` | — |


```ruby
# all contacts in contact list 123
contacts = Mailjet::Contact.all(limit: 0, contacts_list: 123)
```

### GET — a single object

```ruby
contact = Mailjet::Contact.find('passenger@example.com')
p contact.attributes['Data']
```

Two convenience helpers are also available:

```ruby
Mailjet::Contact.count
# => 83

Mailjet::Contact.first
# => #<Mailjet::Contact>
```

### PUT — update an object

A `PUT` in the Mailjet API behaves like a `PATCH`: only the properties you send are updated, and non-mandatory properties can be omitted.

```ruby
recipient = Mailjet::Listrecipient.first
recipient.is_active = false
recipient.save

# or in one call
recipient.update_attributes(is_active: true)
```

### DELETE — remove an object

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

```ruby
recipient = Mailjet::Listrecipient.first
recipient.delete

# or by ID
Mailjet::Listrecipient.delete(123)
```

## Contact management

### Import contacts from CSV

Build the CSV in the format described in [Manage contacts via CSV upload](https://dev.mailjet.com/email/guides/contact-management/#manage-contacts-via-csv-upload), then:

```ruby
Mailjet::ContactslistCsv.send_data(contact_list_id, File.open('contacts.csv', 'r'))
```

### Delete a contact (GDPR)

```ruby
Mailjet::ContactPii.delete(contact_id)
```

## Send emails with ActionMailer

Set the delivery method to Mailjet's SMTP relay:

```ruby
# application.rb, or a config/environments file
config.action_mailer.delivery_method = :mailjet
```

Or send through the [Send API](https://dev.mailjet.com/email/guides/send-api-v31/) instead:

```ruby
# application.rb
config.action_mailer.delivery_method = :mailjet_api
```

### Per-message options

Mailjet-specific options are passed through `delivery_method_options`:

```ruby
class AwesomeMailer < ApplicationMailer
  def awesome_mail(user)
    mail(
      to: user.email,
      delivery_method_options: { api_key: 'your-api-key', secret_key: 'your-secret-key' }
    )
  end
end
```

To use the latest Send API version, set it explicitly:

```ruby
delivery_method_options: { version: 'v3.1' }
```

Supported options:

```ruby
# v3.1
:api_key, :secret_key, :'Priority', :'CustomCampaign', :'DeduplicateCampaign',
:'TemplateLanguage', :'TemplateErrorReporting', :'TemplateErrorDeliver',
:'TemplateID', :'TrackOpens', :'TrackClicks', :'CustomID', :'EventPayload',
:'Variables', :'Headers'

# v3
:recipients, :'mj-prio', :'mj-campaign', :'mj-deduplicatecampaign',
:'mj-templatelanguage', :'mj-templateerrorreporting', :'mj-templateerrordeliver',
:'mj-templateid', :'mj-trackopen', :'mj-trackclick', :'mj-customid',
:'mj-eventpayload', :vars, :headers
```

Alternatively, set the Mailjet SMTP headers directly:

```ruby
headers['X-MJ-CustomID'] = 'order-1001'
headers['X-MJ-EventPayload'] = 'custom payload'
headers['X-MJ-TemplateLanguage'] = 'true'
```

### A minimal mailer

```bash
rails generate mailer UserMailer
```

```ruby
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  def welcome_email
    headers['X-MJ-CustomID'] = 'welcome-email'

    mail(
      from: 'pilot@example.com',
      to: 'passenger@example.com',
      subject: 'This is a nice welcome email'
    )
  end
end
```

```erb
<%# app/views/user_mailer/welcome_email.html.erb %>
Hello world in HTML!
```

```erb
<%# app/views/user_mailer/welcome_email.text.erb %>
Hello world in plain text!
```

```ruby
UserMailer.welcome_email.deliver_now!
```

See the Rails guides on [ActionMailer](https://guides.rubyonrails.org/action_mailer_basics.html) and [`ActionMailer::MessageDelivery`](https://api.rubyonrails.org/classes/ActionMailer/MessageDelivery.html) for the rest.

## Track email delivery

The gem ships a Rack endpoint that receives Mailjet event callbacks (opens, clicks, bounces and so on).

First register your endpoint URL under [account triggers](https://app.mailjet.com/account/triggers), then mount the middleware on the same path:

```ruby
# application.rb
config.middleware.use Mailjet::Rack::Endpoint, '/mailjet/callback' do |params|
  # original_address is set for typofix events
  email = params['email'].presence || params['original_address']

  if user = User.find_by_email(email)
    user.process_email_callback(params)
  else
    Rails.logger.fatal "[Mailjet] User not found: #{email} -- DUMP #{params.inspect}"
  end
end
```

```ruby
# app/models/user.rb
class User < ActiveRecord::Base
  def process_email_callback(params)
    case params['event']
    when 'open'
      # the tracking pixel was loaded — the recipient allowed images
    when 'click'
      # a tracked link was clicked
    when 'bounce'
      # recipient not found — is the address valid?
    when 'spam'
      # the gateway or the recipient flagged the message
    when 'blocked'
      # the gateway or the recipient blocked the sender
    when 'typofix'
      # rerouted from params['original_address'] to params['new_address']
    else
      Rails.logger.fatal "[Mailjet] Unknown event #{params['event']} -- DUMP #{params.inspect}"
    end
  end
end
```

Because this is a Rack application, any Rack-compatible framework works — Sinatra, Padrino and others.

## Testing

Parts of the gem's test suite run against Mailjet's live servers, so valid credentials are required. **Do not use a production account** — some tests are destructive.

```yaml
# GEM_ROOT/config.yml
mailjet:
  api_key: YOUR_API_KEY
  secret_key: YOUR_SECRET_KEY
  default_from: YOUR_REGISTERED_SENDER_EMAIL
```

```bash
bundle
bundle exec rake
```

## Contribute

The wrapper is open source. Fork the repository, branch, implement your fix or feature, add documentation and specs, and open a pull request at [mailjet/mailjet-gem](https://github.com/mailjet/mailjet-gem) — without changes to the gemspec or the version file. Documentation improvements belong in the [API documentation repo](https://github.com/mailjet/api-documentation).