Problema de envio RequestExpired na Amazon SES com Django SES

Recentemente tive um problema curioso ao utilizar a ferramenta de envio de email da Amazon, o Amazon SES, e gostaria de compartilhar a solução com vocês porque as referências que usei para a solução estavam todas muito espalhadas. Então vamos lá!

Em um dos projeto em que estou trabalhando ultimamente, resolvemos mudar o envio do email para utilizar um serviço mais confiável do que o nosso próprio servidor e, por diversos fatores que não cabem nesse post, escolhemos o Amazon SES. Para fazer a integração com o Django, utilizamos o projeto Django-SES. Tudo funcionou muito bem nos testes locais e no ambiente de staging. Mas, quando testamos em produção, tivemos um erro relativamente estranho:

BotoServerError: BotoServerError: 400 Bad Request
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<Error>
<Type>Sender</Type>
<Code>RequestExpired</Code>
<Message>Request timestamp: Fri, 10 May 2013 14:54:17 GMT expired.  It must be within 300 secs/ of server time.</Message>
</Error>
<RequestId>123123123123123123123123</RequestId>
</ErrorResponse>

Curiosamente, esse erro acontecia somente somente em algumas das máquinas de produção. Então, rapidamente pudemos deduzir que o problema era causado por algum erro de configuração de máquinas específicas. Pesquisando nos fóruns da Amazon, achamos esse post que nos deu um caminho a seguir e pudemos entendê-lo melhor ao ler a documentação da Amazon na parte em que fala de autenticação (Programming Guide >  About Requests and Responses > Request Authentication > HMAC-SHA1 Signatures). O que estava bloqueando o envio de email era que o parâmetro de timestamp, que é necessário para a autenticação, estava sendo formado de maneira errada ou com um valor inválido.

Utilizando o comando date, pudemos ver que de fato havia algo estranho já que o máquina estava 8 minutos no futuro! Óbvio que o tempo que estava gerando era invalidado pelo Amazon SES já que ele ainda nem aconteceu. Ainda não descobri o porquê disso ter acontecido, mas suspeito que tenha sido algum erro de configuração inicial da máquina. Para resolver o problema, bastou sincronizar o horário do computador executando o comando:

sudo ntpdate br.pool.ntp.org br.pool.ntp.org br.pool.ntp.org

Para evitar problemas futuros em outras máquinas, achei conveniente adicionar esse comando como último comando no processo de deploy feito pelo Fabric e também criar uma tarefa no cron que faz essa atualização regularmente. Não sei se é exagero, mas como ainda não identifiquei a causa do problema, é melhor prevenir do que remediar.

O interessante desse processo foi descobrir como o Linux resolve a sincronia de data e hora descobrindo o comando ntpdate. E, além disso, acabei descobrindo mais um dos quase infinitos protocolos que eu não conhecia que, no caso, é o Network Time Protocol (NTP), que é um dos protocolos mais antigos existentes e é responsável por viabilizar a sincronia entre relógios de máquinas diferentes (inclusive levando em conta a latência da rede).

Como eu disse, a ideia desse post foi somente compartilhar o problema e consolidar a solução para consulta futura ou para ajudar algum desaventurado que tenha esse mesmo problema. Para se aprofundar mais no tema de configuração de horário da máquina, aconselho esse excelente post do Flávio Torres. Até a próxima!

Trabalhando com Branchs no Git de Maneira Efetiva

Quantas vezes você já perdeu tempo tendo que resolver conflitos gigantes depois de um merge? Ou então, você nunca precisou fazer um merge, mas precisou resolver conflitos após atualizar o seu repositório local? Se sim, isso pode significar que você não está trabalhando com o git de uma maneira mais eficiente lançando mão dos branchs.

Os branchs são ramos paralelos de desenvolvimento que abrimos para podermos organizar o repositório. Podemos criar branchs para resolver problemas específicos e depois, através do merge, colocarmos no branch principal do projeto. O problema, é que se não usarmos isso de uma maneira organizada, pode acabar virando uma grande confusão, e é para evitar isso que existem algumas políticas de branching no git. Aqui eu vou falar sobre a política proposta por esse post e o gitflow, um projetinho que torna bem fácil trabalhar com ela. O gitflow precisa ser instalado e, após isso, basta você executar git flow init e configurar como você quer chamar os seus branchs. Então vamos entendê-los, a começar pelos dois branchs principais:

Continue Reading →

Agilizando a Escrita de Testes no Django com o Model Mommy

Fala pessoal! Depois de um longo inverno, resolvi voltar com o blog em novos ares e tema também, como dá para perceber. De agora em diante, vou tentar escrever com maior regularidade e vou começar com uma meta possível: 1 post a cada duas semanas. Óbvio que minha meta é aumentar isso, mas por hora é tudo novo de novo e vamos começar devagar. Além disso, vou tentar não falar somente sobre desenvolvimento e pretendo abordar outros temas, mas hoje não vou fugir da regra e vou falar sobre o projeto que mais contribuí recentemente, o Model Mommy.

O Model Mommy é um projeto que tem o nobre intuito de facilitar a escrita de testes de aplicações Django, ou seja, ele diminui ainda mais os seus argumentos de que é difícil escrever testes. O projeto é baseado na factory_girl (uma gem Ruby) e tem o propósito de facilitar a criação de objetos com valores não determinísticos no banco de dados para propósito de testes. Ele faz isso fornecendo uma API muito simples e poderosa que te permite manipular desde modelos simples a modelos com relacionamentos mais estruturados.

Continue Reading →

Encontro 1º PythonRioDay

Na semana passada fui com o Thiago Garcia no SINDPD-RJ, onde eu havia palestrado sobre Django na semana passada, para vermos a possibilidade de fazermos um encontro da comunidade Python do Rio de Janeiro no espaço. Rapidamente, já acertamos a data para o 1º PythonRioDay para o dia 21/07, um sábado, no próprio SINDPD-RJ. Para quem vai ao FISL 13, já pode até servir para esquentar os motores.

O intuito é construir um encontro de maneira colaborativa e organizada para juntar as pessoas com interesse em Python no Rio de Janeiro. Para isso, fizemos apenas um formulário bem simples para ver quem quer participar e sobre o que quer falar ou ouvir no evento. Vale desde falar sobre algo pequeno até coisas mais complexas. Sabe aquele papo de que a entrada é 1 kg de alimento não perecível? Então, aqui a entrada é qualquer snippet de código Python que você tenha escrito ou queira entender. Então, está esperando o que? Preencha logo o formulário aqui mesmo:

Continue Reading →

Autenticando o seu usuário Django pelo Facebook

Essa semana tive que fazer uma integração com a API de autenticação do Facebook e fiz uma pesquisazinha. Dei de cara com esse post que fazia uma comparação entre quatro ferramentas. Assim como o post, fiquei entre o django-allauth e o django-social-auth. Testei somente o segundo e ele coube como uma luva para o que eu necessitava – autenticar com o Facebook e manter a autenticação padrão do Django ativa.

Como não achei nada na internet que fosse resumido e focado para a autenticação com o Facebook utilizando essa app, resolvi fazer esse post para compartilhar a experiência. Então vou fazer um passo-a-passo aqui do que tive que fazer para completar a integração (que foi bem simples, diga-se de passagem).

Continue Reading →