mailboxer 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.rdoc +7 -0
  5. data/Rakefile +53 -0
  6. data/VERSION +1 -0
  7. data/app/models/mailboxer_conversation.rb +60 -0
  8. data/app/models/mailboxer_mail.rb +70 -0
  9. data/app/models/mailboxer_mailbox.rb +68 -0
  10. data/app/models/mailboxer_message.rb +42 -0
  11. data/lib/generators/mailboxer/install_generator.rb +15 -0
  12. data/lib/generators/mailboxer/templates/migration.rb +31 -0
  13. data/lib/mailboxer.rb +8 -0
  14. data/lib/mailboxer/engine.rb +10 -0
  15. data/lib/mailboxer/models/messageable.rb +204 -0
  16. data/mailboxer.gemspec +34 -0
  17. data/spec/dummy/Gemfile +6 -0
  18. data/spec/dummy/Rakefile +7 -0
  19. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  20. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  21. data/spec/dummy/app/models/cylon.rb +3 -0
  22. data/spec/dummy/app/models/duck.rb +3 -0
  23. data/spec/dummy/app/models/user.rb +3 -0
  24. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  25. data/spec/dummy/config.ru +4 -0
  26. data/spec/dummy/config/application.rb +45 -0
  27. data/spec/dummy/config/boot.rb +10 -0
  28. data/spec/dummy/config/database.yml +22 -0
  29. data/spec/dummy/config/environment.rb +5 -0
  30. data/spec/dummy/config/environments/development.rb +26 -0
  31. data/spec/dummy/config/environments/production.rb +49 -0
  32. data/spec/dummy/config/environments/test.rb +35 -0
  33. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  34. data/spec/dummy/config/initializers/inflections.rb +10 -0
  35. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  36. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  37. data/spec/dummy/config/initializers/session_store.rb +8 -0
  38. data/spec/dummy/config/locales/en.yml +5 -0
  39. data/spec/dummy/config/routes.rb +60 -0
  40. data/spec/dummy/db/migrate/20110228120600_create_users.rb +13 -0
  41. data/spec/dummy/db/migrate/20110303122122_create_mailboxer.rb +31 -0
  42. data/spec/dummy/db/migrate/20110306002940_create_ducks.rb +13 -0
  43. data/spec/dummy/db/migrate/20110306015107_create_cylons.rb +13 -0
  44. data/spec/dummy/db/schema.rb +53 -0
  45. data/spec/dummy/public/404.html +26 -0
  46. data/spec/dummy/public/422.html +26 -0
  47. data/spec/dummy/public/500.html +26 -0
  48. data/spec/dummy/public/favicon.ico +0 -0
  49. data/spec/dummy/public/javascripts/application.js +2 -0
  50. data/spec/dummy/public/javascripts/controls.js +965 -0
  51. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  52. data/spec/dummy/public/javascripts/effects.js +1123 -0
  53. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  54. data/spec/dummy/public/javascripts/rails.js +191 -0
  55. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  56. data/spec/dummy/public/stylesheets/scaffold.css +56 -0
  57. data/spec/dummy/script/rails +6 -0
  58. data/spec/factories/cylon.rb +3 -0
  59. data/spec/factories/duck.rb +3 -0
  60. data/spec/factories/user.rb +3 -0
  61. data/spec/integration/mailboxer_message_and_mail_spec.rb +717 -0
  62. data/spec/integration/navigation_spec.rb +9 -0
  63. data/spec/mailboxer_spec.rb +7 -0
  64. data/spec/models/mailboxer_conversation_spec.rb +39 -0
  65. data/spec/models/mailboxer_mail_spec.rb +33 -0
  66. data/spec/models/mailboxer_mailbox_spec.rb +99 -0
  67. data/spec/models/mailboxer_models_messageable_spec.rb +107 -0
  68. data/spec/spec_helper.rb +36 -0
  69. metadata +278 -0
