Criando serviço de envio de e-mail com ELIXIR!🔮
Tags: elixir, braziliandevs
Published: 2021-05-17 00:40:06

![Elixir](https://opengraph.githubassets.com/9494be74e4ffb2ab75a2bd83538fa52f80673c63283698fda37a05939bcfce7f/elixir-lang/elixir)
Que tal criar um mini servidor HTTP para envio de e-mail SMTP com o Elixir ?

> Hey, eu atualizei esta postagem no [meu blog pessoal, veja agora!](https://www.tuliocalil.com.br/post/criando-servico-de-envio-de-e-mail-com-elixir)

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.

 * [ Iniciando](#iniciando)  
 * [ Instalando dependências](#instalando-depend%C3%AAncias)  
 * [ Criando servidor HTTP](#criando-servidor-http)  
 * [ Rodando servidor HTTP](#rodando-servidor-http)  
 * [ Enviando e-mail](#enviando-email)  
 * [ Conclusão](#conclus%C3%A3o) 

###### generated with [Summaryze Forem 🌱](https://summaryze-forem.vercel.app/)

## Iniciando
Primeiro precisamos preparar nosso ambiente, caso você ainda não tenha o Elixir no seu ambiente, basta seguir [esse guia oficial](https://elixir-lang.org/install.html) que é simples e detalhado.
Com o Elixir instalado, vamos criar um novo projeto:
```bash
mix new email --sup
```
Desta forma vamos criar um novo projeto utilizando o [Mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html), 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](https://hexdocs.pm/elixir/Application.html).

## Instalando dependências
Podemos navegar até o nosso projeto e vamos agora instalar as dependências que vamos usar, são elas:
- [plug_cowboy](https://github.com/elixir-plug/plug_cowboy): Uma implementação do [Cowboy](https://github.com/ninenines/cowboy) para o Elixir.
- [poison](https://github.com/devinus/poison): Biblioteca JSON para o Elixir.
- [plug](https://elixirschool.com/pt/lessons/specifics/plug/): Uma especificação para componentes e adaptadores web(uma forma de padronizar o objeto de conexão).
- [bamboo](https://github.com/thoughtbot/bamboo): Envio de e-mail com Elixir.
- [bamboo_smtp](https://github.com/fewlinesco/bamboo_smtp): Adaptador para usarmos SMTP no bamboo.

Para isso, vamos abrir o arquivo `mix.esx` e adicionar as seguintes linhas dentro do bloco `deps`:
```exs
{:plug, "~> 1.5"},
{:plug_cowboy, "~> 1.0"},
{:poison, "~> 3.1"},
{:bamboo, "~> 2.1.0"},
{:bamboo_smtp, "~> 4.0.1"}
```

Agora, voltamos ao terminal e vamos instalar de fato as dependências, para isso no terminal rode o comando:
```bash
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`:
```ex
Plug.Adapters.Cowboy.child_spec(scheme: :http, plug: Email.Router, options: [port: 8085])
```
Pela ordem de parâmetros: 
- 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](http://elixirbridge.org/04_Mix_Applications/15-plug-router.html) 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](https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html).

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:

```ex
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 `code` `200` 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:
```bash
 iex -S mix
```
Agora basta acessar o endereço: [http://localhost:8085/](http://localhost:8085/) e vamos ver nosso servidor rodando:
![Elixir http](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2tx0o8u029woktzhpqi.png)

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](https://mailtrap.io/).
Na raiz do nosso projeto vamos criar uma pasta `config` e um arquivo `config.exs`, o module [Config](https://hexdocs.pm/elixir/master/Config.html) é 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:
```exs
use Mix.Config

config :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:
```exs
defmodule Email.Mailer do
  use Bamboo.Mailer, otp_app: :servidor_email
end
```
Agora abra o arquivo `email_router.ex` e na rota de `GET` vamos adicionar o seguinte:
```exs
 import Bamboo.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](https://en.wikipedia.org/wiki/Fluent_interface#:~:text=In%20software%20engineering%2C%20a%20fluent,Eric%20Evans%20and%20Martin%20Fowler.).

Agora, basta rodar nosso servidor novamente e acessarmos nossa [rota](http://localhost:8085/) `GET` e verificar o e-mail do Mail trap:
```bash
 iex -S mix
```
Mailtrap:
![Mailtrap](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fsxtg1hjqp3kf8a2kio5.png)

## 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:
{% github tuliocll/email-elixir %}

Veja esse episodio super legal do Coffe Zone onde falamos de Elixir:
{% spotify spotify:episode:3hWVSpaWfT9CypbzU16bV9 %}