Enviando e-mail com SendGrid no ZF2

Post publicado em 07/07/2016 21:35 Última atualização em 17/12/2017 14:36

O envio de e-mails é algo essencial em aplicações, seja web ou mesmo em Apps e existem diversas maneiras de se implementar. Você pode criar um server específico para e-mails e ter de cuidar de tudo, pode enviar e-mails via SMTP diretamente com sua conta do gmail ou pode simplesmente passar essa responsabilidade a alguém (uma aplicação) que cuidará disso para você. É isso que mostrarei neste post. Recentemente tive uma experiência não muito boa com disparo de e-mails transacionais em servers da Digital Ocean. Não por culpa deles, é claro. A Digital Ocean tem uma política que de imediato bloqueia disparos de e-mails de suas droplets. Para tornar possível, deve ser aberto um chamado, explicar o motivo da liberação solicitada e confirmar que está ciente de que o mau uso acarreta em bloqueio automático e sem aviso prévio. Em meu cenário, configurei tudo bonitinho, cuidei para enviar e-mails somente em momentos estritamente necessários mas tudo foi em vão. Pouco tempo depois, simplesmente meus servers não mais enviavam e-mails. Isto porque houveram diversas tentativas de invasão e consequentemente de disparos de spam. O trabalho foi grande, foi um bom tempo instalando todos os pacotes e configurando certinho, para pouco tempo depois todo o serviço ser perdido.  Foi então que decidi, tirar de mim essa responsabilidade. O serviço escolhido foi o SendGrid que de imediato dá muitos disparos gratuítos ;) Minha aplicação foi construída com o Zend Framework 2. Toda a documentação do SendGrid é muito clara e foi super fácil integrar. Quando procurei por algo pronto para o Zend, somente localizei um exemplo feito em ZF1. Para o ZF2 não havia nenhum módulo que pudesse disponibilizar o SendGrid como um meio de transporte (normalmente utilizado Sendmail ou Smtp), foi então que criei um. Com este módulo, é possível realizar disparos de e-mails transacionais pelo SendGrid, basta o carregar, incluir sua apiKey (obtida diretamente no SendGrid) e pronto, ao invés de utilizar o transport como Smtp ou Sendmail, basta utilizar o SendGridTransport!  

Requisitos

Para o acompanhamento dos exemplos a seguir você deve estar com uma instalação do Zend Framework 2 rodando a pleno vapor. Se ainda não fez, siga este tutorial: https://framework.zend.com/manual/2.4/en/user-guide/skeleton-application.html

Instalando

A instalação se dá somente pelo Composer.
composer require andrebian/sendgrid-transport-module

Configurando

O primeiro passo para a correta configuração é informar que o módulo SendGridTransportModule será carregado em sua aplicação. No arquivo config/application.config.php ou config/modules.config.php, adicione o módulo necessário:
// config/application.config.php
return [
    'modules' => [
        'YourPreviousModules',
        'SendGridTransportModule'
    ],
    'module_listener_options' => [
        'module_paths' => [
            './module',
            './vendor',
        ],
        'config_glob_paths' => [
            'config/autoload/{{,*.}global,{,*.}local}.php',
            'module/{*}/config/autoload/{{,*.}global,{,*.}local}.php',
        ],
    ]
];
Em seguida, caso tenha um arquivo de configurações de e-mail em sua pasta config/autoload, adicione a ApiKey (saiba como obter) de sua conta no SendGrid. Caso não possua nenhum arquivo de configuração ainda, crie um. Pode ser config/autoload/mail.global.php.
// config/autoload/mail.global.php

return array(
    'mail' => array(
        'sendgrid' => array(
            'api_key' => 'YOUR_API_KEY',
        )
    )
);
Pronto, neste ponto o módulo está instalado e configurado, pronto para ser carregado em sua aplicação.

Utilizando

Existem 2 formas básicas de utilizar o SendGrid como transporte de e-mails. A primeira é através de um serviço já registrado ao carregar o módulo e a segunda é configurar o módulo no local desejado para uso. Veremos ambas.

Utilizando a partir de um serviço

Utilize o ServiceLocator do Zend para obter o SendGridTransport já configurado e pronto para uso. O exemplo básico será realizado em um controller, apenas para rápida exmplificação.
// Em um Controller qualquer
$sendGridTransport = $this->getServiceLocator()->get('SendGridTransport');

// Exemplo completo
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Mail;

class SomeController extends AbstractActionController
{
    public function someAction()
    {
        $mail = new Mail\Message();
        $mail->setBody('This is the text of the email.');
        $mail->setFrom(new Mail\Address('test@example.org', 'Sender\'s name'));
        $mail->addTo(new Mail\Address('some@address.com', 'User Name'));
        $mail->setSubject('TestSubject');

        $sendGridTransport = $this->getServiceLocator()->get('SendGridTransport');
        $sendGridTransport->send($mail);

        return new ViewModel();
    }
}
Simples não?! O exemplo acima criar uma mensagem para ser enviada, localiza o serviço que disponibiliza o SendGrid como um meio de transporte para envio de e-mails e por fim envia o e-mail.

Utilizando diretamente

Caso prefira ter mais controle, pode utilizar somente o SendGridTransport diretamente. Lembrando que terá de o configurar manualmente, diferente do serviço já registrado. Vale lembrar também que mesmo ao utilizar diretamente, o serviço permanece registrado e pronto para uso.
use SendGrid;
use SendGridTransportModule\SendGridTransport;

class SomeControllerOrServiceOrHelper 
{
    public function someMethod()
    {
        $mail = new Mail\Message();
        $mail->setBody('This is the text of the email.');
        $mail->setFrom(new Mail\Address('test@example.org', 'Sender\'s name'));
        $mail->addTo(new Mail\Address('some@address.com', 'User Name'));
        $mail->setSubject('TestSubject');

        $sendGrid = new SendGrid('YOUR_API_KEY');
        $sendGridEmail = new SendGrid\Email();
        $sendGridTransport = new SendGridTransport($sendGrid, $sendGridEmail);

        $sendGridTransport->send($mail);
    }
}

Contribuindo

A contribuição pode ser feita através de issues no github.

Conclusão

Este módulo é apenas um começo, existem muitas funcionalidades a serem abordadas ainda, mas para o disparo de e-mails transacionais (recuperação de senhas, boas vindas, lembretes, etc) já está totalmente compatível e funcional. Com esta solução, o disparo de e-mails não mais é impedido, uma vez que o conteúdo é enviado via POST para o SendGrid que então realiza a distribuição dos e-mails. Desta forma as portas 25 e 587 não precisam estar liberadas no server de sua aplicação e toda transação é realizada seguramente entre seu server e o SendGrid por meio de sua ApiKey.


Scroll down