📧 Contatando o Usuário: Testando o Envio de E-Mails
Uma aplicação, diversas vezes, precisa entrar em contato com o usuário, mas eu não estou falando da interface do usuário, o assunto desse post é o envio de e-mails.
Olha,
- Se cadastrou? E-mail de ativação de conta.
- Precisar recuperar a senha? E-mail de novo.
- Fez alterações na conta? Um e-mail de aviso.
- Alertas e notificações? Vai de e-mail também.
Que a realidade é essa é indiscutível.
Para quem tá iniciando, é muito comum implementar isso já para "produção" e verificar se tá funcionando enviando mensagens para as contas de e-mail que possui.
Porém, convenhamos, ficar enviando e-mails para as suas próprias contas como teste é péssimo. No mínimo você fica preso a um único endereço para testar.
Um bom ambiente de testes precisa permitir que mais cenários possam ser validados. E é aqui que o MailHog
entra, pois ele é um servidor SMTP (Simple Mail Transfer Protocol) "falso".
E o que é um Servidor SMTP
?
Basicamente, é pra onde você envia os seus e-mails para que eles sejam enviados ao destinatário (é meio o que o Correios faz).
Figura 1: Fluxo de Envio de E-Mail Simplificado
Mas como o MailHog
é um servidor de SMTP falso, ele vai fazer algo um pouquinho diferente. Nele, TODOS os e-mails que são recebidos (ou seja, que você envia para ele, pela porta 1025
), ao invés de serem redirecionados ao e-mail do destinatário, são centralizados e acessíveis ao desenvolvedor por meio de uma interface web (acessível pela porta 8025
).
Figura 2: Fluxo de Envio de E-Mail com MailHog
Foi isso que implementei no MinhaDespesa mais recentemente, meu projetinho pessoal onde me aprofundo no desenvolvimento web usando PHP. "Só" precisei baixar a imagem do MailHog
e subir o container com docker compose up
.
mailhog:
image: mailhog/mailhog:latest
container_name: mailhog
restart: always
ports:
- 1025:1025
- 8025:8025
Levando o e-mail até o servidor...
Bem, quando disse "só" eu exagerei, não foi só isso, agora vem a parte mais interessante. O servidor (MailHog
) estava de pé, mas ainda faltava configurar a máquina para enviar o e-mail para àquele servidor em específico.
Eu estou usando a imagem php:8.2-apache
e a ferramenta (ou agente) padrão no PHP é o sendmail
, que não vem instalado, mas é o que ele procura quando uso o mail()
.
O sendmail
é um MTA (Mail Transfer Agent) robusto e muito completo (pode atuar como servidor SMTP, recebe e-mails, gerencia filas, faz roteamento e etc.). Para simplesmente enviar e-mails até o MailHog
ele é até robusto demais. Explorando mais sobre isso descobri outra solução: msmtp
.
O msmtp
é um Cliente SMTP e ele faz – quase que exclusivamente – a funcionalidade que precisava: encaminha o e-mail para um servidor SMTP. Agora, só instalar no container através do Dockerfile
:
# Baixa o `msmtp`
RUN apt-get install -y msmtp
# Copia o arquivo de configuração para o container
COPY msmtprc /etc/msmtprc
# Muda o dono (CHange OWNer) do arquivo e passa a ser do usuário e grupo www-data
RUN chown www-data:www-data /etc/msmtprc
# Dentro de `msmtp.ini` muda o executável para o msmtp
RUN echo "sendmail_path = /usr/bin/msmtp -t -i" > /usr/local/etc/php/conf.d/msmtp.ini
O arquivo msmtprc
ficou assim
defaults
auth off
tls off
logfile /var/log/msmtp.log
account default
host mailhog
port 1025
from [email protected]
Agora e-mails à vontade
Finalmente, quando chamo a função mail()
no PHP, ao invés do utilitário procurado ser o sendmail
(que não estava instalado) agora é o msmtp
.
$to = $user->email;
$subject = 'Confirmação de cadastro';
$message = 'Clique no link para confirmar seu registro: http://localhost:8080/register/confirm?token=' . $user->token;
$headers = 'From: [email protected]' . "\r\n" . 'Reply-To: [email protected]' . "\r\n" . 'X-Mailer: PHP/' . phpversion();
$sent = mail($to, $subject, $message, $headers); # true se o e-mail foi enviado e falso caso contrário
Isso me permite testar o cadastro do usuário com ativação de conta por e-mail utilizando diversos e-mails que não são meus (sem incomodar nenhum dos meus amigos).
O que fica de aprendizado maior, pra mim, é que mesmo que eu não precisasse ter feito isso, afinal é um projeto pessoal, não me contive, me expus à essa experiência e agora tenho certeza que estou mais apto para lidar com problemas semelhantes, o que é recompensador. É assim que se torna experiente, fazendo o dever de casa. Então se exponha, é importante para evoluir.
Algum comentário a respeito? Não sou nem de longe o maior conhecedor de como e-mails funcionam, mas sinto que entendi a superficie desse assunto. Agora é continuar estudando.