AWRA OpsHub Search

The Body Everything Else Translates

Every email this system sends is built in one provider's format, and the other four translate out of it. That is not the tidy design anybody would draw on a whiteboard — and it is a better one than the neutral format that would have replaced it.

Integrations & Data AWRA OpsHub Team 12 min read

When a system talks to several providers for one job, there is a moment where somebody proposes an internal neutral format. Everything is built in ours, everything translates out of it, nobody is privileged. It is obviously right, it is what the textbooks say, and here it is not what happened — the first provider's format became the internal format, and the others adapt. That was an accident of history, and it has aged better than the alternative would have.

One shape, five destinations

A purchase order email is assembled once. It is assembled in the shape one particular provider expects: a list of messages, each with a sender, recipients, a subject and a body.

From there, five things can happen to it.

Destination What happens to the body Cost
That provider, from your account Sent as it is Nothing
A different provider, from your domain Converted to a multipart request A translation step
A third provider, from your account Converted to that provider's JSON A translation step
Your own mailbox, through a workspace connector Converted again A translation step
The platform's own sending Sent as it is Nothing

A neutral internal format would have made all five rows cost a translation. This one makes two of them cost nothing.

Two of the five destinations pay nothing. A neutral internal format would have made all five translate.
Two of the five destinations pay nothing. A neutral internal format would have made all five translate.

Why not invent a neutral format?

Because a neutral format is not free, and its costs are the kind that only appear later.

  1. It is one more thing to learn

    A provider format has documentation, examples and a community. An invented internal one has whatever is in the code, and whoever wrote it.

  2. It is a lowest common denominator by construction

    A neutral format supports what all providers support. The moment one offers something useful the others do not, the format either grows an escape hatch or the feature is unreachable.

  3. It converts on the common path too

    Most mail goes out through the default sending path. With a neutral format, that path pays a translation on every message to gain nothing.

  4. It drifts

    A format nobody outside the codebase uses is a format nobody outside the codebase checks. It grows fields that mean something to one caller and gets subtly out of step with what the providers actually accept.

Choosing a real provider's format instead means the common path is free, the format is documented by somebody else, and it cannot drift — because a request that does not match it is refused by a live service.

What it costs, stated plainly

Two things, and the second is the one that matters.

The first is cosmetic: one provider is named all through the internals in a way that reads oddly to anybody who arrives later and finds a function named for a company. That is a documentation problem rather than a design one.

The second is real. The format is now a dependency, and if that provider changed their interface substantially, the internal shape would either follow them or become an invented format after all — with the added indignity of being an invented format that looks like somebody else's.

That is a bet, and it is worth naming as one. The bet is that a widely used transactional email format is stable, which is about as safe as bets in this area get, and it is a bet with a known escape: pinning the shape and writing translators for everybody is exactly the work the other connectors already do.

The translations are not symmetrical

A detail worth knowing, because it explains why the connectors are different sizes.

Translating into another JSON API is field renaming — sender here, recipients there, subject and body across. Translating into a multipart form request is a different exercise, because the shape changes: a structured list of recipients becomes repeated form fields, and the whole notion of nesting goes away.

Both loop over the messages in the body, because the format allows several in one send, and both skip anything that is not shaped like a message rather than failing on it. That last part is small and deliberate: a malformed entry costs its own message rather than the batch.

Two credentials, and a success test that is not a status code

The provider whose format this is uses two credentials rather than one — a key and a secret — which is a different arrangement from every other email connector here and worth knowing when you are copying values out of a console.

It is also reached through its own client library rather than a plain HTTP call, which means success is decided by the library's own test rather than by reading a status code. That is the right call: the library knows what its provider considers a success, including the cases where an acceptable status carries a per-message error inside it.

And there is a per-message error path, four levels into the response, with the whole document as a fallback. The fallback is the important half — a deep path into somebody else's response is a guess about their structure, and the day it does not match is a day you need the message rather than an empty string.

What is in place, layer by layer

How an email is built and routed

One body, built once

Every outbound email is assembled in a single documented format, whichever provider ultimately sends it.

Built in

No translation on the common path

The default sending path and this connector both take the body as it is, so the ordinary case pays nothing for the flexibility.

