Atualizado em 19/06/2026
Todo e-mail que o WordPress dispara passa por uma única função: wp_mail(). Ela é uma fina camada sobre a biblioteca PHPMailer, incluída no núcleo. Entender essa pilha — função, filtros e o action de configuração — é o que permite enviar HTML corretamente, definir um remetente confiável e, principalmente, garantir entregabilidade. Este último ponto é onde a maioria dos sites tropeça, e é também onde mora a maior parte do trabalho de especialista. Se você ainda está se ambientando com pontos de extensão, vale revisar antes os hooks (actions e filters), já que tudo aqui é construído sobre eles.
A assinatura de wp_mail()
A função aceita cinco parâmetros, dos quais só os três primeiros são obrigatórios na prática:
<?php
// wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ): bool
$enviado = wp_mail(
'[email protected]', // string ou array de destinatários
'Seu pedido foi confirmado', // assunto
'Obrigado pela compra!' // corpo (texto puro por padrão)
);
if ( ! $enviado ) {
// Algo falhou no transporte — veja a seção sobre wp_mail_failed.
}
O retorno é um booleano que indica apenas se a mensagem foi aceita pelo transporte. Ele não garante que o e-mail chegou à caixa do destinatário — essa é uma distinção crucial que discutiremos em entregabilidade. O parâmetro $to aceita uma string ou um array; $headers aceita uma string com quebras de linha ou um array de linhas; e $attachments espera caminhos absolutos de arquivos no servidor.
Enviando HTML: o Content-Type
Por padrão, wp_mail() envia em text/plain. Se você colocar tags HTML no corpo sem mudar o Content-Type, o cliente de e-mail mostrará o markup cru (<p>, <a>…) como texto. Há duas formas de declarar HTML. A primeira, e mais segura, é passar o header diretamente na chamada — assim o tipo vale só para aquele e-mail:
<?php
$to = '[email protected]';
$subject = 'Bem-vindo à loja';
$message = '<h1>Olá!</h1>'
. '<p>Seu cadastro foi criado. '
. '<a href="https://exemplo.com/conta">Acessar minha conta</a>.</p>';
$headers = array(
'Content-Type: text/html; charset=UTF-8',
'From: Loja Exemplo <[email protected]>',
);
wp_mail( $to, $subject, $message, $headers );
A segunda forma é o filtro wp_mail_content_type. Ele é global: muda o tipo de todos os e-mails enquanto estiver ativo. Por isso, o padrão correto é adicioná-lo, enviar e removê-lo na sequência:
<?php
add_filter( 'wp_mail_content_type', 'meu_content_type_html' );
function meu_content_type_html() {
return 'text/html';
}
wp_mail( $to, $subject, $message );
// Reverte para não afetar e-mails do núcleo e de outros plugins.
remove_filter( 'wp_mail_content_type', 'meu_content_type_html' );
Armadilha clássica: deixar o filtro wp_mail_content_type permanentemente em text/html. Isso faz com que e-mails que o WordPress monta em texto puro (notificações de comentário, redefinição de senha) sejam interpretados como HTML, e o destinatário recebe um bloco contínuo sem quebras de linha. Prefira passar o Content-Type por header quando o e-mail é pontual; reserve o filtro para casos em que você realmente quer cobrir todos os envios e o reverta logo após.
Definindo o remetente: wp_mail_from e wp_mail_from_name
Sem configuração, o WordPress envia de [email protected] com o nome "WordPress". Esse remetente genérico prejudica tanto a marca quanto a entregabilidade. Ajuste-o com dois filtros:
<?php
add_filter( 'wp_mail_from', 'meu_email_remetente' );
add_filter( 'wp_mail_from_name', 'meu_nome_remetente' );
function meu_email_remetente( $original ) {
// Use SEMPRE um endereço do seu próprio domínio.
return '[email protected]';
}
function meu_nome_remetente( $original ) {
return 'Loja Exemplo';
}
Os callbacks recebem o valor original e devem retorná-lo (são filters, não actions). O endereço escolhido precisa pertencer ao domínio que assina os e-mails via SPF/DKIM; um From divergente do domínio de envio é um dos sinais mais fortes para um filtro de spam descartar a mensagem.
SMTP sem plugin: o action phpmailer_init
O wp_mail() instancia internamente um objeto PHPMailer. O action phpmailer_init entrega esse objeto por referência, e é o ponto oficial para configurar SMTP autenticado direto no código, sem instalar um plugin:
<?php
add_action( 'phpmailer_init', 'meu_smtp' );
function meu_smtp( $phpmailer ) {
$phpmailer->isSMTP();
$phpmailer->Host = 'smtp.seuprovedor.com';
$phpmailer->Port = 587; // 587 = STARTTLS; 465 = SMTPS
$phpmailer->SMTPAuth = true;
$phpmailer->SMTPSecure = 'tls'; // 'tls' p/ 587, 'ssl' p/ 465
// Credenciais via constantes do wp-config.php — nunca no banco/repositório.
$phpmailer->Username = defined( 'MEU_SMTP_USER' ) ? MEU_SMTP_USER : '';
$phpmailer->Password = defined( 'MEU_SMTP_PASS' ) ? MEU_SMTP_PASS : '';
}
Boa prática de segurança: defina MEU_SMTP_USER e MEU_SMTP_PASS no wp-config.php (ou em variáveis de ambiente do servidor) e nunca em campos de opção no banco nem versionadas no Git. Use a porta 587 com STARTTLS sempre que possível; 465 (SMTPS) é a alternativa quando o provedor exige TLS implícito. A escolha entre phpmailer_init e um plugin de SMTP dedicado é, na prática, uma decisão de manutenção: o plugin oferece logs e interface; o código mantém tudo versionado e sem dependências extras.
Entregabilidade: o que realmente importa
Aqui está o conhecimento que separa quem "manda e-mail" de quem garante que o e-mail chega. Em hospedagem compartilhada, o mail() do PHP entrega através de um servidor local sem autenticação e com IP de reputação muitas vezes ruim — o resultado é spam ou descarte silencioso. A correção tem duas frentes que se complementam:
- Transporte autenticado (SMTP): envie por um serviço de e-mail transacional ou pelo SMTP do seu provedor, com usuário e senha — via plugin ou via
phpmailer_init. Isso resolve a autenticação do envio. - Autenticação de domínio no DNS: configure os três registros que provam ao destinatário que você está autorizado a enviar pelo seu domínio:
| Registro DNS | O que faz | Por que importa |
|---|---|---|
| SPF | Lista os servidores autorizados a enviar pelo seu domínio | Sem ele, o From do seu domínio é tratado como possível falsificação |
| DKIM | Assina criptograficamente cada mensagem | Prova que o e-mail não foi adulterado em trânsito e veio mesmo do domínio |
| DMARC | Diz aos provedores o que fazer quando SPF/DKIM falham | Alinha o domínio do From com a autenticação e melhora a reputação |
Sem esses registros, mesmo um SMTP perfeito pode cair em spam, porque o destinatário não consegue confirmar que o seu domínio autorizou o envio. E lembre-se: o endereço em From precisa ser do domínio coberto por esses registros — usar um @gmail.com como remetente em um envio que sai do seu servidor falha o alinhamento de DMARC e tende a ser rejeitado.
Depuração: capturando o erro com wp_mail_failed
Quando wp_mail() retorna false, o motivo real fica em um objeto WP_Error que o WordPress dispara pelo action wp_mail_failed. Registrá-lo é a forma correta de depurar — autenticação recusada, host errado, porta bloqueada, tudo aparece ali:
<?php
add_action( 'wp_mail_failed', 'meu_log_de_email' );
function meu_log_de_email( $wp_error ) {
// $wp_error é um objeto WP_Error com o motivo da falha.
if ( is_wp_error( $wp_error ) ) {
error_log( '[wp_mail] Falha no envio: ' . $wp_error->get_error_message() );
// Os dados do envio também vêm no objeto, úteis para diagnóstico:
$data = $wp_error->get_error_data();
if ( ! empty( $data['to'] ) ) {
error_log( '[wp_mail] Destinatário(s): ' . implode( ', ', (array) $data['to'] ) );
}
}
}
Combine isso com o retorno booleano: trate o false no seu fluxo (não dê o cadastro como concluído, por exemplo) e use o wp_mail_failed para entender por quê. Em desenvolvimento, você também pode habilitar o debug do SMTP definindo $phpmailer->SMTPDebug = 2; dentro do phpmailer_init — apenas nunca deixe isso ligado em produção, pois despeja a conversa SMTP no output.
Onde o WooCommerce entra
As notificações transacionais do WooCommerce — "pedido recebido", "processando", "concluído", redefinição de senha do cliente — são, no fim, chamadas a wp_mail() com templates HTML por cima. Isso tem uma consequência prática importante: configurar SMTP e remetente conserta a entregabilidade da loja inteira de uma vez, sem precisar mexer e-mail por e-mail. O que muda no WooCommerce é a camada de gatilhos e templates (quais eventos disparam, qual layout usar), e isso é assunto do artigo sobre e-mails transacionais do WooCommerce.
Resumo: header, filtro ou hook?
| Header / filtro / hook | Tipo | Efeito |
|---|---|---|
Content-Type: text/html (header) | Header na chamada | Envia aquele e-mail como HTML, sem afetar os demais |
wp_mail_content_type | Filter (global) | Muda o tipo de todos os e-mails — reverta após o envio |
wp_mail_from | Filter | Define o endereço do remetente (From) |
wp_mail_from_name | Filter | Define o nome exibido do remetente |
phpmailer_init | Action | Acessa o PHPMailer p/ configurar SMTP (host, porta, auth) |
wp_mail_failed | Action | Recebe o WP_Error da falha — use para log e depuração |
Armadilhas comuns
- HTML sem
Content-Type: o e-mail chega com as tags visíveis como texto. Declare o tipo por header ou filtro. - Filtro de
Content-Typenão revertido: quebra a formatação de todos os e-mails em texto puro do site. Sempre remova o filtro após o envio pontual. Fromdivergente do domínio: derruba o alinhamento de SPF/DKIM/DMARC e manda o e-mail para o spam. Use um endereço do próprio domínio.- Anexos por caminho relativo:
$attachmentsexige caminho absoluto no servidor; um caminho relativo simplesmente não anexa. - Confiar no retorno
true: ele só diz que o transporte aceitou a mensagem, não que ela chegou. Entregabilidade depende de SMTP + DNS, não do booleano. - Credenciais SMTP no banco ou no repositório: guarde usuário e senha em constantes do
wp-config.phpou variáveis de ambiente.
Boas práticas
- Prefira SMTP autenticado a
mail()em qualquer site que dependa de e-mail (loja, formulário, login). - Configure SPF, DKIM e DMARC no DNS antes de culpar o WordPress por e-mails no spam.
- Use um remetente do seu domínio, com nome reconhecível, alinhado à autenticação.
- Para HTML pontual, passe o
Content-Typepor header; para envios em lote, use o filtro e reverta-o. - Sempre registre falhas com
wp_mail_failede trate o retorno booleano no fluxo da aplicação. - Mantenha a configuração de envio em um plugin via hooks, não dentro do tema, para não perdê-la em uma troca de template.
Perguntas frequentes
Por que o e-mail do WordPress cai na caixa de spam?
Na grande maioria dos casos não é o WordPress — é o transporte. Em hospedagem compartilhada, a função wp_mail() recorre ao mail() do PHP, que entrega via servidor local sem autenticação. Provedores como Gmail e Outlook desconfiam disso. A solução de especialista é enviar por SMTP autenticado (via plugin dedicado ou pelo action phpmailer_init) e configurar SPF, DKIM e DMARC no DNS do seu domínio. Além disso, o endereço em From precisa ser do seu próprio domínio — nunca um @gmail.com qualquer.
Como envio um e-mail em HTML com wp_mail()?
Por padrão wp_mail() envia em texto puro. Para HTML você precisa declarar o Content-Type: ou passando o header 'Content-Type: text/html; charset=UTF-8' na chamada, ou via filtro wp_mail_content_type. Se você usar o filtro, reverta-o logo após o envio, senão todos os outros e-mails do site (inclusive os do núcleo e de plugins) passarão a ser tratados como HTML.
Como mudo o nome e o endereço do remetente?
Com os filtros wp_mail_from (o endereço) e wp_mail_from_name (o nome exibido). Por padrão o WordPress usa wordpress@seudominio, que costuma cair em spam por ser genérico. Defina um endereço real do seu domínio e um nome reconhecível. Garanta que esse endereço esteja autorizado pelo SPF/DKIM do domínio.
Preciso de um plugin de SMTP ou dá para fazer só com código?
Os dois funcionam. Um plugin de SMTP é a rota mais simples e auditável para quem não quer manter código. Mas tecnicamente o action phpmailer_init dá acesso ao objeto PHPMailer que o WordPress usa por baixo, e ali você define Host, Port, SMTPAuth, usuário e senha. Em ambos os casos guarde as credenciais fora do banco — em constantes no wp-config.php ou em variáveis de ambiente.
wp_mail() retornou false. Como descubro o motivo?
wp_mail() retorna true se a mensagem foi entregue ao transporte (não garante a chegada na caixa do destinatário) e false se houve erro antes disso. Para ver o erro real, use o action wp_mail_failed, que recebe um objeto WP_Error com a mensagem do PHPMailer (autenticação recusada, host inválido, etc.). Registre esse erro em log para depurar.
Os e-mails do WooCommerce usam wp_mail()?
Sim. As notificações transacionais do WooCommerce (pedido recebido, processando, concluído) são construídas sobre wp_mail(). Portanto, configurar SMTP e o remetente corrige a entregabilidade tanto dos e-mails do núcleo quanto dos da loja de uma só vez. O que muda no WooCommerce é a camada de templates e gatilhos — veja o artigo sobre e-mails transacionais do WooCommerce.