# Editores e API de MJML

> Crie templates e campanhas responsivos com MJML, em alfa e aberto à equipe do Emailit. Os editores Visual e Code, documentos armazenados, validação, Temple no MJML, colaboração em tempo real e a API de MJML.

O [MJML](https://mjml.io) é uma linguagem de marcação para e-mails responsivos. Você escreve seções, colunas e componentes como `<mj-text>` e `<mj-button>`, e o MJML os compila em um HTML que é renderizado de forma consistente nos clientes de e-mail. No Emailit, o MJML pode ser o código-fonte de um template ou de uma campanha: você o escreve nos editores do painel ou o envia pela API, e o Emailit o valida e compila o HTML.

> **O MJML está em alfa:** O MJML está em alfa e aberto apenas à equipe do Emailit enquanto o testamos. Os workspaces de clientes ainda não veem os editores MJML, e as requisições à API que criam ou alteram templates MJML, ou que chamam os endpoints de MJML, retornam `403` com `error: "mjml_alpha"`. Esta página descreve como o MJML funciona para que você possa se planejar. Todos continuam podendo enviar templates e campanhas feitos com MJML.

## Visão geral

- **Templates**: `editor: "mjml"` com o MJML em `source`. Consulte [Criar um template](/pt/docs/api-reference/templates/create/).
- **Campanhas**: `content_type: "mjml"` com o MJML em `content`. Consulte [Campanhas](#campaigns).
- **Automações**: a etapa **Send email** envia um template MJML como qualquer outro template. Consulte [Automações](#automations).
- **Endpoints de MJML**: [Validar MJML](/pt/docs/api-reference/mjml/validate/), [Renderizar MJML](/pt/docs/api-reference/mjml/render/) e [Obter a referência do MJML](/pt/docs/api-reference/mjml/reference/).

### Quem pode usar o MJML

Durante a fase alfa, o MJML está disponível apenas para os administradores da plataforma Emailit. O papel Admin de um workspace não é suficiente.

| Onde | Equipe do Emailit | Todos os outros |
| --- | --- | --- |
| Painel | Editores MJML, importação de MJML, **Edit with AI** e colaboração em tempo real | Sem editores MJML. Os templates e as campanhas MJML mostram um aviso, não abrem em um editor e continuam podendo ser enviados. |
| API | Templates MJML, campanhas MJML e os endpoints de MJML | `403` com `error: "mjml_alpha"`. O `content_type: "mjml"` de uma campanha continua sendo um simples rótulo, como antes da fase alfa. Consulte [Campanhas](#campaigns). |
| Chaves de API | Nenhuma. As chaves de API pertencem a um workspace, não a uma pessoa. | `403` com `error: "mjml_alpha"` |
| Servidor MCP | As ferramentas de MJML e os parâmetros de MJML das ferramentas de templates e de campanhas | Não listados |

Todos continuam podendo renomear, publicar, exportar, enviar e excluir templates e campanhas MJML. Duplicar um template MJML cria um novo template MJML, então isso exige acesso ao MJML.

### Versão do MJML

O Emailit compila todo o MJML com o **MJML 5.4.1**, tanto no servidor quanto na prévia ao vivo dos editores. A validação confere tags, atributos e valores de atributos com base nessa versão. [Obter a referência do MJML](/pt/docs/api-reference/mjml/reference/) retorna a versão e todos os componentes e atributos que ela suporta.

### Editores

O painel tem dois editores MJML. Os dois são versionados e os dois são versões alfa `0.x`.

| Editor | ID | Versão | Descrição |
| --- | --- | --- | --- |
| MJML Visual Editor | `mjml-visual` | 0.2.0 (alfa) | Arrastar e soltar sobre o e-mail renderizado, cobrindo todos os componentes e atributos do MJML |
| MJML Code Editor | `mjml-code` | 0.2.0 (alfa) | MJML com preenchimento automático, validação inline e uma prévia ao vivo para desktop e celular |

Os dois editores salvam o template com `editor: "mjml"`. O documento armazenado registra qual editor, e qual versão dele, o salvou por último. Os colegas podem editar o mesmo template ou a mesma campanha ao mesmo tempo. Consulte [Edição colaborativa](#editing-together).

## Formatos do código-fonte

Em todos os lugares em que o Emailit aceita MJML (o `source` de um template, o `content` de uma campanha e o campo `source` dos endpoints de MJML), você pode enviar qualquer um destes formatos:

| Formato | Exemplo |
| --- | --- |
| Marcação MJML | Uma string que começa com `<mjml>`. Uma declaração XML ou comentários no início são permitidos. |
| MJML JSON | O formato JSON do próprio MJML, como objeto ou como string JSON: `{ "tagName": "mjml", "attributes": {}, "children": [ … ] }`. As tags finais (ending tags), como `mj-text`, levam o HTML delas em `content`. |
| Documento MJML do Emailit | O envelope que o Emailit armazena (abaixo), como objeto ou como string JSON |

Qualquer outra coisa é rejeitada com `document.unrecognized`. Um código-fonte com mais de 2 MB é rejeitado com `document.too-large`.

### O documento armazenado

O Emailit armazena o MJML em um envelope versionado. Ele é o `source` do template e o `content` da campanha:

```json
{
  "kind": "emailit/mjml",
  "schema_version": 1,
  "mjml_version": "5.4.1",
  "editor": "api",
  "editor_version": null,
  "format": "markup",
  "content": "<mjml>\n  <mj-body>\n    …\n  </mj-body>\n</mjml>"
}
```

| Campo | Descrição |
| --- | --- |
| `kind` | Sempre `emailit/mjml`. |
| `schema_version` | Versão do formato do envelope. Atualmente `1`. |
| `mjml_version` | A versão do MJML à qual o conteúdo se destina. O Emailit a define como a versão com que compilou. |
| `editor` | O que escreveu o documento por último: `mjml-visual`, `mjml-code`, `ai` (**Edit with AI**) ou `api` (a API, as ferramentas MCP e as importações de arquivos). |
| `editor_version` | Versão desse editor, ou `null`. |
| `format` | `markup`: `content` é marcação MJML, mantida como foi escrita, incluindo comentários e formatação. `json`: `content` é MJML JSON. |
| `content` | O MJML. |

O que você envia define o formato: a marcação é armazenada como `markup`, e o MJML JSON, como `json`. Os dois são registrados como `editor: "api"`. Um envelope que você envia mantém o `editor` e o `editor_version` dele.

As respostas da API retornam `source` como esse envelope, serializado em uma string JSON, e você pode enviá-lo de volta sem alterações. As respostas também incluem um objeto `mjml` com as versões do envelope:

```json
"mjml": {
  "mjml_version": "5.4.1",
  "schema_version": 1,
  "editor": "api",
  "editor_version": null,
  "format": "markup"
}
```

O painel abre um documento no editor que o salvou por último. Os documentos escritos pela API abrem no Code Editor quando `format` é `markup` e no Visual Editor quando é `json`.

## Compilar e salvar

Nos templates e nas campanhas MJML, é o Emailit que gera o HTML:

- Ao criar e ao atualizar, o Emailit valida o MJML e o compila. O HTML compilado é armazenado como o `html` do template, e qualquer `html` que você enviar é ignorado.
- O envio usa o HTML armazenado. As tags do Temple continuam nele e são renderizadas para cada destinatário no momento do envio.
- Atualizar apenas outros campos, como `name` ou `subject`, não recompila o template.
- `text` não é gerado a partir do MJML. Envie `text` você mesmo se quiser uma parte em texto simples.
- Mudar um template existente para `editor: "mjml"` sem enviar `source` compila o `source` armazenado do template, que então precisa ser MJML.

O HTML é compilado quando você salva, então o HTML de um template existente só muda quando ele é salvo de novo.

```bash
curl https://api.emailit.com/v2/templates \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome",
    "alias": "welcome",
    "subject": "Welcome, {{first_name|\"there\"}}",
    "editor": "mjml",
    "source": "<mjml><mj-head><mj-title>Welcome</mj-title><mj-preview>Your account is ready</mj-preview></mj-head><mj-body><mj-section><mj-column><mj-text>Hi {{first_name|\"there\"}}, welcome aboard.</mj-text><mj-button href=\"{{activation_url}}\">Activate account</mj-button></mj-column></mj-section></mj-body></mjml>"
  }'
```

Depois, envie-o como qualquer outro template com [Enviar um e-mail](/pt/docs/api-reference/emails/send/): `"template": "welcome"` e um objeto `variables`.

## Validação

Cada vez que você salva, o Emailit executa as mesmas verificações de [Validar MJML](/pt/docs/api-reference/mjml/validate/):

- Sintaxe XML: tags não fechadas ou que não correspondem e atributos malformados (`xml.*`)
- Estrutura, atributos e valores de atributos do MJML para o MJML 5.4.1 (`mjml.*`)
- Sintaxe do Temple e blocos `{{#if}}` balanceados (`temple.*`)
- O formato e as versões do código-fonte (`document.*`), e o próprio compilador (`compiler.*`)

Cada problema encontrado é um diagnóstico com uma gravidade:

| Gravidade | Efeito |
| --- | --- |
| `error` | O MJML é rejeitado. Os templates e as campanhas não são salvos. |
| `warning` | Salvo. Provavelmente um engano: sem `<mj-title>`, texto fora de um componente, um bloco condicional que atravessa componentes ou um HTML acima do limite de corte de 102 KB do Gmail. |
| `info` | Salvo. Uma sugestão ou uma observação: sem `<mj-preview>`, uma imagem sem `alt` ou um documento escrito para uma versão mais antiga do MJML. |

Um diagnóstico tem estes campos. Os campos que não se aplicam ficam de fora.

| Campo | Descrição |
| --- | --- |
| `severity` | `error`, `warning` ou `info` |
| `code` | Um código estável, legível por máquina, por exemplo `mjml.invalid-child` |
| `message` | Uma explicação legível, muitas vezes com uma correção (“Did you mean color?”) |
| `line`, `column` | Posição na marcação, começando em 1. Apenas para código-fonte em marcação. |
| `tag` | O elemento a que o diagnóstico se refere |
| `attribute` | O atributo, quando houver |
| `path` | Caminho de índices de filhos a partir da raiz `<mjml>`. `[0, 1]` é o segundo filho do primeiro filho. |

### Resposta de erro

Salvar um template ou uma campanha com diagnósticos de erro retorna `422`. Para este código-fonte:

```xml
<mjml>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-text colour="#333333">Hi {{first_name|"there"}}</mj-text>
        <mj-button href="{{cta_url}}">{{#if trial}}Start trial</mj-button>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>
```

a resposta é:

```json
{
  "message": "The MJML is not valid.",
  "errors": {
    "source": [
      "Line 5: <mj-text> has no attribute colour. Did you mean color?",
      "Line 6: {{#if trial}} is never closed with {{/if}}."
    ]
  },
  "diagnostics": [
    {
      "severity": "error",
      "code": "mjml.unknown-attribute",
      "message": "<mj-text> has no attribute colour. Did you mean color?",
      "line": 5,
      "column": 18,
      "tag": "mj-text",
      "attribute": "colour",
      "path": [0, 0, 0, 0]
    },
    {
      "severity": "warning",
      "code": "mjml.missing-title",
      "message": "Add an <mj-title> to <mj-head>; clients and screen readers use it.",
      "line": 1,
      "column": 2,
      "tag": "mjml",
      "path": []
    },
    {
      "severity": "info",
      "code": "mjml.missing-preview",
      "message": "Add an <mj-preview> to control the inbox preview text.",
      "line": 1,
      "column": 2,
      "tag": "mjml",
      "path": []
    },
    {
      "severity": "error",
      "code": "temple.unclosed-if",
      "message": "{{#if trial}} is never closed with {{/if}}.",
      "line": 6,
      "column": 39,
      "tag": "mj-button",
      "path": [0, 0, 0, 1]
    }
  ]
}
```

- `errors.source` (`errors.content` nas campanhas) lista até cinco mensagens de erro, com a linha de cada uma quando ela é conhecida.
- `diagnostics` lista todos os diagnósticos, incluindo avisos e informações.
- Um código-fonte ausente ou vazio retorna `422` com `"message": "Validation failed"`, `"errors": { "source": ["The source field is required for MJML."] }` e um array `diagnostics` vazio.

[Validar MJML](/pt/docs/api-reference/mjml/validate/) executa as mesmas verificações sem salvar e retorna `200` com `valid: false` em vez de `422`.

### Códigos de diagnóstico

**XML** (código-fonte em marcação)

| Código | Gravidade | Significado |
| --- | --- | --- |
| `xml.unclosed-tag` | error | Um elemento nunca é fechado. |
| `xml.unexpected-closing-tag` | error | Uma tag de fechamento não corresponde a nenhum elemento aberto. |
| `xml.malformed-closing-tag` | error | Não é possível ler uma tag de fechamento. |
| `xml.unterminated-tag` | error | Uma tag de abertura não tem o `>` de fechamento. |
| `xml.unterminated-attribute` | error | O valor de um atributo não tem a aspa de fechamento. |
| `xml.missing-attribute-value` | error | `name=` não tem valor. |
| `xml.invalid-attribute` | error | Um caractere inesperado dentro de uma tag. |
| `xml.duplicate-attribute` | error | O mesmo atributo duas vezes no mesmo elemento. O primeiro é usado. |
| `xml.unterminated-comment` | error | Um comentário não tem `-->`. |
| `xml.unterminated-cdata` | error | Uma seção CDATA não tem `]]>`. |
| `xml.unexpected-character` | error | Um `<` solto fora de uma tag final. |
| `xml.multiple-roots` | error | Mais de um elemento raiz. |
| `xml.text-outside-root` | error | Texto fora de `<mjml>`. |
| `mjml.missing-root` | error | O documento está vazio. |
| `xml.unquoted-attribute` | warning | Um valor de atributo sem aspas. |
| `xml.stray-text` | warning | Texto entre elementos, fora de qualquer componente de conteúdo. O MJML o ignora. |
| `xml.unexpected-declaration` | warning | Uma declaração depois do início de `<mjml>`. |

**MJML**

| Código | Gravidade | Significado |
| --- | --- | --- |
| `mjml.unknown-tag` | error | Não é um elemento do MJML 5.4.1, com uma sugestão “did you mean” quando houver uma parecida. |
| `mjml.unknown-attribute` | error | O elemento não tem esse atributo. Aviso no próprio `<mjml>`. |
| `mjml.invalid-attribute-value` | error | O tipo de valor errado: não é uma cor, uma unidade nem um valor permitido. |
| `mjml.invalid-child` | error | O elemento não é permitido dentro do elemento pai. |
| `mjml.invalid-root` | error | O elemento raiz não é `<mjml>`. |
| `mjml.missing-body` | error | Não há `<mj-body>`. |
| `mjml.duplicate-body` | error | Mais de um `<mj-body>`. |
| `mjml.include-not-supported` | error | `<mj-include>` não é suportado. |
| `mjml.missing-attribute` | error ou warning | Falta um atributo obrigatório. Erro para `name` e `href` de `<mj-font>`, `name` de `<mj-class>`, `path` de `<mj-selector>` e `name` de `<mj-html-attribute>`. Aviso para o `src` de uma imagem e o `width` de `<mj-breakpoint>`. |
| `mjml.missing-title` | warning | Não há `<mj-title>` em `<mj-head>`. |
| `mjml.empty-title` | warning | `<mj-title>` está vazio. |
| `mjml.duplicate-head` | warning | Mais de um `<mj-head>`. |
| `mjml.ignored-content` | warning | Texto dentro de um elemento que não aceita conteúdo. |
| `mjml.ignored-children` | warning | Elementos filhos dentro de um elemento que só aceita conteúdo. |
| `mjml.column-widths` | warning | As larguras das colunas de uma seção ou de um grupo somam mais de 100%. |
| `mjml.unknown-social-network` | warning | Um nome de `<mj-social-element>` sem ícone integrado e sem `src`. |
| `mjml.script` | warning | `<script>` no conteúdo. Os clientes de e-mail o removem. |
| `mjml.missing-preview` | info | Não há `<mj-preview>`. |
| `mjml.missing-alt` | info | Um `<mj-image>` sem `alt`. |
| `mjml.button-without-link` | info | Um `<mj-button>` sem `href`. |

**Temple**

| Código | Gravidade | Significado |
| --- | --- | --- |
| `temple.unclosed-if` | error | `{{#if}}` sem `{{/if}}`. |
| `temple.endif-without-if` | error | `{{/if}}` sem `{{#if}}`. |
| `temple.else-without-if` | error | `{{else}}` fora de um bloco. |
| `temple.duplicate-else` | error | Dois `{{else}}` no mesmo bloco. |
| `temple.unclosed-expression` | error | `{{` sem `}}`. |
| `temple.empty-expression` | error | `{{ }}`. |
| `temple.empty-condition` | error | `{{#if}}` sem variável. |
| `temple.malformed-else` | error | `{{else}}` escrito com espaços ou argumentos. |
| `temple.unsupported-block` | error | Um bloco diferente de `{{#if}}`, como `{{#each}}`. |
| `temple.unsupported-syntax` | error | Chaves triplas `{{{…}}}`, partials `{{> …}}` ou comentários `{{! …}}`. |
| `temple.invalid-variable` | warning | Uma variável que não é um caminho válido. |
| `temple.invalid-condition` | warning | Uma condição que não é um caminho de variável. Comparações não são suportadas. |
| `temple.block-crosses-components` | warning | Um bloco que abre em um componente e fecha em outro. |

**Documento e compilador**

| Código | Gravidade | Significado |
| --- | --- | --- |
| `document.empty` | error | O código-fonte está vazio. |
| `document.unrecognized` | error | Não é marcação MJML, MJML JSON nem um documento MJML do Emailit. |
| `document.invalid-json` | error | O código-fonte parece JSON, mas não pode ser interpretado. |
| `document.invalid-node` | error | MJML JSON com um nó malformado. |
| `document.too-large` | error | O código-fonte tem mais de 2 MB. |
| `document.unsupported-schema` | error | O `schema_version` do envelope é mais novo do que o Emailit consegue ler. |
| `document.unsupported-mjml-version` | error | A versão do MJML do documento não pode ser compilada. Consulte [Versões e atualizações](#versions-and-upgrades). |
| `document.assumed-mjml-version` | info | O envelope não tem `mjml_version`, então a versão atual é presumida. |
| `document.mjml-upgraded` | info | Escrito para outra versão do MJML e compilado com a 5.4.1. |
| `compiler.failed` | error | O MJML não conseguiu renderizar o documento. |
| `compiler.gmail-clipping` | warning | O HTML tem mais de 102 KB, então o Gmail o corta. |

## Temple no MJML

As tags do [Temple](/pt/docs/templates/temple/) passam pela compilação do MJML sem alterações. O Emailit as renderiza para cada destinatário no momento do envio, sobre o HTML compilado.

### Variáveis no conteúdo e nos atributos

As variáveis funcionam no conteúdo e em qualquer atributo:

```xml
<mj-text>Hi {{first_name|"there"}},</mj-text>
<mj-button href="{{activation_url}}">Activate your account</mj-button>
<mj-image src="{{logo_url}}" alt="{{company|'Acme'}}" />
<mj-section background-color="{{brand_color|'#ffffff'}}">
```

- Dentro de um atributo, escreva os valores padrão com aspas simples: `href="{{url|'https://example.com'}}"`.
- Os valores de atributos que contêm Temple não têm o tipo verificado, porque o valor só é conhecido no momento do envio. Garanta que a variável tenha um valor válido para o atributo, como uma cor para `background-color`.
- Os valores são inseridos como estão, sem escape de HTML.

### Blocos condicionais

Dentro de um único componente, coloque o bloco no conteúdo dele:

```xml
<mj-text>{{#if plan}}You are on the {{plan}} plan.{{else}}You are on the free plan.{{/if}}</mj-text>
```

Para mostrar ou ocultar componentes inteiros, coloque as tags do bloco em elementos `<mj-raw>` irmãos:

```xml
<mj-raw>{{#if vip}}</mj-raw>
<mj-section background-color="#fef3c7">
  <mj-column>
    <mj-text>Your VIP perks are ready.</mj-text>
  </mj-column>
</mj-section>
<mj-raw>{{/if}}</mj-raw>
```

As tags de bloco soltas entre componentes são convertidas em `<mj-raw>` quando a marcação é interpretada, então isto é a mesma coisa:

```xml
{{#if vip}}
<mj-section background-color="#fef3c7">
  …
</mj-section>
{{/if}}
```

Qualquer outro texto entre componentes é ignorado pelo MJML e reportado como `xml.stray-text`.

- Os blocos precisam estar balanceados no documento inteiro. Uma tag não fechada ou sobrando é um erro.
- Abra e feche cada bloco dentro do conteúdo de um único componente, ou entre os `<mj-raw>` irmãos de um mesmo elemento pai. Um bloco que abre em um componente e fecha em outro recebe um aviso `temple.block-crosses-components`, porque ocultá-lo cortaria a estrutura do HTML.
- Os blocos podem ser aninhados.

### Sem suporte

- `<mj-include>` é rejeitado com `mjml.include-not-supported`. Cole o MJML incluído no documento.
- Tags e atributos que o MJML 5.4.1 não define são erros.
- O Temple não tem loops, helpers, partials, comentários, chaves triplas nem comparações. Consulte [Temple](/pt/docs/templates/temple/).

### Variáveis por canal

O mesmo template MJML pode ser enviado de vários lugares, e cada um fornece variáveis diferentes:

| Enviado por | Variáveis |
| --- | --- |
| [Enviar um e-mail](/pt/docs/api-reference/emails/send/) pela API, com `template` | O objeto `variables` que você passa |
| Etapa **Send email** de uma automação | Automações de contatos: os campos do contato no nível superior (`{{first_name}}`, `{{email}}`), os campos personalizados como `{{cf.<key>}}` ou `{{custom_fields.<key>}}`, além de `{{contact.*}}`, `{{payload.*}}` e `{{meta.*}}` |
| Campanhas MJML | `{{first_name}}`, `{{last_name}}`, `{{email}}`, `{{unsubscribe_url}}`, `{{cf.<key>}}` e os mesmos campos em `{{contact.*}}` |

Os editores inserem os campos personalizados como `{{cf.<key>}}`, que funciona nas campanhas MJML e nas automações. Nos envios pela API, passe você mesmo as variáveis.

Para ver a prévia da versão de um destinatário, chame [Renderizar MJML](/pt/docs/api-reference/mjml/render/) com `variables`.

## Campanhas

Uma campanha com `content_type: "mjml"` armazena o MJML em `content`, em qualquer um dos [formatos do código-fonte](#source-formats), e o Emailit compila o `html` dela. Como nos templates, qualquer `html` que você enviar é ignorado. Um MJML inválido retorna `422` com `errors.content` e `diagnostics`. Enviar um `content` vazio limpa tanto o conteúdo quanto o HTML. As respostas de campanhas incluem o mesmo objeto `mjml` dos templates.

As campanhas MJML renderizam o assunto, o HTML e o texto com o **Temple** para cada destinatário, inclusive nos envios de teste. Estas variáveis estão disponíveis:

| Variável | Valor |
| --- | --- |
| `{{first_name}}` | Nome do contato |
| `{{last_name}}` | Sobrenome do contato |
| `{{email}}` | Endereço de e-mail do contato |
| `{{unsubscribe_url}}` | Link de descadastro para este contato e esta campanha |
| `{{cf.<key>}}` | Campo personalizado do contato, por exemplo `{{cf.company}}` |
| `{{contact.first_name}}`, `{{contact.cf.<key>}}`, … | Os mesmos campos em `contact` |

Os campos vazios do contato contam como ausentes, então os valores padrão se aplicam: `{{first_name|"there"}}` renderiza `there` para um contato sem nome. Mantenha um link `{{unsubscribe_url}}` no rodapé dos e-mails de marketing.

As campanhas clássicas (HTML, texto e os outros editores) mantêm as tags de mesclagem fixas:

| | Campanhas clássicas | Campanhas MJML |
| --- | --- | --- |
| Mecanismo | Tags de mesclagem fixas | Temple |
| `{{#if}}` … `{{else}}` … `{{/if}}` | Não processado | Suportado |
| Valores padrão como `{{first_name\|"there"}}` | Não processados | Suportados. Campos vazios contam como ausentes. |
| Maiúsculas e minúsculas | `{{FIRST_NAME}}` funciona | Os caminhos diferenciam maiúsculas de minúsculas |
| Tags desconhecidas | Ficam na mensagem como foram escritas | Renderizadas como vazio |

No painel, iniciar uma campanha a partir de um template MJML copia o documento MJML do template para a campanha.

### Sem acesso ao MJML

Durante a fase alfa, o Emailit compila o MJML de campanhas apenas para a equipe do Emailit. Para todos os outros, incluindo as chaves de API, `content_type: "mjml"` continua sendo o simples rótulo que era antes da fase alfa: `content` é armazenado como você o envia, você envia o HTML compilado em `html` e os envios usam as tags de mesclagem clássicas. Iniciar uma campanha a partir de um template MJML copia o HTML do template para uma campanha HTML.

## Automações

A etapa **Send email** faz referência a um template pelo ID (`tem_…`). Os templates MJML funcionam como qualquer outro: a etapa envia o HTML compilado do template e renderiza o Temple com as variáveis da automação. Consulte [E-mails de automações](/pt/docs/templates/temple/#automation-emails).

Nas configurações da etapa, **Design a new email** cria um template MJML a partir de um design inicial, seleciona-o para a etapa e o abre no Visual Editor. **Edit email** abre o template MJML selecionado. As edições alteram o próprio template, então todas as etapas e chamadas à API que usam o template as recebem. Sem acesso ao MJML, a etapa mostra um link para o template.

## Edição colaborativa

Todos que abrem o mesmo template ou a mesma campanha MJML salvos editam um único rascunho compartilhado em tempo real, em qualquer um dos editores:

- **Presença**: a barra superior mostra quem mais está editando e o que cada pessoa está fazendo. No Visual Editor, você vê as seleções e os cursores dos outros e um breve destaque na cor de cada um onde eles alteram algo. **Layers** mostra quem selecionou um componente. Selecione o avatar de alguém para ir até a seleção dessa pessoa.
- **As edições são mescladas**: alterações em componentes, atributos ou partes diferentes de um texto se combinam em vez de sobrescrever umas às outras. Enquanto alguém digita em um texto no canvas, esse texto fica bloqueado para os outros.
- **Code Editor**: as suas alterações são mescladas no rascunho compartilhado enquanto você digita. As alterações dos outros aparecem no seu código quando você para de digitar, para que o cursor não salte. Se o seu código tiver um erro de sintaxe, elas esperam até você corrigi-lo.
- **Desfazer e refazer** desfazem apenas as suas próprias alterações.
- **Salvar**: há um único **Save** para todos. A barra superior mostra as alterações não salvas do rascunho inteiro e quem salvou por último. O envio sempre usa a versão salva.
- **O rascunho é mantido**: fechar o editor ou perder a conexão não faz você perder as alterações. Elas ficam no rascunho compartilhado e são sincronizadas quando você volta a ficar on-line. Reabrir o editor restaura as alterações não salvas, e você pode descartá-las para voltar à versão salva.
- **Salvo em outro lugar**: quando o template ou a campanha é salvo fora do editor (pela API, pelo MCP ou pelo **Edit with AI**) enquanto está aberto, um rascunho sem alterações não salvas passa para a versão salva. Um rascunho com alterações não salvas as mantém e oferece **Load saved version** ou **Keep this draft**.
- **Excluído**: se o template ou a campanha for excluído, ou deixar de ser MJML, enquanto você edita, o editor avisa e permite copiar o MJML.

A edição colaborativa exige MJML salvo e válido. Os templates e as campanhas cujo MJML não pode ser interpretado, ou que ainda não foram salvos como MJML, abrem sem ela: cada pessoa edita sozinha e o último salvamento prevalece. O editor avisa isso em um banner. Em um workspace suspenso, os editores ficam somente leitura.

## Versões e atualizações

O Emailit compila com uma versão do MJML por vez, atualmente a 5.4.1. Cada documento armazenado registra o `mjml_version` ao qual se destina, e o Emailit o verifica sempre que o documento é compilado:

| `mjml_version` do documento | Resultado |
| --- | --- |
| 5.4.1 | Compilado como está |
| Ausente | A 5.4.1 é presumida (`document.assumed-mjml-version`, info) |
| Outra versão 5.x | Compilado com a 5.4.1 (`document.mjml-upgraded`, info) |
| 4.x | Migrado para o MJML 5 e depois compilado com a 5.4.1 (`document.mjml-upgraded`, info). O MJML 4 e o MJML 5 têm os mesmos componentes e atributos; o HTML gerado é um pouco diferente. |
| 3.x ou anterior | Rejeitado com `document.unsupported-mjml-version` |
| Uma versão principal mais nova | Rejeitado com `document.unsupported-mjml-version` |

Um documento cujo `schema_version` é mais novo do que o Emailit consegue ler é rejeitado com `document.unsupported-schema`. Ao salvar, o documento é armazenado com o `mjml_version` e o `schema_version` atuais. Confira a prévia depois de uma atualização.

Os editores mostram a versão e o changelog deles. Quando um documento foi salvo com uma versão do editor mais nova do que a da página que você tem aberta, o editor pede que você recarregue a página.

## MJML para agentes de IA

[Obter a referência do MJML](/pt/docs/api-reference/mjml/reference/) dá às ferramentas de desenvolvimento e aos modelos de IA o que eles precisam para escrever MJML válido para o Emailit: todos os componentes, com os elementos pais, os filhos e os atributos permitidos (tipo e valor padrão), o guia do Temple, as regras de escrita e um `reference_text` compacto em texto simples para prompts.

No [servidor MCP](/pt/docs/mcp/), as sessões da equipe do Emailit também recebem estas ferramentas no toolset `templates`:

| Ferramenta | Descrição |
| --- | --- |
| `get-mjml-reference` | A referência como texto: as versões do MJML e dos editores, as regras de escrita, o guia do Temple e a referência de componentes. |
| `validate-mjml` | [Validar MJML](/pt/docs/api-reference/mjml/validate/): `valid` e os diagnósticos. |
| `render-mjml` | [Renderizar MJML](/pt/docs/api-reference/mjml/render/): o HTML compilado e, com `variables`, `rendered_html`. |
| `create-template`, `update-template` | Também aceitam `editor: "mjml"` e `source`, a marcação MJML ou o MJML JSON como string. O Emailit compila o HTML. |
| `create-campaign`, `update-campaign` | Também aceitam `content_type: "mjml"` com o MJML em `content`. |

Quando um salvamento falha na validação, o erro da ferramenta lista os diagnósticos de erro e de aviso com os números de linha, para que o agente possa corrigir o código-fonte. Um fluxo típico: ler a referência, escrever o MJML, chamar `validate-mjml` até que `valid` seja `true`, salvar com `create-template` e depois conferir a versão de um destinatário com `render-mjml`. As outras sessões não veem essas ferramentas nem esses parâmetros.

## No painel

- **Templates**: crie um template e escolha **MJML Visual Editor (Alpha)** ou **MJML Code Editor (Alpha)**.
- **Visual Editor**: arrastar e soltar sobre o e-mail renderizado, uma árvore de camadas, um painel de propriedades para cada atributo do MJML, configurações do documento (head, fontes, estilos e atributos padrão), variáveis do Temple em qualquer propriedade e blocos condicionais em volta de componentes.
- **Code Editor**: preenchimento automático para tags, atributos e valores do MJML e para o Temple, validação inline com correções rápidas e formatação.
- **Os dois editores**: uma prévia ao vivo para desktop e celular, compilada no navegador com o MJML 5.4.1, uma prévia com dados de exemplo (com o Temple renderizado), uma lista de problemas e um assistente de IA, quando ele está ativado. Você pode alternar entre Visual e Code no mesmo documento; para mudar para Visual, o código não pode ter erros de sintaxe. Não é possível salvar enquanto o MJML tiver erros.
- **Edição colaborativa**: os colegas que abrem o mesmo template ou a mesma campanha editam juntos em tempo real. Consulte [Edição colaborativa](#editing-together).
- **Edit with AI**: descreva uma alteração em um template ou em uma campanha MJML sem abrir o editor.
- **Importação**: um arquivo `.mjml`, um arquivo `.json` com MJML JSON ou com um documento MJML do Emailit, ou um ZIP com `template.mjml` e uma pasta `images/` na raiz.
- **Exportação**: MJML (marcação), MJML JSON (o documento armazenado), HTML ou um ZIP com `template.mjml`, `template.html` e `images/`. A exportação funciona para todos.
- **Campanhas**: escolha o MJML Visual Editor ou o MJML Code Editor para o conteúdo da campanha.
- **Automações**: crie o e-mail de uma etapa **Send email** ali mesmo. Consulte [Automações](#automations).

## Veja também

- [Criar e editar templates](/pt/docs/templates/editors/)
- [Linguagem de templates Temple](/pt/docs/templates/temple/)
- [Referência da API de MJML](/pt/docs/api-reference/mjml/)
- [Importar e exportar](/pt/docs/templates/import-export/)

---
Fonte: https://emailit.com/pt/docs/templates/mjml/