Built in

Translators for the other providers

Each alternative connector converts the same body into its own provider's shape, rather than every caller learning several formats.

Built in

Several messages per body

The format carries a list, and the translators loop over it, so one send can address several messages without a second call.

Built in

A malformed entry costs itself

Anything in that list that is not shaped like a message is skipped rather than failing the batch around it.

Built in

The provider's own success test

Where a client library is used, its own notion of success is trusted rather than a status check that would miss per-message errors.

Built in

A nested error path with a raw fallback

The specific message is read from where the provider puts it, and anything unrecognised falls back to the whole response.

Built in

Both credentials encrypted at rest

The key and the secret are stored through encrypted casts on the row for one workspace, and never written into a log line.

Built in

Your own sending account

Your credentials, your verified sender, your reputation and your billing. Selected mail leaves from your account rather than ours.

Built in

Choosing a real provider's format as the internal one is a bet that the format stays stable. It is named here as a bet rather than presented as an inevitability.

Three positions held on purpose

  • A real, documented provider format is used internally rather than an invented neutral one. The neutral version costs a translation on the common path, becomes a lowest common denominator by construction, and drifts because nothing outside the codebase ever validates it.
  • The dependency this creates is stated rather than hidden. A format borrowed from a vendor is a bet on that vendor's stability, and a reader deserves to see it named as one.
  • A malformed message in a batch costs only itself. Failing the whole send because one entry was wrong is the version that turns a single bad record into an outage for everything queued behind it.

Five questions about multi-provider email

What format is mail built in?

A good answer sounds like

One, named.

What ours actually is

A single documented provider format, with translators for the alternatives.

Does the common path pay for the flexibility?

A good answer sounds like

No.

What ours actually is

The default sending path takes the body as it is. Only the alternatives translate.

What if that provider changed their format?

A good answer sounds like

They have thought about it.

What ours actually is

The shape would be pinned and translated for everybody — which is exactly what the other connectors already do.

How is a rejection reported?

A good answer sounds like

The provider's message.

What ours actually is

Read from where they put it, with the whole response as a fallback so the reason is never empty.

Whose account sends the mail?

A good answer sounds like

Yours, if you connect one.

What ours actually is

Your credentials and your verified sender, for the categories you choose.

Our take

The instinct to invent a neutral internal format is one of the most reliable ways to add work to a codebase without adding capability. It feels principled, it is what a diagram wants, and what it actually produces is an undocumented dialect that supports the intersection of your providers, that nobody outside the building can check, and that quietly drifts from what any of them accept. Borrowing a real format is uglier on the diagram and better in every other respect: it is documented, it is validated by a live service every time you use it, and the common path pays nothing. Name the dependency, keep the translators honest, and the ugliness is the whole cost.

Send the important mail from your own domain

Purchase orders, RFQs, invoices and receipts leaving from your account rather than a shared one — with the rest still handled for you.

Talk through email delivery

Frequently asked questions

Do we have to use this provider?

No. Its format is used internally, which is invisible from outside — you can connect any of the supported email providers, or your own Google or Microsoft mailbox, or none of them and let the platform send. What the internal format decides is which connector pays a translation step, not which one you can use.

Can one email go to several recipients?

Yes, and the format also carries several distinct messages in one body. The translators loop over that list, so a send addressing several messages is one call rather than several.

What happens if one message in a batch is malformed?

It is skipped and the rest are sent. Failing the whole batch because one entry was wrong turns a single bad record into an outage for everything behind it, which is a much worse trade than losing one message.

Why does this connector need two credentials?

Because that provider uses a key and a secret rather than a single token. It is worth knowing when you are copying values out of a console, since the other email connectors here each use a single credential in a different position.

How do we know a rejection was not silently swallowed?

A refusal reports the provider's own message, read from where they place it in their response, with the entire response as a fallback for anything unrecognised. The one thing you should never see is a failure with an empty reason.

Help Center

Need a quick answer while you read?

Run inventory, procurement, assets, sales, and field work with approved AWRA guidance for setup, migration, integrations, security, pricing, and support.

Search all approved AWRA public help articles.

Open Help Center