AWS

1 mar, 2017

Processando um e-mail sender em um Docker na AWS

Publicidade

O Docker é uma tecnologia de código aberto que permite criar, executar, testar e implantar aplicações distribuídas dentro de contêineres de software.

Ele permite que você empacote um software em uma unidade padronizada para o desenvolvimento de software, contendo todo o necessário para a execução: código, runtime, ferramentas do sistema, bibliotecas do sistema etc.

O Docker permite que você implante aplicações rapidamente, de modo confiável e estável, em qualquer ambiente.

A execução do Docker na AWS viabiliza de modo altamente confiável e de baixo custo a criação, a execução, o teste e a implantação de aplicações distribuídas em qualquer escala.

(fonte: aws)

Então, mãos a obra!

Primeiro, vamos criar uma aplicação realmente simples que seja capaz de seguir o seguinte fluxo:

Primeiramente, vamos criar uma lista de e-mails dos destinatários.

Para tal lista (super fake) podemos utilizar dois aceleradores:

  • http://www.nomesdefantasia.com/
  • http://www.yopmail.com/es/email-generator.php

emaildestinatarios.json

[
    {
        "Nome": "Edward",
        "Email": "edwardmartinsjr@gmail.com"
    },
    {
        "Nome": "Nascia",
        "Email": "makarozyfa-9743@yopmail.com"
    },
    {
        "Nome": "Ehew",
        "Email": "jecitappa-6363@yopmail.com"
    },
    {
        "Nome": "Dratho",
        "Email": "vemmijyqev-1988@yopmail.com"
    },
    {
        "Nome": "Kehew",
        "Email": "qacetyllu-4863@yopmail.com"
    },
    {
        "Nome": "Regin",
        "Email": "icawoxaj-4110@yopmail.com"
    },
    {
        "Nome": "Fortinto",
        "Email": "ollibagaff-6669@yopmail.com"
    },
    {
        "Nome": "Helmnath",
        "Email": "hivubasup-3780@yopmail.com"
    },
    {
        "Nome": "Fridmax",
        "Email": "ozozuxe-0415@yopmail.com"
    },
    {
        "Nome": "Wisefortin",
        "Email": "mottallesse-6173@yopmail.com"
    }
]

Para armazenar este json, precisamos da seguinte struct:

//EmailDestinatarios : Lista de e-mails dos destinatários
type EmailDestinatarios struct {
	Nome  string
	Email string
}

Agora, iremos criar uma função para leitura deste arquivo json.

func getEmailDestinatarios(file string) []EmailDestinatarios {
	//Realiza a leitura do arquivo json
	raw, err := ioutil.ReadFile(file)

	//Tratamento de erros padrão.
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}
	var emailDestinatarios []EmailDestinatarios

	//Unmarshal do conteúdo do arquivo json para um tipo struct EmailDestinatarios
	json.Unmarshal(raw, &emailDestinatarios)
	return emailDestinatarios
}

Com a ajuda do pacote “net/smtp”, depois de armazenarmos na nossa slice, todos os nomes e e-mails dos destinatários do arquivo json, vamos criar uma função para enviar a cada um deles um e-mail, conforme o fluxo que definimos.

func disparaEmailDestinatario(emailDestinatario EmailDestinatarios) {
	//Realiza o setup da autorização do servidor de SMTP. Não se esqueça de configurar seu Gmail SMTP server...
	//https://support.google.com/a/answer/176600?hl=en
	//https://support.google.com/accounts/answer/6010255?hl=en

	hostname := "smtp.gmail.com"
	auth := smtp.PlainAuth("", "seuemail@gmail.com", "suasenhagmail", hostname)

	//Criamos um slice do tipo string do tamanho máximo de 1 para receber nosso e-mail destinatário.
	recipients := make([]string, 1)
	recipients[0] = emailDestinatario.Email

	//Veja mais em: https://golang.org/pkg/net/smtp/#SendMail
	err := smtp.SendMail(
		hostname+":25",
		auth, "seuemail@gmail.com",
		recipients,
		/*Mensagem no RFC 822-style*/
		[]byte("Subject:Olá!\n\n Olá "+emailDestinatario.Nome+". Tudo de bom com Go!"))
	if err != nil {
		log.Fatal(err)
	}

}

