IT & Engineering

Como criar uma abordagem baseada em dados para manter os e-mails da base de usuários atualizados

Este blog foi escrito por Roy Young. Roy atua com desenvolvimento Ruby e está aprimorando suas skills na Tealeaf Academy.

Ah, a tabela "users".

Imagem para Como criar uma abordagem baseada em dados para manter os e-mails da base de usuários atualizados

Este blog foi escrito por Roy Young. Roy atua com desenvolvimento Ruby e está aprimorando suas skills na Tealeaf Academy.

Ah, a tabela “users”.

É possível dizer que esse é um dos ativos mais importantes de uma startup. As mentes mais cínicas não acreditam que o Instagram (um aplicativo de compartilhamento de fotos!) tenha sido comprado por US$ 715 milhões pelo Facebook ou que, segundo rumores, o Mailbox, um cliente de e-mail móvel para Gmail (e ainda na versão beta em muitos aspectos), tenha sido comprado por até US$ 100 milhões pelo Dropbox.

Essa visão cínica costuma resultar de um foco míope apenas no produto ou na tecnologia, o que torna fácil descartar essas avaliações como absurdas. No entanto, o que também precisa ser considerado é o valor de toda a base de usuários e o crescimento dessa base. Essas avaliações astronômicas estão sempre associadas a um produto que tem uma base de usuários grande e em rápido crescimento. Faz sentido, então, que manter sua tabela da base de usuários atualizada com informações de contato corretas seja um bom investimento para a sua empresa. É claro que a parte difícil é criar esse crescimento… então você terá que pagar por essas informações.

Mas este conselho sobre a “parte fácil” é gratuito. Nesta publicação, falarei sobre uma boa metodologia para manter os e-mails da sua base de usuários atualizados em uma época em que muitas pessoas têm vários endereços de e-mail e e-mails descartáveis para muitos dos seus serviços.

Lógica do aplicativo para solicitar a atualização do endereço de e-mail

Quando você envia um e-mail para um endereço de e-mail que não existe mais, a parte receptora (por exemplo, Gmail ou Yahoo) fará a devolução do e-mail para você. Se você monitorar essas devoluções, o seu aplicativo poderá reagir de forma adequada, criando uma ótima experiência de uso, além de manter o seu banco de dados de clientes atualizado. Este blog descreve um aplicativo de exemplo criado no Heroku que usa o Mailgun para monitorar esses e-mails com devolução para que as pessoas com endereços de e-mail inválidos possam continuar a receber e-mails mensais com a fatura. No entanto, a mesma lógica pode ser aplicada a qualquer um dos seus e-mails, para garantir que o seu público permaneça engajado e atualizado sobre a sua empresa por e-mail.

Fluxo de trabalho para manter os contatos atualizados: um processo de 7 etapas para lidar com e-mails devolvidos e solicitar atualizações de usuários

Criei um site de demonstração para este artigo e disponibilizei o código-fonte no GitHub. Esta demonstração orienta iniciantes em todo o processo de configuração dessa funcionalidade. Clique aqui se você quiser pular diretamente para a integração de webhooks de devolução em seu aplicativo.

Envio de e-mails de faturas mensais usando o Heroku Scheduler

Para enviar faturas mensais à sua base de usuários, você precisará programar para:

  • Enviar e-mails de faturas personalizados para centenas, milhares ou milhões de clientes.
  • De fato agendar o envio desses e-mails.

Vamos analisar cada um deles em detalhes.

Envio de e-mails de faturas personalizados

Para os fins deste tutorial, presumo que você já tem uma conta do Mailgun. A partir daí, você vai querer enviar sua lista de clientes para o Mailgun, com as variáveis que quiser inserir de forma dinâmica nos e-mails, como um arquivo JSON, e o HTML ou corpo de texto do e-mail. Aqui está o código.

                                

                                    class MailgunGateway include Rails.application.routes.url_helpers def send_batch_message(users) RestClient.post(messaging_api_end_point, from: "Mailgun Demo ", to: users.map(&:email).join(", "), subject: "Monthly Billing Info", html: billing_info_text, :"h:Reply-To" => "billing@#{ENV["mailgun_domain_name"]}", :"recipient-variables" => recipient_variables(billing_recipients) ) end private def api_key @api_key ||= ENV["mailgun_api_key"] end def messaging_api_end_point @messaging_api_end_piont ||= "https://api:#{api_key}@api.mailgun.net/v2/#{ENV["mailgun_domain_name"]}/messages" end def billing_recipients @users ||= User.where(locked: false) end def recipient_variables(recipients) vars = recipients.map do |recipient| ""#{recipient.email}": {"name":"#{recipient.fullname}"}" end "{#{vars.join(', ')}}" end def billing_info_text <<-EMAIL  Hi %recipient.name%, <p> Your bill for the current month is now available, please click on <br /> #{billing_url} <br /> to see details. </p> <p>Reply to this email directly</p>  EMAIL end end
                                
                            

Vamos analisar o que fizemos.

No método sendbatchmessages, usamos as variáveis de destinatário para que possamos definir variáveis para personalizar cada e-mail. Você notará que estamos inserindo o primeiro nome da pessoa no e-mail. Você pode redigir um e-mail de fatura que inclua detalhes como número da conta, conta da fatura ou qualquer outra coisa que quiser, mas eu prefiro manter a simplicidade.

