Como Enviar E-mail via API em JavaScript (Tutorial do Node.js)
Pule o boilerplate do SMTP. Este guia mostra como enviar e-mails em Node.js usando o API unificada de e-mail Unipile - com código para copiar e colar para Gmail, Outlook e SMTP em menos de 10 linhas de JavaScript.
import { UnipileClient } from 'unipile-node-sdk';
const client = novo UnipileClientprocess.env.UNIPILE_DSN,
process.env.UNIPILE_TOKEN
);
await cliente.email.enviar({
account_id: 'SEU_ID_DA_CONTA',
para: [{ nome_exibicao: 'Alice',
identificador: 'alice@example.com' }],
assunto: 'Olá do Node.js',
body: 'Enviado via Unipile!
'
});Exemplo de Node.js de 5 linhas
Se você já sabe o que é um Enviar API de e-mail e apenas quero enviar código JavaScript da API de e-mail que realmente funcione, aqui está. O tutorial completo segue abaixo.
npm install unipile-node-sdkUNIPILE_DSN e UNIPILE_TOKEN para você .env arquivo.client.email.enviar()account_id, para, assuntoe corpo. Feito.import { UnipileClient } from 'unipile-node-sdk';
const client = novo UnipileClientprocess.env.UNIPILE_DSN,
process.env.UNIPILE_TOKEN
);
const resultado = aguardar cliente.email.enviar({
account_id: 'acc_xxxxxxxxxxxxxxxx',
para: [{
nome_de_exibição: 'Alice Martin',
identificador: 'alice@acme.com'
}],
assunto: 'Olá do Node.js',
body: 'Enviado via API Unipile!
'
});
console.log(resultado); // { tracking_id: 'msg_...' }Pré-requisitos e Configuração
Antes de poder usar o fluxo de trabalho JavaScript da API de envio de e-mail em produção, você precisa de quatro coisas: uma versão compatível do Node.js, o SDK Unipile, uma chave de API e um endpoint DSN.
fetch e de topo await. É recomendado usar o Node 20 LTS para produção. Verifique sua versão com node -v.api4.unipile.com:13444Ambos são necessários para inicializar o cliente..mjs arquivos ou conjunto "tipo":"módulo" em package.json. Para CommonJS, dinâmico import() funciona também - exemplos mostrados abaixo.npm install unipile-node-sdkyarn add unipile-node-sdkpnpm adicionar unipile-node-sdk# Credenciais da Unipile (nunca envie este arquivo para o commit)
UNIPILE_DSN=https://api4.unipile.com:13444
UNIPILE_TOKEN=seu_token_de_acesso_aqui
# O ID da conta de e-mail vinculada
ID_DA_CONTA_DE_EMAIL=acc_xxxxxxxxxxxxxxxxAdicionar .env para você .gitignore. Usar dotenv ou o Node 20.6+ nativo --arquivo-env bandeira para carregá-la: node --env-file=.env send.mjs.
Conectando Sua Primeira Conta de E-mail
O API de e-mail unificada usa um único account_id para abstrair as diferenças de fornecedores. Vincule uma conta uma vez e, em seguida, chame client.email.enviar() idêntico em todos os três provedores.
Escolha seu provedor abaixo para ver o trecho exato do Node.js. O account_id retornado é o que você armazena e reutiliza para cada envio subsequente.
import { UnipileClient } from 'unipile-node-sdk';
const client = novo UnipileClientprocess.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
// Etapa 1: gerar um link OAuth hospedado para o Gmail
const { url } = aguardar cliente.conta.criarLinkDeAutenticaçãoHospedado({
tipo: 'Google',
success_redirect_url: process.env.URL_DE_RETORNO_OAUTH,
failure_redirect_url: process.env.URL_DE_RETORNO_OAUTH ?erro=1',
});
// Passo 2: redirecione seu usuário para `url`
console.log('Redirecionar usuário para:', url);
// Passo 3: Unipile envia o account_id para sua callback
// Armazene isso: process.env.EMAIL_ACCOUNT_ID = result.account_idimport { UnipileClient } from 'unipile-node-sdk';
const client = novo UnipileClientprocess.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
// Funciona para Outlook pessoal E Microsoft 365 / Exchange Online
const { url } = aguardar cliente.conta.criarLinkDeAutenticaçãoHospedado({
tipo: 'MICROSOFT',
success_redirect_url: process.env.URL_DE_RETORNO_OAUTH,
failure_redirect_url: process.env.URL_DE_RETORNO_OAUTH ?erro=1',
});
// Redireciona o usuário -> eles completam o fluxo OAuth da Microsoft
console.log('Redirecionar usuário para:', url);
// Veja: /syncing-emails-with-microsoft-graph-api-a-developers-guide/import { UnipileClient } from 'unipile-node-sdk';
const client = novo UnipileClientprocess.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
// SMTP/IMAP: passar credenciais diretamente (sem redirecionamento OAuth)
const account = aguardar cliente.conta.create({
tipo: 'IMAP',
imap: {
username: process.env.IMAP_USUÁRIO,
password: process.env.IMAP_SENHA,
host: process.env.IMAP_HOST,
porta: 993,
},
smtp: {
username: process.env.IMAP_USUÁRIO,
password: process.env.IMAP_SENHA,
host: process.env.SMTP_HOST,
porta: 587,
},
});
console.log(account.account_id); // guarde istoEnviando seu primeiro e-mail do Node.js
Três padrões prontos para produção para o fluxo de trabalho da API de envio de e-mail em JavaScript: texto simples, HTML com CC/CCO e leitura do objeto de resposta. Todos usam o mesmo client.email.enviar() ligar.
import { UnipileClient } from 'unipile-node-sdk';
const client = novo UnipileClientprocess.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
const resultado = aguardar cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,
para: [{ nome_exibicao: 'Bob', identificador: 'bob@example.com' }],
assunto: 'Bem-vindo à plataforma',
body: 'Oi Bob, sua conta está pronta.',
});
console.log(result.tracking_id); // msg_xxxxxxxxxxxxxxxxconst resultado = aguardar cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,para: [{ display_name: 'Alice', identificador: 'alice@acme.com' }],
cc: [{ display_name: 'Gerente', identificador: 'boss@acme.com' }],
bcc: [{ nome_exibido: 'Auditoria', identificador: 'audit@internal.io' },
assunto: 'Sua fatura #1042',
// Corpo do HTML - o provedor o renderiza nativamente
body: `
Fatura #1042
Valor devido: $299
Pagar agora
`,
});
console.log('Enviado:', result.tracking_id);| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account_id | string | Obrigatório | ID da conta de e-mail vinculada para enviar |
para | Destinatários[] | Obrigatório | Matriz de {nome_exibicao, identificador} objetos |
assunto | string | Obrigatório | Assunto do email |
corpo | string | Obrigatório | Texto simples ou string HTML |
cc | Destinatários[] | Opcional | Copiar destinatários ocultos |
Cópia oculta | Destinatários[] | Opcional | Cópia oculta |
from | Destinatário | Opcional | Substituir nome de exibição do remetente |
responder_para | string | Opcional | ID da mensagem do provedor para responder (threads) |
anexos | Matriz | Opcional | Matriz de [nome do arquivo, Buffer] tuplas |
cabeçalhos_personalizados | objeto[] | Opcional | Matriz de cabeçalhos X personalizados |
opções_de_rastreamento | objeto | Opcional | {abre, links, rótulo} - ativar rastreamento de abertura/clique |
Obtenha sua chave de API, vincule uma conta Gmail ou Outlook em minutos e execute os exemplos do Node.js deste guia contra caixas de correio reais.
Enviando anexos no Node.js
O anexos campo aceita um array de [nome do arquivo, Buffer] tuplas. Leia o arquivo com o Node fs.readFileSync ou transmita com fs.promises.readFile.
fs.promises.readFile(caminho) para obter um Buffer, então passe ['nome_do_arquivo.pdf', buffer]. Funciona para PDF, DOCX, imagens, qualquer binário.cid: esquema. Faça referência ao mesmo nome de arquivo usado na tupla de anexos: <img src="cid:logo.png">.pdfkit), colete-o em um Buffer e anexe sem gravar em disco. Seguro para produção em serverless.import { UnipileClient } from 'unipile-node-sdk';
import promessas como fs } from 'node:fs';
const client = novo UnipileClientprocess.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
// Lê arquivo para um Buffer
const bufferPdf = aguardar fs.lerArquivo('./nota fiscal.pdf');
await cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,
para: [{ nome_exibido: 'Cliente', identificador: 'client@example.com' }],
assunto: 'Sua fatura está anexada',
body: 'Por favor, encontre sua fatura em anexo.
',
anexos: [
['nota fiscal.pdf', bufferPdf], // [nome do arquivo, Buffer]
],
});const [logo, relatório] = aguardar Promise.allfs.lerArquivo('./logo.png'),
fs.lerArquivo('./relatório.xlsx'),
]);
await cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,
para: [{ nome_exibido: 'Equipe', identificador: 'team@acme.com' }],
assunto: 'Relatório do Q1',
body:
Relatório Q1
Veja a planilha anexa para detalhes.
`,
anexos: [
['logo.png', logo], // inline via cid:logo.png no corpo
['relatório.xlsx', relatório], // anexo padrão
],
});Respostas, Tópicos e Rastreamento
Vá além dos envios básicos: respostas encadeadas, cabeçalhos personalizados para idempotência, rastreamento de abertura/clique via webhooks e enviar email em nome de um usuário.
1
Respondendo a um tópico
Passe o ID da mensagem do provedor (retornado na resposta original do envio ou ao listar emails) como responder_para. Unipile injeta o correto Em-Resposta-A e Referências cabeçalhos para que as respostas sejam encadeadas corretamente no Gmail, Outlook e clientes IMAP.
await cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,
para: [{ nome_exibido: 'Alice', identificador: 'alice@acme.com' }],
assunto: 'Re: Sua pergunta',
body: 'Obrigado por entrar em contato! Aqui está a resposta...
',
// ID da mensagem do provedor do e-mail original
responder_para: 'msg_xxxxxxxxxxxxxxxx',
});
2
Cabeçalhos personalizados e idempotência
Uso cabeçalhos_personalizados para adicionar qualquer X- cabeçalho. Um padrão comum é X-Idempotency-Key para evitar envios duplicados ao tentar novamente após um tempo limite de rede.
import { randomUUID } from 'node:crypto';
await cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,
para: [{ nome_exibido: 'Bob', identificador: 'bob@example.com' }],
assunto: 'Confirmação de pedido #9981',
body: 'Seu pedido está confirmado.
', custom_headers: [
{ name: 'X-Idempotency-Key', valor: UUID Aleatório},
{ nome: 'X-Order-ID', valor: '9981' },
],
});
3
Rastreamento de aberturas e cliques via webhooks
Habilitar acompanhamento em opções_de_rastreamento. Unipile dispara um evento de webhook (email.aberto / email.link_clicado) para a sua URL de webhook registrada com o rótulo você define aqui para poder correlacionar eventos às suas IDs internas.
await cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,
para: [{ nome_exibido: 'Chumbo', identificador: 'lead@prospect.com' }],
assunto: 'Acompanhando seu teste',
body: 'Oi, queria dar uma verificada...
',
tracking_options: {
opens: true, // dispara webhook de email.aberto
links: true, // aciona o webhook email.link_clicked
rótulo: 'crm_lead_12345', // seu ID de correlação interna
},
});
4
Enviando em nome de outro usuário
Ao construir aplicativos SaaS multilocatário, cada usuário final vincula sua própria conta de e-mail. Armazene o account_id por usuário em seu banco de dados e passá-lo no momento do envio. Veja o guia completo em Como enviar e-mail em nome de um usuário.
// Cada usuário tem seu próprio account_id vinculado armazenado em seu banco de dados
async function enviarComoUsuario(userId, para, assunto, corpo) {
const usuário = aguardar banco de dados.obterUsuário(identificadorDoUsuario);
return cliente.email.enviaraccount_id: user.unipile_account_id, // por-usuário
para, assunto, corpo,
});
}
// O e-mail é enviado do Gmail de Alice, não do endereço do seu servidor
await enviarComoUsuario('user_alice', destinatários, assunto, corpo);Trabalhando em Python? Veja nosso Implementação Python guia.
Tratamento de Erros e Tentativas
Falhas de rede e limites de taxa são inevitáveis em escala. Aqui está um padrão async/await de nível de produção para sua implementação JavaScript da API de envio de e-mail – com retrocesso exponencial e registro estruturado usando Winston ou Pino.
id_rastreamento está populado. Nenhuma nova tentativa necessária.Tentar Novamente Após cabeçalho. Use retrocesso exponencial.UNIPILE_TOKEN Variável de ambiente. Não tentar novamente - corrigir credenciais.account_id não existe ou foi revogada. Reative a conta.import { UnipileClient } from 'unipile-node-sdk';
import logger from './logger.mjs'; // Winston or Pino instance
const client = new UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
async function sendWithRetry(payload, maxAttempts = 4) {
let attempt = 0;
while (attempt < maxAttempts) {
try {
const result = await client.email.send(payload);
logger.info({ tracking_id: result.tracking_id }, 'Email sent');
return result;
} catch (err) {
const status = err?.status ?? err?.statusCode;
// Do not retry on client errors (4xx except 429)
if (status >= 400 && status !== 429 && status < 500) {
logger.error({ status, err }, 'Non-retryable error');
throw err;
}
attempt++;
if (attempt >= maxAttempts) throw err;
// Exponential backoff: 1s, 2s, 4s, 8s...
const delay = 1000 * 2 ** (attempt - 1);
logger.warn({ attempt, delay, status }, 'Retrying...');
await new Promise(r => setTimeout(r, delay));
}
}
}
// Usage
await sendWithRetry({
account_id: process.env.EMAIL_ACCOUNT_ID,
to: [{ display_name: 'User', identifier: 'user@example.com' }],
subject: 'Your report is ready',
body: 'Click to download.
',
});Melhores Práticas de Segurança em Node.js
Seu UNIPILE_TOKEN concede acesso completo à API. Nunca o exponha do lado do cliente. Veja o completo Guia de segurança de API de e-mail para tópicos avançados, incluindo DKIM, SPF e rotação de tokens OAuth.
UNIPILE_TOKEN deve permanecer no servidor. Qualquer JavaScript do lado do navegador - incluindo componentes de cliente Next.js, frontend React ou Vite - NÃO deve importar o token diretamente./api/enviar-email. Em Express, um endpoint POST. Autentique seus próprios usuários primeiro, depois chame o servidor Unipile com o token do ambiente.account_id resta válido. Você não precisa lidar com a expiração do token de acesso.// client.js - NUNCA faça isso
const cliente = new UnipileClient(
'https://api4.unipile.com:13444',
'sk_live_xxxxxxxxxx' // exposto!
);
// app/api/send-email/route.js
export async function POST(req) {
// verifica autenticação primeiro
const session = await getServerSession();
if (!session) return new Response(null, { status: 401 });
const client = new UnipileClient(
process.env.UNIPILE_DSN, // apenas-no-servidor
process.env.UNIPILE_TOKEN // apenas-no-servidor
);
await client.email.send({...});
}
Armadilhas comuns (específicas do Node.js)
Estes são os erros mais frequentes que os desenvolvedores cometem ao integrar uma API de envio de e-mail em JavaScript pela primeira vez. Cada um é fácil de evitar assim que você conhece o padrão - e todos se aplicam igualmente ao contexto da API de envio de e-mail do Node.js.
await só funciona em módulos ES (.mjs ou "tipo":"módulo"). No CommonJS, coloque sua chamada send dentro de um assíncrono IIFE ou usar .then(). O SDK funciona em ambos - basta escolher o formato de módulo correto.// CommonJS: embrulhar em IIFE assíncrona
(assíncrono () => {
const { UnipileClient } = aguardar import('unipile-node-sdk');
const client = novo UnipileClientprocess.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
await cliente.email.enviar({ /* ... */ });
})();Promise.all envios simultâneos atingirão limites de taxa e causarão erros 429. Use um limitador de concorrência como p-limite para limitar requisições paralelas.import pLimite from 'p-limite';
const limite = pLimite(5); // máximo de 5 envios simultâneos
const resultados = aguardar Promise.alldestinatários.mapa(r => limite(() => cliente.email.enviar({
account_id: process.env.ID_DA_CONTA_DE_EMAIL,
para: [r], assunto, corpo,
})))
);Buffer objeto - não é uma string base64, não é uma string UTF-8. Se você tiver conteúdo base64 (por exemplo, de um webhook ou resposta de API), converta-o primeiro: Buffer.from(base64str, 'base64').// ERRADO: passando uma string
anexos: [['arquivo.pdf', 'JVBERi0xLjQ...']] // string base64 - problema!
// CORRETO: Objeto buffer
anexos: [['arquivo.pdf', Buffer.from(cadeia_base64, 'base64')]]
// ou do disco:
anexos: [['arquivo.pdf', await fs.lerArquivo('./arquivo.pdf')]]enviar() Chamada irá travar o processo no Node 15+. Sempre await o resultado ou anexar um .capturar() manipulador.// INCORRETO: fire-and-forget - trava em erro no Node 15+
cliente.email.enviar(carga útil); // sem await, sem .catch()
// CORRETO: sempre trate a promessa
await cliente.email.enviar(carga útil) // opção 1: await
.capturaerro => registrador.erro(err)); // opção 2: .catch()UNIPILE_TOKEN são apenas para o lado do servidor Node.js. O fetch do navegador diretamente para a API exporia seu token. Use uma rota de backend (rota de API Next.js, endpoint Express, função Netlify/Vercel) como proxy.account_id de uma conta Gmail, Outlook ou IMAP previamente vinculada. A API retorna 404 se o account_id estiver ausente ou tiver sido desvinculado.Perguntas frequentes
Perguntas frequentes sobre o envio de e-mails em JavaScript e Node.js com a API unificada de e-mail da Unipile.
unipile-node-sdk, inicializar UnipileClient com seu DSN e token, vincule uma conta Gmail ou Outlook via OAuth, e então chame client.email.enviar(). Nenhum servidor SMTP, nenhuma porta 587, nenhuma configuração TLS necessária do seu lado – a Unipile cuida da camada de transporte.Não - e você não deveria. Chamar a API do Unipile a partir do JavaScript do navegador exporia sua UNIPILE_TOKEN para qualquer usuário que abrir as Ferramentas do Desenvolvedor. Sempre chame a API a partir de um contexto Node.js do lado do servidor: uma rota do Express, uma rota de API do Next.js (app/api/), uma Vercel Edge Function ou uma Netlify Function.
Seu frontend envia uma requisição para seu próprio endpoint de backend, que autentica a sessão do usuário e, em seguida, chama o Unipile no lado do servidor.
O Nodemailer se conecta diretamente a um servidor SMTP a partir do seu processo Node.js. Ele exige que você gerencie credenciais SMTP, lide com TLS, configure DKIM por conta própria e resolva as peculiaridades de cada provedor separadamente.
A API de e-mail Unipile é uma camada de abstração em nuvem: você vincula contas via OAuth (sem necessidade de credenciais SMTP para Gmail/Outlook), obtém um SDK unificado e consistente para todos os provedores, e a Unipile cuida do transporte, novas tentativas e renovação de token. A contrapartida é que seus envios passam pela infraestrutura da Unipile em vez de uma conexão SMTP direta.
Sim. O unipile-node-sdk pacotes com definições de tipo TypeScript. Você obtém preenchimento automático completo e segurança de tipo para o enviar() carga útil, incluindo Destinatário, opções_de_rastreamento, e o tipo de resposta.
import { UnipileClient } from 'unipile-node-sdk';
// Tipos TS completos - autocompletar funciona no VSCode
const cliente: UnipileClient = novo UnipileClient(dsn, token);
const resultado = aguardar cliente.email.enviar({ /* digitado! */ });Para envios de alto volume, use um limitador de concorrência (por exemplo,. p-limite com 5 a 10 chamadas simultâneas), adicione exponential backoff em respostas 429 e distribua os envios entre várias contas vinculadas, se possível. Cada conta de e-mail vinculada tem seus próprios limites de envio definidos pelo provedor (Gmail: ~500/dia para contas comuns, mais alto para Workspace).
Para e-mails em massa/marketing de verdade em escala (milhões de destinatários), considere um ESP dedicado (Mailgun, SendGrid) juntamente com o Unipile para envios transacionais e baseados em OAuth.
Next.js: use rotas de API (app/api/enviar-email/route.js) ou Server Actions. Mantenha a instanciação do SDK apenas no lado do servidor.
Nuxt: rotas do servidor (server/api/send-email.post.tsO SDK é apenas para Node.js, portanto, não pode ser incluído em um composable ou plugin que é executado no cliente.
NestJS: criar um MóduloEmail com um serviço que envolve UnipileClient. Injete-o onde você precisar acionar envios - em controladores, trabalhos CRON ou manipuladores de eventos.
Ainda tem dúvidas? Nossa equipe está aqui para ajudar.