Por fim, depois de construirmos os métodos de suporte, o programa principal deve ficar assim:

func main() {

	//Carrega os destinatários em uma slice
	var emailDestinatarios = getEmailDestinatarios("./emaildestinatarios.json")

	for _, item := range emailDestinatarios {
		//dispara um e-mail para cada um dos destinatários
		disparaEmailDestinatario(item)
	}

}

Ok, executando nosso programa devemos identificar na caixa de saída e na caixa de entrada do Gmail, configurado na função disparaEmailDestinatario algo parecido com isso:

Caixa de entrada (*considerando que você tenha colocado seu e-mail como um dos destinatários no arquivo json):

Caixa de saída:

Ótimo, agora que nosso programa está funcionando adequadamente, vamos empacotar ele em uma estrutura muito simples de docker.

Vamos criar um arquivo com o nome “Dockerfile.local” e nele o seguinte conteúdo:

Dockerfile.local

FROM google/golang-runtime

Legal, agora vamos criar um arquivo .zip(application source bundle) com a seguinte estrutura de arquivos:

  • local
  • json
  • go

Coloquemos um nome adequado a este arquivo compactado.

Ex.: “v201702191610.zip”

Agora, considerando que você já tenha uma conta AWS validada, vamos seguir com o deploy do nosso container.

Passo 1, criando uma instância elástica:

  • Faça o login e siga até Elastic Beanstalk -> Create New Application;
  • Preencha “Application name” e “Description” – seja criativo;
  • Next;
  • Em New Environment, escolha “Web Server Environment” -> “Create web server”;
  • Em Environment Type, na lista Predefined configuration, escolha “Preconfigured – Docker -> Go”:

  • Na lista Environment type, escolha “Single Instance”, ao menos para este nosso teste, afinal de contas, a vantagem de se utilizar uma instância elástica é ter um processamento escalonado conforme a necessidade de processamento da sua aplicação;
  • Next.

Passo 2, realizando o upload da aplicação:

  • Em Application Version, escolha “Upload your own” e escolha o zip(application source bundle) que criarmos:

  • Next;
  • Environment Information, Next;
  • Additional Resources, Next;
  • Configuration Details, Next;
  • Environment Tags, escolha qualquer chave e valor que lhe agrade – seja criativo;
  • Next;
  • Permissions, Next;
  • Review & Launch.

Se tudo der certo, você deverá ver algo neste sentido:

E depois de um tempo, deve mudar para isso:

Você pode realizar quantos uploads achar necessário, através do botão “Upload and Deploy”:

Importante: mais uma daquelas “Siga por sua conta e risco…

Eventualmente, o Gmail irá impedir que você dispare um e-mail á partir de uma máquina desconhecida, mesmo você tendo configurado o Gmail SMTP server corretamente.

Esta ação faz que o upload da sua aplicação falhe de forma catastrófica resultando em um status degraded/red.

Se isto acontecer, cheque na sua caixa de e-mail, pois você receberá um e-mail do tipo:

Apenas confira em algum serviço de whois se o ip do device apresentado pertence á AWS:

Se estiver seguro de que é o ip de saída da sua instância‎, libere-o e faça um novo upload da aplicação com um nome de versão diferente.

Pronto, depois destes passos, a aplicação deverá ir para o status running/green. Cheque seu e-mail e verifique se foram disparados os e-mails aos destinatários conforme seu arquivo json.

Após você rodar sua aplicação, é recomendável que você finalize o processamento desta instância, simplesmente terminando ela.

Clique em Actions -> Terminate Environement:

E pronto! Taxímetro desligado…

Conclusão, Go é muito divertido e Go distribuído é mais divertido ainda!

Git:https://github.com/edwardmartinsjr/iMasters-Go/tree/master/emailsender