Mailgun-Compatible Messages API
- Table of Contents
- Overview
- Authentication
- Requests and Responses
- Limits
- Send a Message
- The Message-ID
- Tags and Variables
- Batch Sending
- Unsupported Parameters
- Differences from Mailgun
This feature is only available on GreenArrow CloudMTA.
Contact us if you need support for a field or an API that is not listed here.
Overview
The Mailgun-compatible Messages API lets software that was written for Mailgun’s message sending API send email through GreenArrow. GreenArrow translates each request and submits the message to the HTTP Submission API.
These endpoints are available:
| Endpoint | Purpose |
|---|---|
POST /v3/{domain_name}/messages |
Send a message that GreenArrow builds from the parameters |
POST /v3/{domain_name}/messages.mime |
Send a MIME message that you build |
This page documents /messages and the rules that apply to both endpoints. The Mailgun-Compatible MIME Messages API page documents what is different for /messages.mime.
A request that is not a batch sends one message to all of its recipients. A batch request (with recipient-variables or an X-Mailgun-Recipient-Variables header) sends one message to each to recipient, with the variables of that recipient. See Batch Sending.
Send each request to the hostname of the Mailgun compatibility API of your GreenArrow CloudMTA. The examples on this page use mg.api.example.com.
Read Differences from Mailgun before you move an integration from Mailgun. Some requests that Mailgun accepts are refused here.
The Mail Class
Each message uses the Mail Class that the mailclass option of the compatibility_api_mailgun directive names. The bounce address of this Mail Class is the envelope sender (MAIL FROM) of each message. The other settings of the Mail Class apply too, for example its click and open tracking settings when the request does not have o:tracking, o:tracking-clicks or o:tracking-opens.
GreenArrow records the IP address of your client as the source address of the message. When the http_submission_api_received_header directive is show_source, the Received header of the message shows it.
Authentication
Authenticate with HTTP Basic authentication. The username is api, and the password is a GreenArrow API key.
curl -s --user "api:$API_KEY" \
https://mg.api.example.com/v3/mail.example.com/messages \
-F from='[email protected]' \
-F to='[email protected]' \
-F subject='Hello' \
-F text='Hello!'
GreenArrow checks the credentials first: before it reads the request body, and before it checks a parameter. A request with no credentials, with a username other than api, or with a key that is not valid gets the 401 response, also when the request has other errors.
The 401 response has the plain-text body Forbidden, with Content-Type: text/plain; charset=utf-8 and the header WWW-Authenticate: Basic realm="MG API", as on Mailgun.
Requests and Responses
Request format
- Send the parameters in a
multipart/form-databody (curl -F) or in anapplication/x-www-form-urlencodedbody. A request with an attachment must usemultipart/form-data. A body of another type is refused with400. - The body can be compressed with gzip. Set the header
Content-Encoding: gzip. - GreenArrow does not read the query string. Send each parameter in the body.
- To give a parameter more than one value (for example two
toaddresses), send the parameter one time for each value. -
attachmentandinlinemust be file parts of amultipart/form-databody. Each other parameter must be a plain value. A plain value ofattachmentorinline, and a file part of another parameter (for examplehtmlsent as a file), is refused with400. - The fixed values of the options (
yes,no,true,falseandhtmlonly) are accepted in any letter case, for exampleYESorHtmlOnly. - A parameter that this page does not list is refused with
400. See Unsupported Parameters.
The domain in the path
{domain_name} is the sending domain. The domain of the from address must be equal to it.
A {domain_name} that is not a valid domain name, or that has no dot (for example localhost or ip_pools), gets the 401 response. Mailgun gives the same answer for a domain that is not a domain of the account.
The answers for a domain that is not ready to send depend on how your GreenArrow CloudMTA uses Sending Domains:
- When GreenArrow uses Sending Domains, a Sending Domain whose DNS records are verified and whose sending is disabled (
sending_enabledisfalse) gets the403response. - When GreenArrow also requires that the
Fromdomain of each message is a verified Sending Domain, a{domain_name}that is not a Sending Domain gets the401response. A Sending Domain whose DNS records are not verified also gets the401response.
When GreenArrow does not use Sending Domains in these ways, it accepts a message from a domain that is not a Sending Domain.
Success
A message that GreenArrow queued gets a 200 response with Content-Type: application/json; charset=utf-8:
{"id": "<[email protected]>", "message": "Queued. Thank you."}
id is the Message-ID of the message. See The Message-ID.
Errors
The body of an error response is JSON with one field, message, except the plain-text 401 response:
{"message": "from parameter is missing"}
| Status | Meaning |
|---|---|
400 |
The request is not valid, or it asks for something that GreenArrow does not support. See Error Messages. |
401 |
The credentials are missing or not valid, or {domain_name} is not a domain that can send. The body is Forbidden. See Authentication. |
403 |
The Sending Domain of {domain_name} is verified, but its sending is disabled. The message is Mailgun’s text for a domain that is not verified: Domain {domain_name} is not allowed to send: The domain is unverified and requires DNS configuration. Log in to your control panel to view required DNS records.
|
413 |
The request body is larger than 26,214,400 bytes after decompression. See Limits. |
429 |
GreenArrow is busy. It could not inject the message within 30 seconds, because message injection is throttled. The message was not queued. Send it again after 60 seconds. |
500 |
GreenArrow could not handle the request. The message is GreenArrow backend error. Contact GreenArrow support.
|
GreenArrow waits up to 60 seconds for the HTTP Submission API to queue the message. When this time passes, the answer is the 500 response, and the message can be queued or not.
When a request has more than one error, the response gives one of them.
Error Messages
These are the messages of the 400, 413 and 429 responses. When GreenArrow and Mailgun refuse a request for the same reason, the message is Mailgun’s. {name} is the name of the parameter as sent, and {value} is its value.
| Case | Message |
|---|---|
from is missing. |
from parameter is missing |
to is missing. |
to parameter is missing |
subject is missing. |
subject parameter is missing |
The request has no text, html or amp-html. |
Need at least one of 'text', 'html', 'amp-html' or 'template' parameters specified |
amp-html without text or html. |
amp-html parameter needs text or html |
from is not one address, or a to, cc or bcc value is not an address list. |
{name} parameter is not a valid address. please check documentation |
from is sent more than one time. |
from parameter must have one value |
The domain of from is not {domain_name}. |
from parameter must have the domain {domain_name} |
| A name is an encoded-word in a charset that GreenArrow does not decode. | {name} parameter has an unknown charset: {charset} |
| More than 1,000 recipients. | too many recipients: the limit is 1000 |
The values of the o:, h: and v: parameters are more than 16,384 bytes. |
Send options (parameters starting with o:, h:, or v:) are limited to 16 kB total |
| An unknown parameter, a template parameter, or a parameter that is not supported. | {name} parameter is not supported |
An option that is not supported, with a value other than no or false. o:dkim with no or false. |
{name} parameter value {value} is not supported |
recipient-variables is not a JSON object or null. |
'recipient-variables' parameter is not a valid JSON |
h:X-Mailgun-Recipient-Variables, or the X-Mailgun-Recipient-Variables header of the /messages.mime document, is not a JSON object or null. |
X-Mailgun-Recipient-Variables is not a valid JSON |
A batch with cc or bcc. |
cc and bcc parameters cannot be used with recipient-variables |
A batch with a line break (CR or LF) in a recipient variable of a to address. |
recipient-variables has a line break in a value for {address} |
| A batch in which the Click Tracking ID of a recipient is more than 300 characters. | o:tag and v: values are limited to 300 characters in the Click Tracking ID, got {length} for {address} |
A /messages.mime batch whose document has a Message-ID that is not a valid msg-id in angle brackets, such as <[email protected]>. |
message parameter has a Message-ID that is not a valid Message-ID |
An option value that is not valid, for example o:tracking=maybe. |
{name} parameter has an invalid value: {value} |
o:deliverytime is not a date. |
{value} is not an RFC-2822 compliant date |
o:deliverytime is more than 7 days after the request. |
scheduled delivery time must not be farther than 168h0m0s from now |
o:deliver-within is less than 5 minutes or more than 24 hours. {duration} is the value in the form 4m0s. |
invalid deliver-within period: want=[5m0s;24h0m0s], got={duration} |
o:deliver-within has another format. |
invalid deliver-within format |
o:secondary-dkim or o:secondary-dkim-public is not signing_domain/selector. |
{name} parameter must be signing_domain/selector |
o:secondary-dkim-public without o:secondary-dkim. |
o:secondary-dkim-public parameter needs o:secondary-dkim |
o:sending-ip is not an IP address of this system. |
o:sending-ip parameter is not an IP address of this system |
o:sending-ip with o:sending-ip-pool. |
o:sending-ip and o:sending-ip-pool parameters cannot be used together |
o:sending-ip-pool is not the pool ID of a Route. |
o:sending-ip-pool parameter is not a valid pool ID |
An h: header that is refused, that is sent more than one time, or whose name is not valid. |
{name} parameter is not allowed |
A line break (CR or LF) in an h: value, or in from, to or cc. A fold in h:X-Mailgun-Recipient-Variables is not a line break. |
{name} parameter has a line break |
| A header that is too long for a line and has no space where it can be folded. | {name} parameter is too long for a header line |
h:Message-ID is not a valid Message-ID. |
h:Message-ID parameter is not a valid Message-ID |
A control character in an o:tag value, in a v: value, or in a string of h:X-Mailgun-Variables. |
{name} parameter has a control character |
| The Click Tracking ID is more than 300 characters. | o:tag and v: values are limited to 300 characters in the Click Tracking ID, got {length} |
| A file part where a plain value is expected. | {name} parameter must not be a file |
A plain value of attachment or inline. |
{name} parameter is not a file |
An attachment or inline filename that GreenArrow cannot use. |
{name} parameter has an invalid filename: {filename} |
An attachment or inline file that is empty, or that is the one character 0. |
{name} parameter has an empty file: {filename} |
| A body that cannot be decoded, for example a body that is not valid gzip or form data. | invalid request body |
A body larger than 26,214,400 bytes after decompression (413). |
request body is too large: the limit is 26214400 bytes |
GreenArrow could not inject the message within 30 seconds (429). |
Too many requests, please try again after 60 seconds |
The /messages.mime endpoint has more messages for its message parameter. See The Document.
The HTTP Submission API also checks each message. When it refuses a message, the response is a 400 with the message of the HTTP Submission API.
Limits
| Limit | Value | When the request is over the limit |
|---|---|---|
| Request body | 25 MB (26,214,400 bytes), after decompression. The form encoding and the multipart overhead count. | 413 |
| Recipients | 1,000, across to, cc and bcc, after duplicate addresses are removed. |
400 |
| Options | 16 KB (16,384 bytes): the values of all o:, h: and v: parameters together. The names of the parameters do not count. |
400 |
| Click Tracking ID | 300 characters. See The Click Tracking ID. | 400 |
o:deliverytime |
7 days after the time of the request. | 400 |
o:tag |
10 tags of up to 128 characters each. | GreenArrow drops the other tags. See o:tag. |
| Header line | 998 bytes. GreenArrow folds a longer header at its spaces. |
400 for a header that has no space where it can be folded |
| Time to send the request body | 120 seconds from the start of the request. | |
| Time to queue the message | 60 seconds from when GreenArrow has read the request body. | A 500. The message may or may not be queued. |
Send a Message
POST /v3/{domain_name}/messages
GreenArrow builds the message from the parameters, and submits it to the HTTP Submission API. All of its recipients get one message, except in a batch.
Parameters
|
from
string /required |
The sender, as an address ( The value must have one address. The domain of the address must be equal to A name that is an RFC 2047 encoded-word ( GreenArrow gives the address to the HTTP Submission API as |
|
to
string /required /may be repeated |
The recipients. Each value is an address, an address with a name, or a list of these with commas between them. Names are decoded as for A value that is not an address list is refused with All of the |
|
cc
string /optional /may be repeated |
The |
|
bcc
string /optional /may be repeated |
The |
|
subject
string /required |
The subject of the message. An empty value gives an empty subject. |
|
text
string /optional |
The text part of the message. |
|
html
string /optional |
The HTML part of the message. |
|
amp-html
string /optional |
The AMP part of the message. A message with |
|
attachment
file /optional /may be repeated |
A file to attach. The filename of the part is the name of the attachment. See Attachments and Inline Images. |
|
inline
file /optional /may be repeated |
An image or another file to show in the HTML part. The filename of the part is its Content-ID, so the HTML refers to |
|
o:tag
string /optional /may be repeated |
A tag of the message. GreenArrow keeps the first 10 tags, in request order, and drops a tag of more than 128 characters. A tag that GreenArrow drops does not count toward the 10. These limits do not cause an error. The tags go into the Click Tracking ID. |
|
o:dkim
string /optional |
|
|
o:secondary-dkim
string /optional |
A second DKIM key to sign the message with, as The message gets the usual DKIM signature of its GreenArrow does not check that the key exists. When it does not exist, GreenArrow logs an error and sends the message without the second signature. The response is |
|
o:secondary-dkim-public
string /optional |
The domain and selector of the second signature, as |
|
o:deliverytime
string /optional |
The time of the first delivery attempt. The value is an RFC 2822 date with a numeric zone ( The zone names are A time in the past counts as the time of the request. A time more than 7 days after the request is refused with GreenArrow makes the first delivery attempt at this time, or up to scheduled_send_jitter (1 minute by default) later. It uses the X-GreenArrow-SendNoEarlierThan header, or with The |
|
o:deliver-within
string /optional |
The time window for the delivery of the message, as hours and minutes: |
|
o:testmode
string /optional |
Not supported. |
|
o:tracking
string /optional |
Click and open tracking: |
|
o:tracking-clicks
string /optional |
Click tracking: |
|
o:tracking-opens
string /optional |
Open tracking: |
|
o:require-tls
string /optional |
Not supported. |
|
o:skip-verification
string /optional |
Not supported. |
|
o:sending-ip
string /optional |
An IP address to send the message from. It must be the IPv4 address of an IP Address VirtualMTA of this system. An IPv4-mapped IPv6 address ( A VirtualMTA that redirects its mail does not count. When more than one VirtualMTA has the address, GreenArrow uses the one that was created first. Routes ( |
|
o:sending-ip-pool
string /optional |
The pool ID of the Route that sends the message. A pool ID is 24 hexadecimal characters that GreenArrow makes from the ID of the Route; see Identifiers. The name of a Route and its numeric ID are not accepted. GreenArrow gives the Route ID to the HTTP Submission API as |
|
o:tracking-pixel-location-top
string /optional |
Not supported. |
|
h:{header}
string /optional |
A header of the message, for example
These headers are refused with
The letter case of a header name does not matter. A name that is not a valid header field name is refused with |
|
v:{name}
string /optional |
A variable of the message, for example |
|
recipient-variables
JSON object or null /optional |
The variables of each recipient, by address, for example |
template, t:version, t:text, t:variables and some o: options are not supported. See Unsupported Parameters.
Repeated and Empty Values
When a parameter that has one value is sent more than one time, GreenArrow does this:
| Parameter | When it is sent more than one time |
|---|---|
subject |
The values are joined with one space. |
text |
Each value is written followed by a line break. |
html, amp-html
|
The values are joined with <br> and a line break. |
v:{name}, and each o: option other than o:tag
|
The last value is used. |
recipient-variables |
The last value is used. |
from, h:{header}
|
Refused with 400. |
An empty text, html or amp-html value counts as absent. An empty subject gives an empty subject, an empty ordinary h: value gives an empty header, an empty v: value gives the value "", and an empty o:tag gives the tag "". An empty recipient-variables or h:X-Mailgun-Recipient-Variables value is refused because it is not valid JSON.
Attachments and Inline Images
Send each attachment and inline file as a file part of a multipart/form-data body, for example -F [email protected] with curl.
-
Content type. GreenArrow uses the
Content-Typeof the part. When the part has no type, a type that is not valid, orapplication/octet-stream, GreenArrow uses the type of the filename’s extension, orapplication/octet-streamwhen the extension is not known. -
Filenames. A filename cannot be blank, and cannot contain
",', CR or LF. -
Inline filenames. The filename of an
inlinepart is its Content-ID, so it must also be an RFC 5322 dot-atom-text, with or without an@and a dot-atom-text domain. Thusphoto.jpgand[email protected]are accepted, andmy photo.jpgand a name with characters that are not ASCII are refused. -
Content. A file cannot be empty, and cannot be the one character
0.
The message has the attachment files first, then the inline files, each in request order.
Examples
A message with two recipients
curl -s --user "api:$API_KEY" \
https://mg.api.example.com/v3/mail.example.com/messages \
-F from='Example Team <[email protected]>' \
-F to='Alice Adams <[email protected]>' \
-F to='[email protected]' \
-F subject='September update' \
--form-string html='<html><body><p>Hello!</p></body></html>' \
--form-string text='Hello!' \
-F o:tag=september-update \
-F o:tracking=false \
-F h:Reply-To='[email protected]' \
-F v:campaign_id=2026-09-update
200 OK:
{"id": "<[email protected]>", "message": "Queued. Thank you."}
The message has one To header with both recipients.
With -F, curl reads a value that starts with < as the name of a file to read, and a value that starts with @ as a file to upload. Thus -F html='<html>...' does not send the HTML. Use --form-string for a text or html value that starts with < or @.
To read a body part from a file, use -F html='<body.html'. This sends the contents of the file as a plain value. Do not use -F [email protected]: it sends a file part, which is refused with 400.
A message with an attachment and an inline image
curl -s --user "api:$API_KEY" \
https://mg.api.example.com/v3/mail.example.com/messages \
-F from='[email protected]' \
-F to='[email protected]' \
-F subject='Your report' \
--form-string html='<p>Your report is attached.</p><img src="cid:logo.png">' \
-F text='Your report is attached.' \
-F [email protected] \
-F [email protected]
A scheduled message
This message is delivered on 18 September 2026 from 09:00 to 11:00 UTC:
curl -s --user "api:$API_KEY" \
https://mg.api.example.com/v3/mail.example.com/messages \
-F from='[email protected]' \
-F to='[email protected]' \
-F subject='Good morning' \
-F text='Good morning!' \
-F o:deliverytime='Fri, 18 Sep 2026 09:00:00 +0000' \
-F o:deliver-within=2h
The Message-ID
The id of a 200 response is the Message-ID of the message, with angle brackets.
- With
h:Message-ID, theMessage-IDis that value. GreenArrow adds the angle brackets when they are missing. The value must be a validmsg-id(RFC 5322): a dot-atom-text,@, and a dot-atom-text or a domain literal ([192.0.2.1]). Another value, for examplehello, is refused with400. - Without
h:Message-ID, GreenArrow makes aMessage-IDin Mailgun’s form:<{time}.{random}@{domain_name}>.{time}is the time of the request in UTC asYYYYMMDDhhmmss, and{random}is 16 lower-case hexadecimal digits. For example:<[email protected]>.
For /messages.mime, the Message-ID of the document comes first. See The Message-ID on that page.
Tags and Variables
The Click Tracking ID
GreenArrow writes the tags, the variables and the identity of each message as a JSON document in its X-GreenArrow-Click-Tracking-ID header. The events of the message have this document in their click_tracking_id field.
{"m":"3f2b8c1e-9d4a-4e6f-8a17-5c0d2e9b7a41","M":"<[email protected]>","t":["september-update"],"v":{"campaign_id":"2026-09-update"}}
| Key | Value |
|---|---|
m |
A unique ID of the message: a version 4 UUID that GreenArrow makes. It is unique also when two messages have the same Message-ID. |
M |
The Message-ID of the message: the id of the response. |
t |
The tags (o:tag), in request order. It is not present when the message has no tags. |
v |
The variables: the v: parameters, and the members of h:X-Mailgun-Variables when its value is a JSON object. The names are in byte order. It is not present when the message has no variables. |
The document is compact JSON, with no spaces between tokens. Each character that is not ASCII is written as a \uXXXX escape. <, > and & are not escaped. A control character (U+0000 to U+001F, and U+007F) in a tag, in a v: value, or in a string of h:X-Mailgun-Variables is refused with 400.
The document must fit in 300 characters. GreenArrow refuses a request whose document is longer with 400. GreenArrow does not cut the variables, so the events always have all of them. The m and M values count toward the 300 characters. With a Message-ID that GreenArrow makes, the document without tags and variables is 85 characters plus the length of the domain name. The escapes of the JSON encoding count too.
The X-Mailgun-Variables Header
When a request has v: parameters, the message has an X-Mailgun-Variables header with the variables as a JSON object, in the form that Mailgun writes: with a space after each , and : between tokens, and the names in byte order. For example:
X-Mailgun-Variables: {"C": "3", "a": "1", "b": "2"}
As in the Click Tracking ID, each character that is not ASCII is written as a \uXXXX escape.
h:X-Mailgun-Variables. Without v: parameters, an h:X-Mailgun-Variables header is written as given. When its value is a JSON object, its members are also variables of the message, with their JSON types. A name that is in the header and in a v: parameter gets a JSON array of the two values, the value of the header first: {"a": ["from-header", "from-v"]}. A value that is not a JSON object gives no variables, and it is not an error.
When a /messages request has both h:X-Mailgun-Variables and v: parameters, the message has one X-Mailgun-Variables header with the merged variables. A value of h:X-Mailgun-Variables that is not a JSON object is then lost. Outside a batch, /messages.mime writes both headers, as Mailgun does.
Unfold the header before you parse it. GreenArrow folds each header that is too long for one line (998 bytes):
- It folds the
X-Mailgun-Variablesheader that it writes at the spaces between the JSON tokens. Only when one name or one string value is too long for a line does it fold at a space inside that string. - It folds an
h:X-Mailgun-Variablesheader that it writes as given at any of its spaces, also inside a string value.
A fold puts a line break in front of a space. Thus the JSON is correct only when you unfold the header (RFC 5322) before you parse it. A reader that does not unfold the header can get a string value with a line break in it, or JSON that is not valid.
Batch Sending
A request with recipient-variables is a batch. GreenArrow sends one message to each to recipient. On /messages, the To header of each message has only that recipient. (On /messages.mime, the document keeps its own To header. See Batch Sending.) Each message has the variables of its recipient in place of its placeholders. GreenArrow submits a batch to the HTTP Submission API as one template. See Individualized Messages.
curl -s --user "api:$API_KEY" \
https://mg.api.example.com/v3/mail.example.com/messages \
-F from='Example Team <[email protected]>' \
-F to='Alice Adams <[email protected]>' \
-F to='[email protected]' \
-F subject='Hey %recipient.first_name%, your plan renews soon' \
--form-string text='Hi %recipient.first_name%, your plan renews on %recipient.renews_on%.' \
-F recipient-variables='{"[email protected]": {"first_name": "Alice", "renews_on": "12 Oct 2026"}, "[email protected]": {"first_name": "Bob", "renews_on": "19 Oct 2026"}}' \
-F v:campaign_id=2026-10-renewals
Each valid value of recipient-variables makes a batch, also {} and null. With {}, each recipient gets its own copy of the same message. On /messages, the recipients do not see each other’s addresses.
Placeholders. %recipient.{name}% is replaced with the value of the recipient’s variable {name}, and %recipient% with the address of the recipient. GreenArrow replaces the placeholders in the headers of the message (also From, Subject and the h: headers), in its text and HTML parts, and in the v: values. It does not replace them in attachments, in the name of an attachment, or in the variables of h:X-Mailgun-Variables. A placeholder whose variable the recipient does not have stays as it is. The simplemh_batch_unresolved_placeholders_total metric counts these placeholders. For the placeholders in the v: values, GreenArrow also logs the names, with the addresses of up to 10 recipients.
A value is written as Mailgun writes it:
Value in recipient-variables
|
Text in the message |
|---|---|
| A string | The string, with no escapes, also in an HTML part |
| A number | The number as it is in the JSON, for example 1.50
|
true, false, null
|
True, False, None
|
| An object or an array | Compact JSON, for example {"a":1}
|
%recipient.address.city% is not a nested name: it is replaced only by a variable called address.city.
The recipients. A key of recipient-variables matches a to address when the two addresses are equal. The letter case does not matter. A key that matches no to address is not used. A to address that has no key gets the message with its placeholders as they are. A key whose value is not an object gives no variables.
The X-Mailgun-Recipient-Variables header. h:X-Mailgun-Recipient-Variables, or an X-Mailgun-Recipient-Variables header in a /messages.mime document, also makes a batch. Its value has the same JSON form as recipient-variables. GreenArrow unfolds the header before it reads it. When a request gives more than one of these, the variables of each recipient merge name by name. For a name in more than one, recipient-variables wins over the headers of the document, and the headers of the document win over h:X-Mailgun-Recipient-Variables. A later header of the document wins over an earlier one. GreenArrow does not deliver the header, because the header has the variables of all of the recipients. h:X-Mailgun-Recipient-Variables counts toward the 16 KB limit of the options. recipient-variables does not.
The response, the Message-ID and the variables. The response is one 200, as for one message. Each message of the batch has the same Message-ID: the id of the response. Each recipient has its own Click Tracking ID: m is a unique ID of the recipient’s message, and v has the v: values with the recipient’s placeholders replaced. v also has the variables of h:X-Mailgun-Variables, with their placeholders as they are. When these sources supply variables, the recipient’s X-Mailgun-Variables header has the same variables as v. On /messages.mime too, that header replaces the message-level h:X-Mailgun-Variables header.
Refused batches. A batch is refused with 400 when:
- It has
ccorbcc. Mailgun sends eachccandbccrecipient one copy of the message for eachtorecipient. - A variable of a
torecipient has a line break (CR or LF). - The Click Tracking ID of one recipient is longer than 300 characters. The message names the recipient.
- The value of
recipient-variablesor of the header is not a JSON object ornull.
See Error Messages for the messages.
Unsupported Parameters
GreenArrow refuses these parameters with 400:
| Parameter | Message |
|---|---|
template, t:version, t:text, t:variables, and each other t: parameter |
{name} parameter is not supported |
o:deliverytime-optimize-period, o:time-zone-localize, o:archive-to, o:suppress-headers, o:inbox-placement-test-key
|
{name} parameter is not supported |
o:testmode, o:require-tls, o:skip-verification, o:tracking-pixel-location-top
|
no and false are accepted and ignored. Another value: {name} parameter value {value} is not supported
|
o:dkim with no or false
|
o:dkim parameter value {value} is not supported |
A parameter that this page does not list, for example sender or o:foo
|
{name} parameter is not supported |
Differences from Mailgun
The From domain. The domain of from must be equal to {domain_name}. Mailgun accepts a From address of another domain.
Unknown parameters are refused. A parameter that this page does not list is refused with 400.
Refused headers. The h: headers that control GreenArrow (X-GreenArrow-*, X-Virtual-MTA, X-Schedule, X-Job, X-CampaignID and X-Mailer-Info), the headers that GreenArrow builds (From, To, Cc, Subject, Date, MIME-Version, Content-Type and Content-Transfer-Encoding), h:Bcc, h:Return-Path, h:Authentication-Results and h:Sender are refused.
Repeated values. A request with from or an h: header sent more than one time is refused. Mailgun writes both values.
subject is required. Mailgun accepts a request with no subject.
amp-html needs text or html. Mailgun accepts amp-html alone.
Attachments. An attachment or inline filename cannot contain " or '. An inline filename must be an RFC 5322 dot-atom-text, with or without an @ and a dot-atom-text domain: no spaces, and ASCII only. A file cannot be empty, and cannot be the one character 0.
Tags. When a request has more than 10 tags, GreenArrow keeps the first 10 in request order. Mailgun keeps 10, not in request order. A tag cannot contain a control character.
Variables. A v: value cannot contain a control character. The tags and the variables must fit in the 300-character Click Tracking ID. Mailgun cuts variables over 4 KB in its events. GreenArrow does not cut them.
X-Mailgun-Variables. A /messages request with both h:X-Mailgun-Variables and v: parameters gives one X-Mailgun-Variables header with the merged variables. Mailgun writes two headers.
The username. A username other than api is refused with 401. Mailgun accepts any username.
h:Message-ID. The value must be a valid msg-id. Mailgun accepts any value, for example hello.
o:deliverytime. It can be up to 7 days after the request. Mailgun allows 72 hours.
o:dkim. no and false are refused, because GreenArrow always signs.
o:secondary-dkim. A key that does not exist gives no second signature. It is not an error.
The 401 and 403 domain responses. These responses need GreenArrow’s Sending Domains to be in use. See “The domain in the path” in Requests and Responses. Mailgun answers 403 for a domain of the account that is not verified. GreenArrow answers 401 for a Sending Domain whose DNS records are not verified, and 403 for a verified Sending Domain whose sending is disabled.
No unsubscribe tracking. GreenArrow does not add a List-Unsubscribe header, and does not add an unsubscribe footer. It does not replace %unsubscribe_url%, %tag_unsubscribe_url% or %mailing_list_unsubscribe_url%. A List-Unsubscribe header that you send with h:List-Unsubscribe is delivered as given. A Mail Class that forces the automatic List-Unsubscribe header on adds one.
Encoded names. GreenArrow decodes the encoded-words of the charsets UTF-8, ISO-8859-1 and US-ASCII in from, to and cc. It refuses an encoded-word in another charset.
Batch sending. A batch with cc or bcc is refused. A recipient variable with a line break is refused. Mailgun accepts both. The multipart/mailgun-variables part is not supported.
Templates. template and the t: parameters are refused.