@@ -0,0 +1,12 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/db/*.sqlite3
5
+ spec/dummy/log/*.log
6
+ spec/dummy/tmp/
7
+ **.tmp_*
8
+ Gemfile.lock
9
+ .idea
10
+ .project
11
+ .document
12
+ .settings/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Eduardo Casanova Cuesta
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ = Mailboxer
2
+
3
+ This project is based on the need of a private message system for {ging / social_stream}[https://github.com/ging/social_stream]. Instead of creating our core message system heavily dependent on our development we are trying to implement a generic and potent messaging gem.
4
+
5
+ It is born from the great, but old, code from {lpsergi / acts_as_messageable}[https://github.com/psergi/acts_as_messageable].
6
+
7
+ There is a lack of documentaion and it will be solved as soon as the gem is more stable and had proved to be useful integrated with SocialStream.
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "mailboxer"
16
+ gem.homepage = "http://github.com/roendal/mailboxer"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Private messaging system for rails apps.}
19
+ gem.description = %Q{TODO: longer description of your gem}
20
+ gem.email = "ecasanovac@gmail.com"
21
+ gem.authors = ["Eduardo Casanova Cuesta"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ gem.add_development_dependency('rspec-rails', '~> 2.4.1')
27
+ gem.add_development_dependency('factory_girl', '~> 1.3.2')
28
+ gem.add_development_dependency('forgery', '~> 0.3.6')
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ require 'rspec/core'
33
+ require 'rspec/core/rake_task'
34
+ RSpec::Core::RakeTask.new(:spec) do |spec|
35
+ spec.pattern = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
39
+ spec.pattern = 'spec/**/*_spec.rb'
40
+ spec.rcov = true
41
+ end
42
+
43
+ task :default => :spec
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "mailboxer #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,60 @@
1
+ class MailboxerConversation < ActiveRecord::Base
2
+ attr_reader :originator, :original_message, :last_sender, :last_message, :users
3
+ has_many :mailboxer_messages
4
+ has_many :mailboxer_mails, :through => :mailboxer_messages
5
+ before_create :clean
6
+ scope :participant, lambda {|participant|
7
+ joins(:mailboxer_messages,:mailboxer_mails).select('DISTINCT mailboxer_conversations.*').where('mailboxer_mails.receiver_id' => participant.id,'mailboxer_mails.receiver_type' => participant.class.to_s)
8
+ }
9
+
10
+ #originator of the conversation.
11
+ def originator
12
+ @orignator = self.original_message.sender if @originator.nil?
13
+ return @orignator
14
+ end
15
+
16
+ #first message of the conversation.
17
+ def original_message
18
+ @original_message = self.mailboxer_messages.find(:first, :order => 'created_at') if @original_message.nil?
19
+ return @original_message
20
+ end
21
+
22
+ #sender of the last message.
23
+ def last_sender
24
+ @last_sender = self.last_message.sender if @last_sender.nil?
25
+ return @last_sender
26
+ end
27
+
28
+ #last message in the conversation.
29
+ def last_message
30
+ @last_message = self.mailboxer_messages.find(:first, :order => 'created_at DESC') if @last_message.nil?
31
+ return @last_message
32
+ end
33
+
34
+ def mails(participant=nil)
35
+ return MailboxerMail.conversation(self).receiver(participant) if participant
36
+ return MailboxerMail.conversation(self)
37
+ end
38
+
39
+ #all users involved in the conversation.
40
+ def recipients
41
+ return last_message.get_recipients
42
+ end
43
+
44
+ def get_recipients
45
+ return self.recipients
46
+ end
47
+
48
+ def count_messages
49
+ return MailboxerMessage.conversation(self).count
50
+ end
51
+
52
+ protected
53
+ #[empty method]
54
+ #
55
+ #this gets called before_create. Implement this if you wish to clean out illegal content such as scripts or anything that will break layout. This is left empty because what is considered illegal content varies.
56
+ def clean
57
+ return if subject.nil?
58
+ #strip all illegal content here. (scripts, shit that will break layout, etc.)
59
+ end
60
+ end
@@ -0,0 +1,70 @@
1
+ class MailboxerMail < ActiveRecord::Base
2
+ belongs_to :mailboxer_message
3
+ has_one :mailboxer_conversation, :through => :mailboxer_message
4
+ belongs_to :receiver, :polymorphic => :true
5
+ scope :receiver, lambda { |receiver|
6
+ where(:receiver_id => receiver.id,:receiver_type => receiver.class.to_s)
7
+ }
8
+ scope :message, lambda { |message|
9
+ where(:mailboxer_message_id => message.id)
10
+ }
11
+ scope :conversation, lambda { |conversation|
12
+ joins(:mailboxer_message).where('mailboxer_messages.mailboxer_conversation_id' => conversation.id)
13
+ }
14
+ scope :sentbox, where(:mailbox_type => "sentbox")
15
+ scope :inbox, where(:mailbox_type => "inbox")
16
+ scope :trash, where(:trashed => true)
17
+ scope :read, where(:read => true)
18
+ scope :unread, where(:read => false)
19
+
20
+ class << self
21
+ def mark_as_read(options={})
22
+ where(options).update_all(:read => true)
23
+ end
24
+
25
+ def mark_as_unread(options={})
26
+ where(options).update_all(:read => false)
27
+ end
28
+
29
+ def move_to_trash(options={})
30
+ where(options).update_all(:trashed => true)
31
+ end
32
+
33
+ def untrash(options={})
34
+ where(options).update_all(:trashed => false)
35
+ end
36
+
37
+ def move_to_inbox(options={})
38
+ where(options).update_all(:mailbox_type => :inbox, :trashed => false)
39
+ end
40
+
41
+ def move_to_sentbox(options={})
42
+ where(options).update_all(:mailbox_type => :sentbox, :trashed => false)
43
+ end
44
+ end
45
+
46
+ def mark_as_read
47
+ update_attributes(:read => true)
48
+ end
49
+
50
+ def mark_as_unread
51
+ update_attributes(:read => false)
52
+ end
53
+
54
+ def move_to_trash
55
+ update_attributes(:trashed => true)
56
+ end
57
+
58
+ def untrash
59
+ update_attributes(:trashed => false)
60
+ end
61
+
62
+ def move_to_inbox
63
+ update_attributes(:mailbox_type => :inbox, :trashed => false)
64
+ end
65
+
66
+ def move_to_sentbox
67
+ update_attributes(:mailbox_type => :sentbox, :trashed => false)
68
+ end
69
+
70
+ end
@@ -0,0 +1,68 @@
1
+ class MailboxerMailbox
2
+ #this is used to filter mail by mailbox type, use the [] method rather than setting this directly.
3
+ attr_accessor :type
4
+ #the user/owner of this mailbox, set when initialized.
5
+ attr_reader :messageable
6
+ #creates a new Mailbox instance with the given user and optional type.
7
+
8
+ def initialize(recipient, box = :all)
9
+ @messageable = recipient
10
+ @type = box
11
+ end
12
+ #sets the mailbox type to the symbol corresponding to the given val.
13
+ def type=(val)
14
+ @type = val.to_sym
15
+ end
16
+
17
+ def conversations(options = {})
18
+ return MailboxerConversation.where(options).participant(@messageable)
19
+ end
20
+
21
+ def mail(options = {})
22
+ return MailboxerMail.where(options).receiver(@messageable)
23
+ end
24
+
25
+ def inbox(options = {})
26
+ return self.mail(options).inbox
27
+ end
28
+
29
+ def sentbox(options = {})
30
+ return self.mail(options).sentbox
31
+ end
32
+
33
+ def trash(options = {})
34
+ return self.mail(options).trash
35
+ end
36
+
37
+ def [](mailbox_type)
38
+ self.type = mailbox_type
39
+ return self
40
+ end
41
+
42
+ def <<(msg)
43
+ return self.add(msg)
44
+ end
45
+
46
+ def add(msg)
47
+ mail_msg = MailboxerMail.new
48
+ mail_msg.mailboxer_message = msg
49
+ mail_msg.read = (msg.sender.id == @messageable.id && msg.sender.class == @messageable.class)
50
+ mail_msg.receiver = @messageable
51
+ mail_msg.mailbox_type = @type.to_s unless @type == :all
52
+ @messageable.mailboxer_mails << mail_msg
53
+ return mail_msg
54
+ end
55
+
56
+ def empty_trash(options = {})
57
+ return self.trash(options).delete_all
58
+ end
59
+
60
+ def has_conversation?(conversation)
61
+ return self.mail.conversation(converstaion).count!=0
62
+ end
63
+
64
+ def is_trashed?(conversation)
65
+ return self.trash.conversation(conversation).count!=0
66
+ end
67
+
68
+ end
@@ -0,0 +1,42 @@
1
+ class MailboxerMessage < ActiveRecord::Base
2
+ #any additional info that needs to be sent in a message (ex. I use these to determine request types)
3
+ serialize :headers
4
+
5
+ attr_accessor :recipients
6
+
7
+ class_inheritable_accessor :on_deliver_callback
8
+ protected :on_deliver_callback
9
+ class_inheritable_accessor :on_deliver_clean
10
+ protected :on_deliver_clean
11
+ belongs_to :sender, :polymorphic => :true
12
+ belongs_to :mailboxer_conversation
13
+ has_many :mailboxer_mails
14
+ scope :conversation, lambda { |conversation|
15
+ where(:mailboxer_conversation_id => conversation.id)
16
+ }
17
+
18
+ class << self
19
+ def on_deliver(clean_method, callback_method)
20
+ self.on_deliver_clean = clean_method
21
+ self.on_deliver_callback = callback_method
22
+ end
23
+ end
24
+
25
+ def deliver(mailbox_type, should_clean = true)
26
+ self.on_deliver_clean.call(self) unless self.on_deliver_clean.nil? or !should_clean
27
+ self.save
28
+ self.recipients.each do |r|
29
+ r.mailbox[mailbox_type] << self
30
+ end
31
+ self.on_deliver_callback.call(self, mailbox_type) unless self.on_deliver_callback.nil?
32
+ end
33
+
34
+ def get_recipients
35
+ recipients_array = Array.new
36
+ self.mailboxer_mails.each do |mail|
37
+ recipients_array << mail.receiver
38
+ end
39
+ return recipients_array
40
+ end
41
+
42
+ end
@@ -0,0 +1,15 @@
1
+ class Mailboxer::InstallGenerator < Rails::Generators::Base #:nodoc:
2
+ include Rails::Generators::Migration
3
+
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ require 'rails/generators/active_record'
7
+
8
+ def self.next_migration_number(dirname)
9
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
10
+ end
11
+
12
+ def create_migration_file
13
+ migration_template 'migration.rb', 'db/migrate/create_mailboxer.rb'
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ class CreateMailboxer < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :mailboxer_conversations do |t|
4
+ t.column :subject, :string, :default => ""
5
+ t.column :created_at, :datetime, :null => false
6
+ end
7
+ create_table :mailboxer_mails do |t|
8
+ t.references :receiver, :polymorphic => true
9
+ t.column :mailboxer_message_id, :integer, :null => false
10
+ t.column :read, :boolean, :default => false
11
+ t.column :trashed, :boolean, :default => false
12
+ t.column :mailbox_type, :string, :limit => 25
13
+ t.column :created_at, :datetime, :null => false
14
+ end
15
+ create_table :mailboxer_messages do |t|
16
+ t.column :body, :text
17
+ t.column :subject, :string, :default => ""
18
+ t.column :headers, :text
19
+ t.references :sender, :polymorphic => true
20
+ t.column :mailboxer_conversation_id, :integer
21
+ t.column :sent, :boolean, :default => false
22
+ t.column :created_at, :datetime, :null => false
23
+ end
24
+ end
25
+
26
+ def self.down
27
+ drop_table :mailboxer_mails
28
+ drop_table :mailboxer_conversations
29
+ drop_table :mailboxer_messages
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ module Mailboxer
2
+ module Models
3
+ autoload :Messageable, 'mailboxer/models/messageable'
4
+ end
5
+ end
6
+ # reopen ActiveRecord and include all the above to make
7
+ # them available to all our models if they want it
8
+ require 'mailboxer/engine'
@@ -0,0 +1,10 @@
1
+ module Mailboxer
2
+ class Engine < Rails::Engine
3
+
4
+ initializer "mailboxer.models.messageable" do
5
+ ActiveSupport.on_load(:active_record) do
6
+ include Mailboxer::Models::Messageable
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,204 @@
1
+ module Mailboxer
2
+ module Models
3
+ module Messageable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :mailboxer_messages
8
+ cattr_accessor :mailbox_types
9
+ has_many :mailboxer_mails, :order => 'created_at DESC', :dependent => :delete_all
10
+
11
+ end
12
+ # declare the class level helper methods which
13
+ # will load the relevant instance methods
14
+ # defined below when invoked
15
+ module ClassMethods
16
+ #enables a class to send and receive messages to members of the same class - currently assumes the model is of class type 'User',
17
+ #some modifications to the migrations and model classes will need to be made to use a model of different type
18
+ #
19
+ #====options:
20
+ #* :received - the mailbox type to store received messages (defaults to :inbox)
21
+ #
22
+ #* :sent - the mailbox type to store sent messages (defaults to :sentbox)
23
+ #
24
+ #* :deleted - the mailbox type to store deleted messages (defaults to :trash)
25
+ #
26
+ #====example:
27
+ # acts_as_messageable :received => :in, :sent => :sent, :deleted => :garbage
28
+ def acts_as_messageable
29
+ include Mailboxer::Models::Messageable::InstanceMethods
30
+ end
31
+ end
32
+
33
+ #Adds class methods
34
+ #module SingletonMethods
35
+ #end
36
+
37
+ # Adds instance methods.
38
+ module InstanceMethods
39
+ #returns an instance of class type Mailbox - this object essentially wraps the user's mail messages and provides a clean interface for accessing them.
40
+ #see Mailbox for more details.
41
+ #
42
+ #====example:
43
+ # phil = User.find(3123)
44
+ # phil.mailbox[:inbox].unread_mail #returns all unread mail in your inbox
45
+ # phil.mailbox[:sentbox].mail #returns all sent mail messages
46
+ #
47
+ def mailbox
48
+ @mailbox = MailboxerMailbox.new(self) if @mailbox.nil?
49
+ @mailbox.type = :all
50
+ return @mailbox
51
+ end
52
+ #creates new Message and Conversation objects from the given parameters and delivers Mail to each of the recipients' inbox.
53
+ #
54
+ #====params:
55
+ #recipients::
56
+ # a single user object or array of users to deliver the message to.
57
+ #msg_body::
58
+ # the body of the message.
59
+ #subject::
60
+ # the subject of the message, defaults to empty string if not provided.
61
+ #====returns:
62
+ #the sent Mail.
63
+ #
64
+ #====example:
65
+ # phil = User.find(3123)
66
+ # todd = User.find(4141)
67
+ # phil.send_message(todd, 'whats up for tonight?', 'hey guy') #sends a Mail message to todd's inbox, and a Mail message to phil's sentbox
68
+ #
69
+ def send_message(recipients, msg_body, subject = '')
70
+ convo = MailboxerConversation.create({:subject => subject})
71
+ message = MailboxerMessage.create({:sender => self, :mailboxer_conversation => convo, :body => msg_body, :subject => subject})
72
+ message.recipients = recipients.is_a?(Array) ? recipients : [recipients]
73
+ message.deliver(:inbox)
74
+ return mailbox[:sentbox] << message
75
+ end
76
+ #creates a new Message associated with the given conversation and delivers the reply to each of the given recipients.
77
+ #
78
+ #*explicitly calling this method is rare unless you are replying to a subset of the users involved in the conversation or
79
+ #if you are including someone that is not currently in the conversation.
80
+ #reply_to_sender, reply_to_all, and reply_to_conversation will suffice in most cases.
81
+ #
82
+ #====params:
83
+ #conversation::
84
+ # the Conversation object that the mail you are responding to belongs.
85
+ #recipients::
86
+ # a single User object or array of Users to deliver the reply message to.
87
+ #reply_body::
88
+ # the body of the reply message.
89
+ #subject::
90
+ # the subject of the message, defaults to 'RE: [original subject]' if one isnt given.
91
+ #====returns:
92
+ #the sent Mail.
93
+ #
94
+ def reply(conversation, recipients, reply_body, subject = nil)
95
+ return nil if(reply_body.blank?)
96
+ subject = subject || "RE: #{conversation.subject}"
97
+ response = MailboxerMessage.create({:sender => self, :mailboxer_conversation => conversation, :body => reply_body, :subject => subject})
98
+ response.recipients = recipients.is_a?(Array) ? recipients : [recipients]
99
+ response.deliver(:inbox)
100
+ return mailbox[:sentbox] << response
101
+ end
102
+ #sends a Mail to the sender of the given mail message.
103
+ #
104
+ #====params:
105
+ #mail::
106
+ # the Mail object that you are replying to.
107
+ #reply_body::
108
+ # the body of the reply message.
109
+ #subject::
110
+ # the subject of the message, defaults to 'RE: [original subject]' if one isnt given.
111
+ #====returns:
112
+ #the sent Mail.
113
+ #
114
+ def reply_to_sender(mail, reply_body, subject = nil)
115
+ return reply(mail.mailboxer_conversation, mail.mailboxer_message.sender, reply_body, subject)
116
+ end
117
+ #sends a Mail to all of the recipients of the given mail message (excluding yourself).
118
+ #
119
+ #====params:
120
+ #mail::
121
+ # the Mail object that you are replying to.
122
+ #reply_body::
123
+ # the body of the reply message.
124
+ #subject::
125
+ # the subject of the message, defaults to 'RE: [original subject]' if one isnt given.
126
+ #====returns:
127
+ #the sent Mail.
128
+ #
129
+ def reply_to_all(mail, reply_body, subject = nil)
130
+ msg = mail.mailboxer_message
131
+ recipients = msg.get_recipients
132
+ if(msg.sender != self)
133
+ recipients.delete(self)
134
+ if(!recipients.include?(msg.sender))
135
+ recipients << msg.sender
136
+ end
137
+ end
138
+ return reply(mail.mailboxer_conversation, recipients, reply_body, subject)
139
+ end
140
+ #sends a Mail to all users involved in the given conversation (excluding yourself).
141
+ #
142
+ #*this may have undesired effects if users have been added to the conversation after it has begun.
143
+ #
144
+ #====params:
145
+ #conversation::
146
+ # the Conversation object that the mail you are responding to belongs.
147
+ #reply_body::
148
+ # the body of the reply message.
149
+ #subject::
150
+ # the subject of the message, defaults to 'RE: [original subject]' if one isnt given.
151
+ #====returns:
152
+ #the sent Mail.
153
+ #
154
+ def reply_to_conversation(conversation, reply_body, subject = nil)
155
+ #move conversation to inbox if it is currently in the trash - doesnt make much sense replying to a trashed convo.
156
+ if(mailbox.is_trashed?(conversation))
157
+ mailbox.mail.conversation(conversation).untrash
158
+ end
159
+ #remove self from recipients unless you are the originator of the convo
160
+ recipients = conversation.get_recipients
161
+ if(conversation.originator != self)
162
+ recipients.delete(self)
163
+ if(!recipients.include?(conversation.originator))
164
+ recipients << conversation.originator
165
+ end
166
+ end
167
+ return reply(conversation,recipients, reply_body, subject)
168
+ end
169
+ #returns the mail given as the parameter, marked as read.
170
+ def read_mail(mail)
171
+ return mail.mark_as_read if mail.receiver == self
172
+ end
173
+ #returns the mail given as the parameter, marked as unread.
174
+ def unread_mail(mail)
175
+ return mail.mark_as_unread if mail.receiver == self
176
+ end
177
+ #returns an array of the user's Mail associated with the given conversation.
178
+ #All mail is marked as read but the returning array is built before this so you can see which messages were unread when viewing the conversation.
179
+ #
180
+ #???This returns deleted/trashed messages as well for the purpose of reading trashed convos, to disable this send the option ':conditions => "mail.trashed != true"'
181
+ #
182
+ #====params:
183
+ #conversation::
184
+ # the Conversation object that you want to read.
185
+ #options::
186
+ # any options to filter the conversation, these are used as find options so all valid options for find will work.
187
+ #
188
+ #====returns:
189
+ #array of Mail belonging to the given conversation.
190
+ #
191
+ def read_conversation(conversation, options = {})
192
+ mails = conversation.mailboxer_mails.receiver(self)
193
+ mails_clone = mails.clone
194
+
195
+ mails.each do |mail|
196
+ mail.mark_as_read
197
+ end
198
+
199
+ return mails_clone
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end