Nesse post vou demonstrar como criar um super simples, pequeno e muito leve. Também vamos ver como fazer envio de e-mail quando o usuário acessar uma determinada rota do servidor.
Primeiro precisamos preparar nosso ambiente, caso você ainda não tenha o Elixir no seu ambiente, basta seguir esse guia oficial que é simples e detalhado.
Com o Elixir instalado, vamos criar um novo projeto:
mix new email --sup
Desta forma vamos criar um novo projeto utilizando o Mix, que é uma ferramenta que vem junto com o Elixir para criar, testar e compilar códigos em Elixir, além de gerenciar dependências também.
O parâmetro --sup é para que possamos gerar uma aplicação com o esqueleto no padrão OTP.
Instalando dependências
Podemos navegar até o nosso projeto e vamos agora instalar as dependências que vamos usar, são elas:
Agora, voltamos ao terminal e vamos instalar de fato as dependências, para isso no terminal rode o comando:
mix deps.get
Criando servidor HTTP
Com as dependências instaladas vamos começar configurar nosso servidor HTTP, para isso vamos configurar a inicialização dele, abra o arquivo lib/email/application.ex e adicione a seguinte linha dentro da lista children:
Schema é o protocolo que vamos utilizar: HTTP(tcp) ou HTTPS(ssl).
plug é para que possamos informar um Plug personalizado, nesse caso será o nosso router (eu recomendo essa leitura aqui para ficar mais claro).
Options são opções que podemos passar para o servidor, neste caso usamos apenas a porta, você pode ver outras aqui.
Como especificamos nosso modulo Email.Router, precisamos cria-lo agora, para isso, dentro da pasta lib/email crie um arquivo com o nome "email_router.ex" e dentro dele vamos declarar o nosso modulo e nossas rotas, dessa forma:
defmodule Email.Router do
use Plug.Router
use Plug.Debugger
require Logger
plug(Plug.Logger,log::debug)
plug(:match)
plug(:dispatch)get"/"do
send_resp(conn,200,"Server rodando...")
end
match _ do
send_resp(conn,404,"Pagina não encontrada")
end
end
Explicando:
Após definir nosso modulo, utilizamos o use para injetar dois módulos no contexto do nosso router.
Com require Logger vamos importar alguns recursos do logger (exceto funções).
Temos algumas chamadas plug, que basicamente vão configurar os modulos de log, match(para fazer o match das rotas com a requisição) e dispatch (processar a requisição após o match).
Na ultima parte do arquivo, temos as nossas rotas: uma GET na raiz que responde com status code200 e uma mensagem e a segunda, que serve como um "caso não encontre a rota", renderizando um "Pagina não encontrada".
Rodando servidor HTTP
Agora vamos compilar e rodar nosso servidor, para isso rode no seu terminal o seguinte comando:
iex -S mix
Agora basta acessar o endereço: http://localhost:8085/ e vamos ver nosso servidor rodando:
Como podemos ver, nosso servidor está funcionando perfeitamente!
Vamos agora para o próximo passo!
Enviando e-mail
Para fazermos o envio do e-mail, vamos começar configurando nosso servidor SMTP, para esse tutorial, vou utilizar o Mailtrap.
Na raiz do nosso projeto vamos criar uma pasta config e um arquivo config.exs, o module Config é utilizado para definirmos varias configurações do nosso aplicativo, além de configurações do iex também.
Nele vamos colocar nossa configuração de SMTP, o conteúdo ficará dessa forma:
useMix.Configconfig:email,Email.Mailer,adapter:Bamboo.SMTPAdapter,server:"SERVER",hostname:"SERVER",port:2525,username:"USER",# or {:system, "SMTP_USERNAME"}password:"PASS",# or {:system, "SMTP_PASSWORD"}tls::always,# can be `:always` or `:never`allowed_tls_versions:[:"tlsv1",:"tlsv1.1",:"tlsv1.2"],# or {:system, "ALLOWED_TLS_VERSIONS"} w/ comma seprated values (e.g. "tlsv1.1,tlsv1.2")ssl:false,# can be `true`retries:1,no_mx_lookups:false,# can be `true`auth::if_available# can be `:always`. If your smtp relay requires authentication set it to `:always`.
Basta preencher com suas informações e pronto.
Vamos precisar criar um modulo mailer passando o nome da nossa aplicação, para isso, crie um arquivo chamado mailer.exs dentro de lib/email e dentro dele vamos por:
Agora abra o arquivo email_router.ex e na rota de GET vamos adicionar o seguinte:
importBamboo.Email...new_email()|>to("meu@email.com")|>from("meu@email.com")|>subject("Teste")|>text_body("Testando envio de email")|>Email.Mailer.deliver_now
Aqui o código começa a ficar um pouco "estranho" pra quem não tem contato com Elixir, mas vou explicar: Primeiro fazemos o import do modulo "Email" dentro de "Bamboo", dessa forma temos acesso as funções contidas no modulo.
Em seguida fazemos uma chamada a função new_email() que vem do modulo que importamos e começamos uma sequencia de pipe. Utilizamos o pipe para pegar o resultado de uma expressão e lançar como primeiro argumento de uma outra. Esteticamente lembra o fluent pattern.
Agora, basta rodar nosso servidor novamente e acessarmos nossa rotaGET e verificar o e-mail do Mail trap:
iex -S mix
Mailtrap:
Conclusão
Podemos melhorar ainda mais esse código, podemos por exemplo pegar os parâmetros de e-mail(destinatário, mensagem e assunto) via GET ou POST, podemos também utilizar um .env para carregar as informações do SMTP de forma mais segura.
Espero que tenha gostado, já faz algum tempo que queria escrever sobre Elixir e foi super legal.
Aqui está o projeto finalizado: