Formulario de contacto en RoR con Action Mailer

7 de Agosto, 2007 — Ruby on Rails

Edito y amplío este post del 12 de diciembre del 2006 para intentar que el ejemplo sea más claro. Está probado en Rails 1.2.

localhost:~ User$ ./script/generate mailer Contact

Añadir al final del archivo config/environment.rb lo siguiente para que Action Mailer pueda autentificarse y enviar el correo.

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => 'smtp.website.com',
:port => 25,
:authentication => :login, # Don't change this one.
:user_name => "smtp_username",
:password => "smtp_password"}
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.default_charset = "utf-8"

Se puede enviar también utilizando sendmail poniendo únicamente
ActionMailer::Base.delivery_method = :sendmail

Ahora edita el archivo app/models/contact.rb y añade el método que enviará el email:

class Contact < ActionMailer::Base
def contact_email(email_params, sent_at = Time.now)
@recipients = "contact@website.co.uk" # Dirección donde se envía el correo
@from = email_params[:name] + " <" + email_params[:address] + ">"
@subject = email_params[:subject]
@sent_on = sent_at
@body["email_body"] = email_params[:body]
@body["email_name"] = email_params[:name]
end
end

En el directorio ‘views/contact’ crea el archivo contact_email.rhtml, este archivo es el contenido del email que se enviará a la dirección especificada anteriormente. En este caso se envían las variables “name” y “body”. Dentro de este archivo se puede poner texto y otras variables o incluso definirlo como html con las cabeceras correspondientes.

Name:
<%= @email_name %>
Message:
<%= @email_body %>

Vamos a crear el formulario de contacto. Crea una vista en el controlador principal, por ejemplo contacto.rhtml:

<%= start_form_tag :action=> "send_mail" %>
<label for="email_name">Name:</label>
<%= text_field "email", "name", :size => 30 %>
<label for="email_address">Email Address:</label>
<%= text_field "email", "address", :size => 30 %>
<label for="email_subject">Subject:</label>
<%= text_field "email", "subject", :size => 30 %>
<label for="email_body">Body:</label>
<%= text_area "email", "body", :rows => 8, :cols => 30 %>
<input value="Send Email" class="primary" type="submit" />
<%= end_form_tag %>

En el controlador principal añade el método siguiente que es el que procesa el formulario

def send_mail
Contact::deliver_contact_email(@params[:email])
end

Hay un detalle importante: el nombre del método que se llama es deliver_contact_email, en el modelo el método se llama contact_email. Cuando se llama a un método que envía un email con ActionMailer hay que seguir esta convención y añadir “deliver” antes del nombre del método.
Siguiendo este ejemplo podemos tener otro método que envía otro email que se llame contact_email_factory. Cuando lo invoquemos desde el controlador habrá que hacerlo con Contact::deliver_contact_email_factory(@params[:email])

Sólo nos queda añadir un enlace para poder acceder al formulario. En la página que queramos ponemos el siguiente enlace:

<%= link_to 'Contacto', :controller => "controlador_principal", :action => "contacto" %>

En el controlador principal tiene que haber un método cómo este que es el que procesa el enlace y muestra la vista correspondiente:

def contacto
render :action => 'contacto'
end

