Enviar e-mail com o rails 2.1 utilizando serviços SMTP do gmail

Filed Under (Ruby on Rails links, Tutorial) by marcos on 19-08-2008

Tagged Under : , , , , ,

Uma duvida muito comum que aparece com as pessoas que estão estudando rails (Foi o meu caso :D) é enviar e-mail através da sua aplicação, seja para validar cadastro, notificação de usuário.. e inúmeros outros motivos que aparecem (Só não utilizar para enviar SPAM!!).

Vamos iniciar criando nossa aplicação:

  $ rails email

Caso tenha funcionado o rails cria o projeto dentro dos padrões MVC:

$ rails email
      create
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  config/initializers
      (...)

Vamos configurar o banco de dados.. caso ao contrários.. nossa aplicação não funciona. Para isso edite o arquivo db/database.yml, e adicione o código abaixo (Caso for banco de dados MySQL)

development:
  adapter: mysql
  encoding: utf8
  database: email
  username: root
  password: 
  host: localhost
test:
  development

production:
  development

Não se esqueça de criar o banco de dados tambem:

$ mysql -u root -p
password:
mysql> create database email;

Para nós podermos utilizar o serviço de smtp do gmail é necessário adicionar o arquivo lib/smtp_tls.rb devido ao fato do gmail usar TLS.

require "openssl"
require "net/smtp"

Net::SMTP.class_eval do
  private
  def do_start(helodomain, user, secret, authtype)
    raise IOError, 'SMTP session already started' if @started
    check_auth_args user, secret, authtype if user or secret

    sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
    @socket = Net::InternetMessageIO.new(sock)
    @socket.read_timeout = 60 #@read_timeout
    @socket.debug_output = STDERR #@debug_output

    check_response(critical { recv_response() })
    do_helo(helodomain)

    raise 'openssl library not installed' unless defined?(OpenSSL)
    starttls
    ssl = OpenSSL::SSL::SSLSocket.new(sock)
    ssl.sync_close = true
    ssl.connect
    @socket = Net::InternetMessageIO.new(ssl)
    @socket.read_timeout = 60 #@read_timeout
    @socket.debug_output = STDERR #@debug_output
    do_helo(helodomain)

    authenticate user, secret, authtype if user
    @started = true
  ensure
    unless @started
      # authentication failed, cancel connection.
        @socket.close if not @started and @socket and not @socket.closed?
      @socket = nil
    end
  end

  def do_helo(helodomain)
     begin
      if @esmtp
        ehlo helodomain
      else
        helo helodomain
      end
    rescue Net::ProtocolError
      if @esmtp
        @esmtp = false
        @error_occured = false
        retry
      end
      raise
    end
  end

  def starttls
    getok('STARTTLS')
  end

  def quit
    begin
      getok('QUIT')
    rescue EOFError
    end
  end
end

Adicionar os códigos abaixo no arquivo config/environment.rb

Rails::Initializer.run do |config|
  # (...) Não apague o conteúdo dentro do |config|
end

require 'smtp_tls'
ActionMailer::Base.default_content_type = "text/html"
ActionMailer::Base.smtp_settings = {
  :address => "smtp.gmail.com",
  :port => 587,
  :authentication => :plain,
  :domain => "mycompany.com",
  :user_name => "seuemail@gmail.com",
  :password => 'suasenha'
}

Não esqueça de habilitar o acesso via SMTP/POP dentro do gmail.. pois por padrão vem desabilitado.

Agora vamos criar o nosso mailer:

$ script/generate mailer Emailer
      exists  app/models/
      create  app/views/emailer
      exists  test/unit/
      create  test/fixtures/emailer
      create  app/models/emailer.rb
      create  test/unit/emailer_test.rb

Agora vamos editar o nosso model: app/models/emailer.rb

class Emailer < ActionMailer::Base
  def contact(from, subject, message, name, sent_at = Time.now)
    @subject = subject                    # Titulo do email
    @recipients = 'seuemail@gmail.com'    # Destino do email
    @from = from                          # origem do email
    @reply_to = from                      # Responder email para (Novidade do rails 2.1)
    @sent_on = sent_at                    # Data do email

    # view
    @body["name"] = name
    @body["title"] = subject
    @body["email"] = from
    @body["message"] = message
    @headers = {}
  end
end

Vamos criar agora a view para o contact: app/views/emailer/contact.html.erb

<p>
    <b>Nome:</b> <%= @name %>
</p>
<p>
    <b>Email:</b> <%= @email %>
</p>
<p>
    <b>Titulo:</b> <%= @title %>
</p>
<p>
    <b>Mensagem:</b>
</p>
<p>
 <%= @message %>
</p>

Para verificar se tudo está funcionando. vamos criar um controller chamado Emailers:

$ script/generate controller emailers
     exists  app/controllers/
     exists  app/helpers/
     create  app/views/emailers
     exists  test/functional/
     create  app/controllers/emailers_controller.rb
     create  test/functional/emailers_controller_test.rb
     create  app/helpers/emailers_helper.rb

Dentro dele vamos adicionar o método send_email: app/controllers/emailers_controller.rb

class EmailersController < ApplicationController
  def send_email
    if request.post?
      from = params[:from]
      subject = params[:subject]
      message = params[:message]
      name = params[:name]

      if !from.blank? and !subject.blank? and !message.blank? and !name.blank?
        Emailer.deliver_contact(from, subject, message, name)
        return if request.xhr?
        render :text => 'O email foi enviado com sucesso'
      else
        @form_error = 'Não foi enviado o email'
      end
    end
  end
end

Só falta agora criar a view para o nosso novo método do controller: app/views/emailers/send_email.html.erb

<%= '<font color="red">'+@form_error+'</font><hr />' if @form_error %>

<% form_tag :action => 'send_email' do %>
<table border="0">
<tr>
    <th>Nome:</th>
    <td><%= text_field_tag :name %></td>
</tr>
<tr>
    <th>Email:</th>
    <td><%= text_field_tag :from %></td>
</tr>
<tr>
    <th>Assunto:</th>
    <td><%= text_field_tag :subject %></td>
</tr>
</table>

<%= text_area_tag :message %> <p />

<%= submit_tag "Enviar" %>
<% end %>

Agora para testar: http://localhost:3000/emailers/send_email

É isso.. até a proxima :)

Comments:

3 Responses to “Enviar e-mail com o rails 2.1 utilizando serviços SMTP do gmail”


  1. Nossa morzão entendi tudo desse negocio de mandar email pelo rails….mor ta bonituuuu o teu blog gostei bastantão

    Beijao


  2. O Garoto tem futuro
    ;-)


  3. Muito bom, parabens

Leave a Reply