luisico

Return-Path en un mail desde Rails

17 Apr 2009

Pongamos la clásica funcionalidad web en la que un usuario lee una noticia y tiene el típico enlace “Mandar la noticia a un amigo” de forma que dicho amigo va a recibir un mail enviado por un servicio de noticias, pero va a saber que quien se lo ha querido enviar es su colega. Lo que necesito entonces es poder mandar emails desde rails que cumplan las siguientes condiciones:

  • La dirección de origen que aparezca en el email, es decir la cabecera From ha de ser una genérica asociada al servicio, como por ejemplo noreply@example.com.
  • El Reply-To ha de ser otra dirección, pongamos la del usuario que ha querido enviar el mail a su amigo.
  • Quiero estar seguro de que cada email que se envía desde este servicio se envía correctamente y si no lo hace, al menos conocer la razón de porque no ha sido así. Por lo tanto necesito que si falla el envío, el servidor SMTP donde ha fallado sea capaz de devolverme una respuesta para que mi sistema pueda ir parseando emails de respuesta de envios fallidos. Eso sí lo que no quiero es que estas respuestas vayan a parar al buzón del sistema del usuario con el que está arrancada la aplicación web, ya que se me pueden mezclar en ese buzón un montón de cosas y no solo las respuestas de esos envíos concretos de correo. Por lo tanto necesito poder indicarle a rails esa dirección de respuesta de errores. La cabecera que se encarga de proporcionarle está información a los servidores de correo es la de Return-Path. Pongamos que está dirección es fail@example.com

Así que el código de ejemplo de un envío de este tipo sería el siguiente: En el config/environments/production.rb:

config.action_mailer.delivery_method = :sendmail

y en la clase del ActionMailer::Base:

class MessageMailer < ActionMailer::Base
  def message_email(email_data)
    recipients  email_data[:recipient]
    from        "noreply@example.com"
    headers     "Return-Path" => "fail@example.com"
    reply_to    email_data[:sender_email]
    subject     email_data[:subject]
    body        :body => email_data[:body]
  end
end

Si se tienen en la aplicación muchos métodos de envío de correos diferentes, para no tener que indicar siempre el header de Reply-To, se puede poner a mano en el environment como parametro de sendmail:

  config.action_mailer.delivery_method = :sendmail
  config.action_mailer.sendmail_settings = {
    :location => '/usr/sbin/sendmail',
    :arguments => '-i -t -f fail@example.com'
  }