10 Comentarios »

  1. He hecho lo que ponías y en el log veo perfectamente la salida, pero no envía
    nada… :(

    ¿Sabrías pq puede ser?

    environment.rb (al final)
    ————————–
    ActionMailer::Base.raise_delivery_errors = true
    ActionMailer::Base.delivery_method = :sendmail
    ActionMailer::Base.default_charset = “ISO-8859-1″

    contact.rb
    —————–
    class Contact < ActionMailer::Base
    def contact_email(email_params, sent_at = Time.now)
    @recipients = “xxxxxxx@gmail.com” # Dirección donde se envía el
    correo
    @from = email_params[:name] + ” ”
    @subject = email_params[:subject]
    @sent_on = sent_at
    @body[”email_body”] = email_params[:body]
    @body[”email_name”] = email_params[:name]
    end
    end

    contact_email.rhtml
    ———————-
    Nombre:

    Mensaje:

    resultado.rhmtl
    ———————
    […]
    ’send_mail’ %>

    Nombre:

    30 %>

    E-mail:

    30 %>

    Motivo del contacto:

    30 %>

    Mensaje:

    3, :cols => 30 %>

     

    […]

    controlador
    ————-
    def send_mail
    Contact::deliver_contact_email(@params[:email])
    render :action => ‘resultado’
    end

    Log
    ————————-
    Sent mail:
    Date: Mon, 22 Oct 2007 19:11:31 +0200

    From: nombre

    To: xxxxxxxxxxx@gmail.com

    Subject: motivo

    Mime-Version: 1.0

    Content-Type: text/plain; charset=ISO-8859-1

    Nombre:
    nombre
    Mensaje:
    mensaje
    Rendering actionresultadolayoutfalse within
    layouts/establishment_contents

    Muchas gracias.

    Comentario por David — 22 de Octubre, 2007 @ 8:32
  2. Hola David. ¿Tienes instalado algún servidor de correo en la máquina donde estás haciendo las pruebas?, de ser así, ¿tienes el enlace simbolico al comando “sendmail” creado?

    Comentario por Emili Parreño — 22 de Octubre, 2007 @ 10:59
  3. Hola. No tengo ningún servidor de correo. Pensé que con ActionMailer::Base.delivery_method = :sendmail en el environment.rb era suficiente. La llamada a send_mail lo tengo en el formulario de resultado.rhtml.
    ” ’send_mail’ %>”

    Nombre:

    30 %>

    E-mail:

    30 %>

    Motivo del contacto:

    30 %>

    Mensaje:

    3, :cols => 30 %>

     

    Muchas gracias

    Comentario por David — 23 de Octubre, 2007 @ 8:30
  4. ’send_mail’ %>

    Nombre:

    30 %>

    E-mail:

    30 %>

    Motivo del contacto:

    30 %>

    Mensaje:

    3, :cols => 30 %>

     

    </p

    Comentario por David — 23 de Octubre, 2007 @ 8:33
  5. ” ’send_mail’ %>

    Nombre:
    30 %>

    E-mail:
    30 %>

    Motivo del contacto:
    30 %>

    Mensaje:
    3, :cols => 30 %>

     

    Comentario por David — 23 de Octubre, 2007 @ 8:34
  6. Perdona por los mensajes. Se corta cuando meto código…
    “form_tag :action=> ’send_mail’”
    [..]
    “image_submit_tag (’../images/aceptar.gif’)”
    [..]
    “end_form_tag”

    Comentario por David — 23 de Octubre, 2007 @ 9:16
  7. Lo sé David, tengo que arreglarlo de alguna manera.
    El problema que tienes es que no tienes un servidor de correo que pueda enviarte los mensajes. Tendrás que subir la aplicación al servidor y probarlo on-line.

    Comentario por Emili Parreño — 23 de Octubre, 2007 @ 10:05
  8. Gracias amigo :)

    Comentario por Hugo — 3 de Marzo, 2008 @ 3:57
  9. Gracias por tu articulo.

    Emili, en :address puedo poner la ip del servidor de correo que es exchage2003 sin agregar el prefijo smtp, ej: :smtp => “smtp.10.3.240.241″, sigo todos los pasos y no me da, claro que sospecho del proxy de la empresa. gracias

    Comentario por wifer — 1 de Abril, 2008 @ 2:53
  10. En teoría debería funcionar también con la IP, sin el smtp delante. En cuanto al proxy, si lo pruebas desde tu máquina es como si tu cliente de correo estuviera enviando un email o sea que debería funcionar. Mira los logs, tal vez encuentre más información de lo que está pasando (/log/development.log). Otra cosa que puedes probar para ver si es el proxy es ejecutar tu aplicación y enviar un correo en otra red: en tu casa o en un cybercafe.

    Suerte.

    Comentario por Emili — 1 de Abril, 2008 @ 8:53

Redifusión RSS de los comentarios de la entrada.

Deje un comentario

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. | Emili Parreño