> ## Documentation Index
> Fetch the complete documentation index at: https://www.courier.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has several environments and each has its own keys, which are plain `pk_` strings with no environment prefix. Start with Test.
> Send with `client.send.message`, the default import of the v7 Node SDK. Reference a template by its `nt_` id or its alias.
> A send accepts a bare Elemental element list, but storing content on a template requires the top-level elements wrapped in a channel element.
> Templates and journeys can be built in the Courier app or created through the API. Either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.
> Prefer the Guides tab for how-do-I questions and the Docs tab for how-does-it-behave questions. The API reference lives under /api-reference.

# Send email with Mandrill through Courier

> Connect Mandrill with an API key, import Mandrill templates, and override fields per send.

export const AppLink = ({href, children, name, bare}) => {
  const label = children || name || "Open in Courier";
  if (bare) {
    return <a href={href} target="_blank" rel="noreferrer">{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="app" href={href} target="_blank" rel="noreferrer">
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method" aria-hidden="true">↗</span>
    </a>;
};

export const Doc = ({href, children, name, bare}) => {
  const label = children || name || href;
  if (bare) {
    return <a href={href}>{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="doc" href={href}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">DOC</span>
    </a>;
};

## Prerequisites

* [A Mailchimp Transactional (Mandrill) account](https://mandrillapp.com/)
* A Mandrill API key

## Setup

<Steps>
  <Step title="Create a Mandrill API key">
    In Mailchimp Transactional, follow [the quick start](https://mailchimp.com/developer/transactional/guides/quick-start/) to create an API key.
  </Step>

  <Step title="Configure in Courier">
    Open the <AppLink href="https://app.courier.com/integrations/catalog/mandrill">Mandrill integration</AppLink> in Courier, enter your API key, From Address, and From Name, then save.
  </Step>
</Steps>

Addressing a recipient and sending are the same on every email provider, so they are documented once: <Doc href="/docs/integrations/email/overview#profile-requirements">profile requirements</Doc> and <Doc href="/docs/integrations/email/overview#send-to-a-recipient">send to a recipient</Doc>.

## Overrides

<Doc href="/docs/send/overrides#how-overrides-work">How overrides work</Doc> covers the two levels and which one wins. <Doc href="/docs/integrations/email/overview#channel-overrides">Email channel overrides</Doc> lists the fields every email provider takes.

Use a provider override to change what Courier sends to Mandrill's Messages API. This example adds an attachment.

<CodeGroup>
  ```javascript Node.js highlight={8-25} theme={null}
  const { requestId } = await courier.send.message({
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        email: "sarah@acme-corp.com",
      },
      providers: {
        mandrill: {
          override: {
            body: {
              message: {
                from_email: "support@acme-corp.com",
                subject: "Hi there",
                from_name: "Rod",
                attachments: [
                  {
                    type: "text/plain",
                    name: "myfile.txt",
                    content: "ZXhhbXBsZSBmaWxl",
                  },
                ],
              },
            },
          },
        },
      },
    },
  });
  ```

  ```python Python highlight={8-25} theme={null}
  response = client.send.message(
      message={
          "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          "to": {
              "email": "sarah@acme-corp.com",
          },
          "providers": {
              "mandrill": {
                  "override": {
                      "body": {
                          "message": {
                              "from_email": "support@acme-corp.com",
                              "subject": "Hi there",
                              "from_name": "Rod",
                              "attachments": [
                                  {
                                      "type": "text/plain",
                                      "name": "myfile.txt",
                                      "content": "ZXhhbXBsZSBmaWxl",
                                  },
                              ],
                          },
                      },
                  },
              },
          },
      },
  )
  ```

  ```bash cURL highlight={11-28} wrap theme={null}
  curl -X POST https://api.courier.com/send \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "message": {
        "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
        "to": {
          "email": "sarah@acme-corp.com"
        },
        "providers": {
          "mandrill": {
            "override": {
              "body": {
                "message": {
                  "from_email": "support@acme-corp.com",
                  "subject": "Hi there",
                  "from_name": "Rod",
                  "attachments": [
                    {
                      "type": "text/plain",
                      "name": "myfile.txt",
                      "content": "ZXhhbXBsZSBmaWxl"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }'
  ```

  ```ruby Ruby highlight={8-25} theme={null}
  response = courier.send_.message(
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        email: "sarah@acme-corp.com"
      },
      providers: {
        mandrill: {
          override: {
            body: {
              message: {
                from_email: "support@acme-corp.com",
                subject: "Hi there",
                from_name: "Rod",
                attachments: [
                  {
                    type: "text/plain",
                    name: "myfile.txt",
                    content: "ZXhhbXBsZSBmaWxl"
                  }
                ]
              }
            }
          }
        }
      }
    }
  )
  ```

  ```go Go highlight={10-27} theme={null}
  response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
  	Message: courier.SendMessageParamsMessage{
  		To: courier.SendMessageParamsMessageToUnion{
  			OfUserRecipient: &shared.UserRecipientParam{
  				Email: courier.String("sarah@acme-corp.com"),
  			},
  		},
  		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
  		Providers: shared.MessageProvidersParam{
  			"mandrill": shared.MessageProvidersTypeParam{
  				Override: map[string]any{
  					"body": map[string]any{
  						"message": map[string]any{
  							"from_email": "support@acme-corp.com",
  							"subject": "Hi there",
  							"from_name": "Rod",
  							"attachments": []any{
  								map[string]any{
  									"type": "text/plain",
  									"name": "myfile.txt",
  									"content": "ZXhhbXBsZSBmaWxl",
  								},
  							},
  						},
  					},
  				},
  			},
  		},
  	},
  })
  ```

  ```java Java highlight={6-21} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(UserRecipient.builder().email("sarah@acme-corp.com").build())
          .template("nt_01kx4h2jdafq8bk9aftxak4b40")
          .providers(MessageProviders.builder()
              .putAdditionalProperty("mandrill", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
                      "body", java.util.Map.of(
                          "message", java.util.Map.of(
                              "from_email", "support@acme-corp.com",
                              "subject", "Hi there",
                              "from_name", "Rod",
                              "attachments", java.util.List.of(
                                  java.util.Map.of(
                                      "type", "text/plain",
                                      "name", "myfile.txt",
                                      "content", "ZXhhbXBsZSBmaWxl"
                                  )
                              )
                          )
                      )
                  ))))
              .build())
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={8-25} theme={null}
  $response = $client->send->message(
    message: [
      'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
      'to' => [
        'email' => 'sarah@acme-corp.com',
      ],
      'providers' => [
        'mandrill' => [
          'override' => [
            'body' => [
              'message' => [
                'from_email' => 'support@acme-corp.com',
                'subject' => 'Hi there',
                'from_name' => 'Rod',
                'attachments' => [
                  [
                    'type' => 'text/plain',
                    'name' => 'myfile.txt',
                    'content' => 'ZXhhbXBsZSBmaWxl',
                  ],
                ],
              ],
            ],
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={9-34} theme={null}
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient { Email = "sarah@acme-corp.com" },
          Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          Providers = new Dictionary<string, MessageProvidersType>()
          {
              {
                  "mandrill",
                  new()
                  {
                      Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
                          """
                          {
                            "body": {
                              "message": {
                                "from_email": "support@acme-corp.com",
                                "subject": "Hi there",
                                "from_name": "Rod",
                                "attachments": [
                                  {
                                    "type": "text/plain",
                                    "name": "myfile.txt",
                                    "content": "ZXhhbXBsZSBmaWxl"
                                  }
                                ]
                              }
                            }
                          }
                          """
                      ),
                  }
              },
          },
      },
  };

  var response = await client.Send.Message(parameters);
  ```

  ```bash CLI highlight={5} wrap theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{"email": "sarah@acme-corp.com"}' \
    --message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
    --message.providers '{"mandrill": {"override": {"body": {"message": {"from_email": "support@acme-corp.com", "subject": "Hi there", "from_name": "Rod", "attachments": [{"type": "text/plain", "name": "myfile.txt", "content": "ZXhhbXBsZSBmaWxl"}]}}}}}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send my template to sarah@acme-corp.com with an attachment through Mandrill.
  ```
</CodeGroup>

Overrides are deep-merged into the request. Fields you set replace their counterparts, and everything you leave out is still sent. See the full field list in the [Mandrill Messages API docs](https://mandrillapp.com/api/docs/messages.JSON.html).

## Template import

Import your Mandrill templates from the <AppLink href="https://app.courier.com/integrations/catalog/mandrill">Mandrill configuration page</AppLink>.

<Note>
  Enter your Mandrill credentials on the configuration page to load your saved templates.
</Note>

Templates ready for import appear as checkboxes.

<Frame caption="Template import page">
  <img src="https://mintcdn.com/courier-4f1f25dc/rYENcCCTyPPrDtw0/assets/template-import.webp?fit=max&auto=format&n=rYENcCCTyPPrDtw0&q=85&s=1e8c8f189a398d3ed6b692cf1c180e20" width="1010" height="700" data-path="assets/template-import.webp" />
</Frame>

## Troubleshooting

> Check the <Doc href="/docs/monitor/overview">Courier Logs</Doc> to debug provider errors. For anything else, contact [Courier Support](mailto:support@courier.com).

### Mandrill click tracking not working

Three likely causes:

* Click tracking is off.
* The URL is too long, so Mandrill disabled click tracking.
* The clicks are recorded but not updated in real time.

**Solution**

Check whether click tracking is enabled:

<Steps>
  <Step title="Log into Mandrill">
    Log in to your Mandrill account.
  </Step>

  <Step title="Open Sending defaults">
    Go to Settings, then Sending defaults.
  </Step>

  <Step title="Check the Track Clicks setting">
    Set the "Track Clicks" dropdown to anything other than "No click tracking".
  </Step>
</Steps>

Mandrill tracks opens and clicks in real time, but status updates can lag. Delays run from a few minutes to much longer, such as when their system is under load. <Doc href="/docs/workspaces/overview">Courier has its own link tracking</Doc> for clicks on your Templates.

### Mandrill BCC not working

Mandrill is ignoring the BCC headers.

**Solution**

1. Use the `to` field rather than the `bcc` field, and set `X-MC-PreserveRecipients` to `false`.
2. Or put the BCC address in the `to` field with its `type` set to `bcc`. Add `preserve_recipients: true` under the message section, as below.

```json theme={null}
{
   "to":[
      {
         "email":"sarah@acme-corp.com",
         "name":"Sarah Bennett",
         "type":"to"
      },
      {
         "email":"archive@acme-corp.com",
         "name":"Archive",
         "type":"bcc"
      },
      {
         "email":"ops@acme-corp.com",
         "name":"Ops",
         "type":"bcc"
      }
   ]
}
```

For more on X-MC-PreserveRecipients, see [Mailchimp's SMTP headers documentation](https://mailchimp.com/developer/transactional/docs/smtp-integration/#customize-messages-with-smtp-headers)

### Mandrill CC emails not present

Pass CC fields to Mandrill's API <Doc href="/docs/send/overrides">through the designer</Doc> or through an API override.

As with BCC, set `preserve_recipients` to `true` in the override request. Without it, **CC emails will not be sent**.

**Solution**

```json theme={null}
{
  // ... rest of message definition
   "providers":{
      "mandrill":{
         "override":{
            "body":{
               "message":{
                  "preserve_recipients":true, //This setting must be set to true when passing CC recipients.
                  "attachments":[
                     {
                        "name":"Top Secret",
                        "content":"ZXhhbXBsZSBmaWxl",
                        "type":"application/pdf"
                     }
                  ]
               }
            }
         }
      }
   }
}
```

### Mandrill merge vars not working

Merge variables usually fail because of how they are nested.

**Solution**

Nest the variables inside the `message` struct, as below.

```javascript theme={null}
var message = {
    to: "sarah@acme-corp.com",
    mandrillOptions: {
        template_name: 'template1',
        template_content: [
        ],
        message: {
            "merge": true,
            "merge_language": "handlebars",
            "global_merge_vars": [{
                    "name": "fname",
                    "content": "Sample"
                },
                {
                    "name": "email",
                    "content": "sarah@acme-corp.com"
                }
            ]
        }
    }
};
```

## Provider details

```text theme={null}
mandrill
```

Courier recommends routing to the channel. Naming this key in `routing.channels` instead is supported, and sends through just this provider.

<Card title="Send to a specific provider" icon="bullseye-arrow" href="/docs/send/send-to-a-provider" horizontal arrow="true">
  When that is worth doing, and what you give up: failover, channel priority, and providers you add later.
</Card>
