Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Ruby On Rails > как проверить отправлены ли письма?


Автор: m_maxser 2.8.2012, 13:46
Здравствуйте.

В проекте, пользователь сам настраивает в каких случаях получать сообщения сайта на свой ящик. Может вообще от них отказаться, может настроить получение на конкретные события. Делается примерно так:
Код

class PublicationMailer < ActionMailer::Base
  ...
  def new_event(event)
      subject = ' (новое событие)'

      mail(:to => @users_emails.join(','),
         :subject => subject)
  end
end

все нормально работает. 

Теперь стоит задача сохранять отправленные сообщения в базу. Для этого создана модель Message, которая связана с моделью User. Связей четыре, по две с каждой стороны. 

Модель User имеет связи incoming_messages (связь has_many :through) и outgoing_messages (просто has_many). 
Message в свою очередь имеет связи recipients (связь has_many :through) и sender (просто belongs_to).

Из этого видно, что пользователь может просмотреть историю отправленных (созданных им самим) и полученных сообщений. Также как и сообщения знают своего отправителя и получателя.

Раньше многие-ко-многим были описаны как связь has_and_belongs_to_many. И работало примерно так:
Код

class PublicationMailer < ActionMailer::Base
  ...
  def new_event(event)
      subject = ' (новое событие)'

      mail(:to => @users.emails.join(','),
         :subject => subject)
      #render содержит текст отправленного письма
      Message.create(subject, render, @users)
  end
end


Переход на has_many :through был обусловлен тем, что мы хотим запоминать, кому сообщение было отправлено только в личку, а кому еще и на почту. Для этого в промежуточную таблицу message_users было добавленно булевое поле mailed. Таблица  message_users связана с моделью MessageUser и имеет поля: id, message_id, user_id, mailed, created_at, updated_at.

Нужно как-то обновлять поле mailed. Но как?. По сути не сложно пройти по масиву пользователей и просто присваивать mailed=1. Но ведь может быть так, что письмо небыло доставлено по той или иной причине.

Теперь вопросы smile
1. Достаточно ли для проверки на отправку условия if mail(:to => @users.emails.join(','), :subject => subject) или нет?
2. Как лучше сделать? Отправлять всем сразу(как сейчас) или циклом перебирать каждый email  и отправлять письмо? Понимаю, что во втором варианте нагрузка больше, но зато mailed можно менять индивидально для каждого;
3. Как вынести  Message.create за пределы этого класса? Мне кажется, что ему тут не место, но не знаю как тогда сохранить render (текст) письма;
4. Возможно ли подтвердить факт доставки? Или только факт отправки?

Вроде все smile.

Автор: m_maxser 3.8.2012, 14:29
Немного переделал код. Вопрос №3 снят,  Message.create вынесен из метода new_event.
Код

class EventsController < ApplicationController
...
  def create
...
      event = Event .new(params[:event ])
      email = PublicationMailer.new_event(event)
     
      message = Message.create(email.subject.to_s, email.body.to_s, @company.managers)
      
      email.deliver
      
...
  end
end

Теперь это работает почти как надо:
строка 6   - создано сообщение,
строка 8   - сообщение сохранено/ Сохранено для ВСЕХ(!) менеджеров и доступно в личных сообщениях.
строка 10 - сообщение отправляю на ящик ТОЛЬКО подписавшимся на рассылку. 
Код

class PublicationMailer < ActionMailer::Base
  ...
  def new_event(event)
      subject = ' (новое событие)'
      mail(:to => @users_emails.join(','),
         :subject => subject)
  end
end

Код

class Message < ActiveRecord::Base
...  
  def self.create(subject = '', body= '', users = [])
      message = Message.new
      message[:subject] = subject
      message[:body] = body
      message.sender = User.current
      
      message.save
      
      message.recipients = users
  end
end

Дело осталось за малым - как-то обновить поле mailed для тех кому было отправленно письмо. 
Есть ли какой-нибудь объект (или еще, что-то) содержащий информацию об отправке? Т.е. я хочу после срабатывания метода deliver, открыть этот объект, посмотреть были ли ошибки, посмотреть кому письмо было отправленно, а кому - нет. И только потом основываясь на этих данных обновить поле mailed для пользователей, которым письмо было отправленно.

Автор: m_maxser 3.8.2012, 15:07
я не смог найти в Интернете как работает метод deliver. Кроме отправки он, еще что-нибудь делает? Может он возвращает что-нибудь типа true или false? Если да, то можно было бы обыграть как-то так:

Код

if email.deliver
  # теоретический метод изменяющий поле mailed
end


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)