Envio automático de e-mails de faturamento mensais com o Heroku Scheduler

Assim que definirmos o método de criação e envio de e-mails via Mailgun, precisamos criar um código para acionar esse método como gatilho automaticamente. Escolhi implantar esse aplicativo no Heroku e estou usando o Heroku Scheduler porque ele dá conta do recado, é um complemento gratuito e fácil de integrar.

O Heroku Scheduler vai executar uma tarefa Rake especificada em um horário especificado. Então, aqui precisamos compilar uma tarefa Rake para enviar e-mails de faturamento usando o Mailgun em lib/tasks/scheduler.rake.

Primeiro, quando enviamos faturas de faturamento para nossa base de usuários, precisamos encontrar os endereços de e-mail do cliente para o qual enviaremos a fatura.

No esquema de banco de dados muito simples deste aplicativo de exemplo, temos um atributo :locked que é definido como True quando houve devolução de um e-mail antes (mais sobre isso abaixo). Portanto, nossa consulta simplesmente extrai toda a nossa base de usuários na qual esse campo é False.

Para realmente enviar o e-mail, estou usando o Mailgun Envio em lote. Como o número máximo de destinatários permitidos por chamada de API é de 1 000, usamos o findinbatches para enviar e-mails de faturamento ao Mailgun em lotes de 1 000 destinatários.

                                

                                    desc "This task is called by the Heroku scheduler add-on"
task :send_billing_info => :environment do
  if DateTime.now.mday == 1
    User.where(locked: false).find_in_batches(batch_size: 1000) do |group|
      MailgunGateway.new.send_batch_message(group)
    end
  end
end
                                
                            

Como a configuração de “FREQUENCY” (Frequência) do Heroku Scheduler tem apenas três seletores — “daily” (diariamente), “hourly” (por hora) e “every 10 mins” (a cada 10 min) —, precisamos verificar se o dia atual é o primeiro dia do mês usando if DateTime.now.mday == 1. Se for, o e-mail será enviado. Se não, nenhum e-mail será enviado.

Recebimento de notificação de e-mails com devolução

Quando houver devolução de um e-mail, o Mailgun enviará um POST por meio do webhook de devolução ao nosso aplicativo. Você precisa definir a URL de callback em “Bounces” no Painel de Controle do Mailgun. Nesta demonstração, a minha URL de callback é "http://mailgun-demo.herokuapp.com/api/bounced_mails"

Quando o aplicativo receber a notificação de devolução, ele encontrará o endereço de e-mail no banco de dados do cliente e definirá o status da pessoa como bloqueado, de modo que o aplicativo não enviará e-mails de faturamento para ela até que ela atualize o seu endereço de e-mail.

                                

                                    class Api::BouncedMailsController < ApplicationController
  skip_before_filter :verify_authenticity_token
  def create
    if verify(ENV["mailgun_api_key"], params[:token], params[:timestamp], params[:signature])
      user = User.find_by_email(params[:recipient])
      if user && params[:event] == "bounced"
        user.lock!
      end
      head(200)
    end
  end
  private
  def verify(api_key, token, timestamp, signature)
    signature == OpenSSL::HMAC.hexdigest(
      OpenSSL::Digest::Digest.new('sha256'),
      api_key,
      '%s%s' % [timestamp, token])
  end
end
                                
                            

user.lock! serve para definir o status como bloqueado, para que nossa tarefa Rake nunca envie e-mails para essa pessoa. Esse método é definido no modelo User.

                                

                                    class User < ActiveRecord::Base
  …
  def lock!
    self.locked = true
    save(validate: false)
  end
end
                                
                            

O método verify serve para verificar se o webhook é originário do Mailgun; caso contrário, qualquer outra pessoa poderia enviar um POST falso para bloquear a base de usuários no seu aplicativo.

Para obter mais detalhes sobre a configuração de webhooks, você pode ler a documentação do Mailgun – Eventos/Webhooks.

No final, retornamos um cabeçalho 200 para informar ao Mailgun que essa interação foi bem-sucedida; caso contrário, o Mailgun achará que nosso servidor está fora do ar e continuará tentando chamar o nosso webhook.

Exibição da tela em flash para que a pessoa atualize o e-mail

Assim que o aplicativo souber quais contas têm um endereço de e-mail inválido, precisaremos exibir uma tela em flash no próximo login com uma solicitação para confirmar as informações de contato em arquivo.

                                

                                    class SessionsController < ApplicationController
  def new
    redirect_to home_path if current_user
  end
  def create
    user = User.find_by_email(params[:email])
    if user && user.authenticate(params[:password])
      session[:user_id] = user.id
      if user.locked
        flash[:error] = "Your Email Address is invalid, please update it."
        redirect_to edit_user_path(current_user)
      else
        redirect_to home_path
      end
    else
      flash[:error] = "Incorrect email or password. Please try again."
      redirect_to sign_in_path
    end
  end
  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
end
                                
                            

Quando o endereço de e-mail for atualizado, definiremos o atributo de bloqueio novamente como false para que essas pessoas continuem a receber e-mails.

Simples assim. Agora, quando houver devolução dos e-mails da sua base de usuários, você poderá solicitar que eles atualizem suas informações, proporcionando uma ótima experiência de uso com o benefício adicional de manter os dados dos seus clientes atualizados.