has_emails 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. data/CHANGELOG +8 -0
  2. data/README +32 -71
  3. data/Rakefile +8 -8
  4. data/app/models/email.rb +7 -79
  5. data/app/models/email_address.rb +32 -110
  6. data/db/migrate/001_create_email_addresses.rb +4 -13
  7. data/lib/has_emails/extensions/action_mailer.rb +106 -0
  8. data/lib/has_emails.rb +50 -77
  9. data/test/app_root/app/models/empty +0 -0
  10. data/test/app_root/config/environment.rb +4 -27
  11. data/test/app_root/db/migrate/001_migrate_has_messages_to_version_2.rb +9 -0
  12. data/test/app_root/db/migrate/002_migrate_has_emails_to_version_1.rb +9 -0
  13. data/test/factory.rb +48 -0
  14. data/test/functional/has_emails_test.rb +139 -0
  15. data/test/test_helper.rb +5 -68
  16. data/test/unit/action_mailer_test.rb +57 -0
  17. data/test/unit/email_address_test.rb +100 -152
  18. data/test/unit/email_test.rb +26 -86
  19. metadata +78 -87
  20. data/app/mailers/application_mailer.rb +0 -85
  21. data/app/models/email_recipient.rb +0 -78
  22. data/app/models/email_recipient_build_extension.rb +0 -7
  23. data/db/bootstrap/events.yml +0 -4
  24. data/db/bootstrap/states.yml +0 -9
  25. data/db/migrate/002_add_email_specs.rb +0 -18
  26. data/db/migrate/003_add_email_recipient_specs.rb +0 -18
  27. data/test/app_root/app/models/department.rb +0 -2
  28. data/test/app_root/app/models/user.rb +0 -3
  29. data/test/app_root/db/migrate/001_create_users.rb +0 -11
  30. data/test/app_root/db/migrate/002_create_departments.rb +0 -12
  31. data/test/fixtures/departments.yml +0 -9
  32. data/test/fixtures/email_addresses.yml +0 -32
  33. data/test/fixtures/message_recipients.yml +0 -85
  34. data/test/fixtures/messages.yml +0 -52
  35. data/test/fixtures/state_changes.yml +0 -128
  36. data/test/fixtures/users.yml +0 -11
  37. data/test/unit/application_mailer_test.rb +0 -69
  38. data/test/unit/email_recipient_test.rb +0 -79
  39. data/test/unit/has_emails_test.rb +0 -36
  40. data/test/unit/recipient_extension_test.rb +0 -99
data/CHANGELOG CHANGED
@@ -1,5 +1,13 @@
1
1
  *SVN*
2
2
 
3
+ *0.1.0* (May 5th, 2008)
4
+
5
+ * Update to latest has_messages api
6
+
7
+ * Simplify by removing support for models other than EmailAddresses in Emails
8
+
9
+ * Updated documentation
10
+
3
11
  *0.0.1* (September 26th, 2007)
4
12
 
5
13
  * Refactor has_email_address/has_email_addresses so that new associations for unsent/sent emails isn't created for has_email_address
data/README CHANGED
@@ -1,28 +1,25 @@
1
1
  = has_emails
2
2
 
3
- +has_emails+ adds support for emailing capabilities between ActiveRecord models.
3
+ +has_emails+ demonstrates a reference implementation for sending emails with
4
+ logging and asynchronous support.
4
5
 
5
6
  == Resources
6
7
 
7
- API
8
-
9
- * http://api.pluginaweek.org/has_emails
10
-
11
8
  Wiki
12
9
 
13
10
  * http://wiki.pluginaweek.org/Has_emails
14
11
 
15
- Announcement
12
+ API
16
13
 
17
- * http://www.pluginaweek.org
14
+ * http://api.pluginaweek.org/has_emails
18
15
 
19
- Source
16
+ Development
20
17
 
21
- * http://svn.pluginaweek.org/trunk/plugins/active_record/has/has_emails
18
+ * http://dev.pluginaweek.org/browser/trunk/has_emails
22
19
 
23
- Development
20
+ Source
24
21
 
25
- * http://dev.pluginaweek.org/browser/trunk/plugins/active_record/has/has_emails
22
+ * http://svn.pluginaweek.org/trunk/has_emails
26
23
 
27
24
  == Description
28
25
 
@@ -33,43 +30,29 @@ web application to send notices and other notifications to users.
33
30
 
34
31
  Rails already provides ActionMailer as a way of sending emails. However, the
35
32
  framework does not provide an easy way to persist emails, track their status, and
36
- process them asynchronously. Designing and building this type of framework can
37
- become complex and cumbersome and takes away from the focus of the web application.
38
- This plugin helps ease that process by providing a complete implementation for
39
- sending and receiving emails to and between models in your application.
33
+ process them asynchronously. Designing and building a framework that supports this
34
+ can be complex and takes away from the business focus. This plugin can help ease
35
+ that process by demonstrating a complete implementation of these features.
40
36
 
41
37
  == Usage
42
38
 
43
- === Adding emailing support
44
-
45
- If you want to use the built-in support for email addresses (using the EmailAddress
46
- model), you can add emailing support for users like so:
47
-
48
- class User < ActiveRecord::Base
49
- has_email_address
50
- # has_email_addresses if you want to support multiple addresses
51
- end
39
+ === Creating new emails
52
40
 
53
- On the other hand, if you already have the email address for users stored as a
54
- column in your users table, you can add emailing support like so:
41
+ Emails should usually still be created using ActionMailer. However, instead of
42
+ delivering the emails, you can queue the emails like so:
55
43
 
56
- class User < ActiveRecord::Base
57
- has_messages :emails,
58
- :message_class => 'Email'
59
- end
44
+ Notifier.deliver_signup_notification(david) # sends the email now
45
+ Notifier.queue_signup_notification(david) # sends the email later (has_emails kicks in)
60
46
 
61
- === Creating new emails
47
+ In addition to queueing emails, you can build them directly like so:
62
48
 
63
- email = user.emails.build
64
- email.to << [user1, email_address1, 'someone@somewhere.com']
49
+ email_address = EmailAddress.find(123)
50
+ email = email_address.emails.build
51
+ email.to EmailAddress.find(456)
65
52
  email.subject = 'Hey!'
66
53
  email.body = 'Does anyone want to go out tonight?'
67
54
  email.deliver!
68
55
 
69
- As can be seen in the above example, you can use Users, EmailAddresses, or even
70
- Strings as recipients in emails. Each will be automatically converted to the
71
- EmailRecipient class so that it can be stored in the database.
72
-
73
56
  === Replying to emails
74
57
 
75
58
  reply = email.reply_to_all
@@ -82,49 +65,27 @@ EmailRecipient class so that it can be stored in the database.
82
65
  forward.body = 'Interested?'
83
66
  forward.deliver!
84
67
 
85
- === External process messaging
68
+ === Processing email asynchronously
86
69
 
87
70
  In addition to delivering emails immediately, you can also *queue* emails so
88
- that an external application processes and delivers them. This is especially
89
- useful when you want to asynchronously send e-mails so that it doesn't block the
90
- user interface on your web application.
91
-
92
- To queue emails for external processing, you can simply use the <tt>queue!</tt>
93
- event, rather than <tt>deliver!</tt>. This will indicate to any external processes
94
- that the email is ready to be sent. The external process can then invoke <tt>deliver!</tt>
95
- whenever it is ready to send the queued email.
71
+ that an external application processes and delivers them (as mentioned above).
72
+ This is especially useful when you want to asynchronously send e-mails so that
73
+ it doesn't block the user interface on your web application.
96
74
 
97
- === Running migrations
75
+ To process queued emails, you need an external cron job that checks and sends
76
+ them like so:
98
77
 
99
- To migrate the tables required for this plugin, you can either run the
100
- migration from the command line like so:
101
-
102
- rake db:migrate:plugins PLUGIN=has_emails
103
-
104
- or (more ideally) generate a migration file that will integrate into your main
105
- application's migration path:
106
-
107
- ruby script/generate plugin_migration has_emails
78
+ Email.with_state('queued').each do |email|
79
+ email.deliver!
80
+ end
108
81
 
109
82
  == Testing
110
83
 
111
- Before you can run any tests, the following gems must be installed:
84
+ Before you can run any tests, the following gem must be installed:
112
85
  * plugin_test_helper[http://wiki.pluginaweek.org/Plugin_test_helper]
113
- * dry_validity_assertions[http://wiki.pluginaweek.org/Dry_validity_assertions]
114
86
 
115
87
  == Dependencies
116
88
 
117
- This plugin depends on the presence of the following plugins:
89
+ * plugins_plus[http://wiki.pluginaweek.org/Plugins_plus]
118
90
  * has_messages[http://wiki.pluginaweek.org/Has_messages]
119
-
120
- This plugin is also a plugin+. That means that it contains a slice of an
121
- application, such as models and migrations. To test or use a plugin+, you
122
- must have the following plugins/gems installed:
123
- * plugin_dependencies[http://wiki.pluginaweek.org/Plugin_dependencies]
124
- * loaded_plugins[http://wiki.pluginaweek.org/Loaded_plugins]
125
- * appable_plugins[http://wiki.pluginaweek.org/Appable_plugins]
126
- * plugin_migrations[http://wiki.pluginaweek.org/Plugin_migrations]
127
-
128
- Instead of installing each individual plugin+ feature, you can install them all
129
- at once using the plugins+[http://wiki.pluginaweek.org/Plugins_plus] meta package,
130
- which contains all additional features.
91
+ * state_machine[http://wiki.pluginaweek.org/State_machine]
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'rake/gempackagetask'
4
4
  require 'rake/contrib/sshpublisher'
5
5
 
6
6
  PKG_NAME = 'has_emails'
7
- PKG_VERSION = '0.0.1'
7
+ PKG_VERSION = '0.1.0'
8
8
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
9
9
  RUBY_FORGE_PROJECT = 'pluginaweek'
10
10
 
@@ -31,18 +31,18 @@ spec = Gem::Specification.new do |s|
31
31
  s.name = PKG_NAME
32
32
  s.version = PKG_VERSION
33
33
  s.platform = Gem::Platform::RUBY
34
- s.summary = 'Adds support for emailing capabilities between ActiveRecord models.'
34
+ s.summary = 'Demonstrates a reference implementation for sending emails with logging and asynchronous support.'
35
35
 
36
36
  s.files = FileList['{app,db,lib,test}/**/*'].to_a + %w(CHANGELOG init.rb MIT-LICENSE Rakefile README)
37
37
  s.require_path = 'lib'
38
38
  s.autorequire = 'has_emails'
39
39
  s.has_rdoc = true
40
40
  s.test_files = Dir['test/**/*_test.rb']
41
- s.add_dependency 'has_messages', '>= 0.0.1'
42
- s.add_dependency 'validates_as_email_address', '>= 0.0.1'
41
+ s.add_dependency 'has_messages', '>= 0.1.0'
42
+ s.add_dependency 'validates_as_email_address', '>= 0.0.2'
43
43
 
44
- s.author = 'Aaron Pfeifer, Neil Abraham'
45
- s.email = 'info@pluginaweek.org'
44
+ s.author = 'Aaron Pfeifer'
45
+ s.email = 'aaron@pluginaweek.org'
46
46
  s.homepage = 'http://www.pluginaweek.org'
47
47
  end
48
48
 
@@ -54,12 +54,12 @@ end
54
54
 
55
55
  desc 'Publish the beta gem'
56
56
  task :pgem => [:package] do
57
- Rake::SshFilePublisher.new('pluginaweek@pluginaweek.org', '/home/pluginaweek/gems.pluginaweek.org/gems', 'pkg', "#{PKG_FILE_NAME}.gem").upload
57
+ Rake::SshFilePublisher.new('aaron@pluginaweek.org', '/home/aaron/gems.pluginaweek.org/public/gems', 'pkg', "#{PKG_FILE_NAME}.gem").upload
58
58
  end
59
59
 
60
60
  desc 'Publish the API documentation'
61
61
  task :pdoc => [:rdoc] do
62
- Rake::SshDirPublisher.new('pluginaweek@pluginaweek.org', "/home/pluginaweek/api.pluginaweek.org/#{PKG_NAME}", 'rdoc').upload
62
+ Rake::SshDirPublisher.new('aaron@pluginaweek.org', "/home/aaron/api.pluginaweek.org/public/#{PKG_NAME}", 'rdoc').upload
63
63
  end
64
64
 
65
65
  desc 'Publish the API docs and gem'
data/app/models/email.rb CHANGED
@@ -1,84 +1,12 @@
1
1
  # Represents an email which has been sent to one or more recipients. This is
2
- # essentially the same as the Message class, but overrides the +to+, +cc+, and +bcc+
3
- # associations to that proper instances of the MessageRecipient class are created.
2
+ # essentially the same as the Message class, but overrides how the it is
3
+ # delivered.
4
4
  class Email < Message
5
- validates_presence_of :sender_spec
6
- validates_as_email_address :sender_spec,
7
- :allow_nil => true
8
-
9
- with_options(
10
- :class_name => 'EmailRecipient',
11
- :foreign_key => 'message_id',
12
- :order => 'position ASC',
13
- :dependent => true
14
- ) do |e|
15
- e.has_many :to,
16
- :conditions => ['kind = ?', 'to'],
17
- :extend => [MessageRecipientToBuildExtension, EmailRecipientBuildExtension]
18
- e.has_many :cc,
19
- :conditions => ['kind = ?', 'cc'],
20
- :extend => [MessageRecipientCcBuildExtension, EmailRecipientBuildExtension]
21
- e.has_many :bcc,
22
- :conditions => ['kind = ?', 'bcc'],
23
- :extend => [MessageRecipientBccBuildExtension, EmailRecipientBuildExtension]
24
- end
25
-
26
- # Returns the sender of the message. This can be a string if being sent
27
- # from an arbitrary e-mail address.
28
- def sender_with_spec
29
- sender_without_spec || sender_spec
30
- end
31
- alias_method_chain :sender, :spec
32
-
33
- # If sender is a string, then sets the spec, otherwise uses the original
34
- # sender setter
35
- def sender_with_spec=(value)
36
- self.sender_spec = EmailAddress.convert_from(value).spec
37
- self.sender_without_spec = value if !value.is_a?(String)
38
- end
39
- alias_method_chain :sender=, :spec
40
-
41
- # Converts the sender into an Email Address, whether it be a string,
42
- # EmailAddress, or other model type
43
- def sender_email_address
44
- EmailAddress.convert_from(sender_spec)
45
- end
46
-
47
- # The name of the person whose sending the email
48
- def sender_name
49
- sender_without_spec ? EmailAddress.convert_from(sender_without_spec).name : sender_email_address.name
50
- end
51
-
52
- # Returns a string version of the email address plus any name like
53
- # "John Doe <john.doe@gmail.com>"..
54
- def sender_with_name
55
- address = self.email_address
56
- address.name = self.name
57
- address.with_name
58
- end
59
-
60
- # Actually delivers the email to the recipients
61
- def deliver
62
- ApplicationMailer.deliver_email(self)
63
- end
64
-
65
- # Saves the +sender_spec+ in the forwarded message
66
- def forward
67
- message = super
68
- message.sender_spec = sender_spec
69
- message
70
- end
71
-
72
- # Saves the +sender_spec+ in the replied message
73
- def reply
74
- message = super
75
- message.sender_spec = sender_spec
76
- message
77
- end
5
+ after_deliver :deliver_email
78
6
 
79
7
  private
80
- # Strings are allowed to participate in messaging
81
- def model_participant?
82
- sender_id && sender_type || sender_spec.nil?
83
- end
8
+ # Actually delivers the email to the recipients
9
+ def deliver_email
10
+ ActionMailer::Base.deliver_email(self)
11
+ end
84
12
  end
@@ -1,123 +1,45 @@
1
1
  # Represents a valid RFC822 email address
2
2
  class EmailAddress < ActiveRecord::Base
3
+ has_emails
4
+
5
+ validates_presence_of :spec
6
+ validates_as_email_address :spec
7
+ validates_uniqueness_of :spec,
8
+ :scope => 'name'
9
+
3
10
  class << self
4
- # Converts the specified record to an EmailAddress. It will convert the
5
- # following types:
6
- # 1. String
7
- # 2. A record with an +email_address+ String attribute
8
- # 3. A record with an +email_address+ association
9
- # 4. A record with an +email_addresses+ association (first record will be chosen)
10
- #
11
- # If an EmailAddress is specified, the same model will be returned. An
12
- # ArgumentError is raised if it doesn't match any of the above criteria.
13
- def convert_from(record)
14
- if record
15
- if EmailAddress === record
16
- record
17
- elsif String === record
18
- EmailAddress.new(:spec => record)
19
- elsif record.respond_to?(:email_address)
20
- if record.email_address.is_a?(String)
21
- address = EmailAddress.new(:spec => record.email_address)
22
- address.name = record.name if record.respond_to?(:name)
23
- address
24
- else
25
- record.email_address
26
- end
27
- elsif record.respond_to?(:email_addresses)
28
- record.email_addresses.first
29
- else
30
- raise ArgumentError, "Cannot convert #{record.class} to an EmailAddress"
31
- end
32
- end
11
+ # Finds or create an email address based on the given value
12
+ def find_or_create_by_address(address)
13
+ name, spec = split_address(address)
14
+ find_or_create_by_name_and_spec(name, spec)
33
15
  end
34
16
 
35
- # Determines if the given spec is a valid address using the RFC822 spec
36
- def valid?(spec)
37
- !RFC822::EmailAddress.match(spec).nil?
17
+ # Splits the given address into a name and spec
18
+ def split_address(address)
19
+ if match = /^(\S.*)\s+<(.*)>$/.match(address)
20
+ name = match[1]
21
+ spec = match[2]
22
+ else
23
+ spec = address
24
+ end
25
+
26
+ return name, spec
38
27
  end
39
28
  end
40
29
 
41
- acts_as_tokenized :token_field => 'verification_code', :token_length => 32
42
-
43
- # Support e-mail address verification
44
- has_states :initial => :unverified
45
-
46
- # Add messaging capabilities. This will give us an email_box.
47
- has_messages :emails,
48
- :message_class => 'Email'
49
- belongs_to :emailable,
50
- :polymorphic => true
51
-
52
- validates_presence_of :spec
53
-
54
- with_options(:allow_nil => true) do |klass|
55
- klass.validates_uniqueness_of :spec
56
- klass.validates_as_email_address :spec
57
- end
58
-
59
- # The name of the person who owns this email address
60
- attr_accessor :name
61
-
62
- # Ensure that the e-mail address has a verification code that can be sent
63
- # to the user
64
- before_create :set_code_expiry
65
-
66
- state :unverified, :verified
67
-
68
- # Verifies that the email address is valid
69
- event :verify do
70
- transition_to :verified, :from => :unverified
71
- end
72
-
73
- # Sets the full address
74
- def spec=(new_spec)
75
- @local_name = @domain = nil
76
- write_attribute(:spec, new_spec)
77
- end
78
-
79
- # The part of the e-mail address before the @
80
- def local_name
81
- parse_spec if !@local_name
82
- @local_name
83
- end
84
-
85
- # The part of the e-mail address after the @
86
- def domain
87
- parse_spec if !@domain
88
- @domain
89
- end
90
-
91
- # Gets the name of the person whose email address this is. Default is an
92
- # empty string. Override this if you want it to appear in with_name
93
- def name
94
- @name || ''
30
+ # Sets the value to be used for this email address. This can come in two formats:
31
+ # * With name - John Doe <john.doe@gmail.com>
32
+ # * Without name - john.doe@gmail.com
33
+ def address=(address)
34
+ self.name, self.spec = self.class.split_address(address)
95
35
  end
96
36
 
97
- # Returns a string version of the email address plus any name like
98
- # "John Doe <john.doe@gmail.com>". In order to have a valid name within the
99
- # string, you must override +name+.
37
+ # Generates the value for the email address, including the name associated with
38
+ # it (if provided). For example,
39
+ #
40
+ # e = EmailAddress.new(:name => 'John Doe', :spec => 'john.doe@gmail.com')
41
+ # e.with_name # => "John Doe <john.doe@gmail.com>"
100
42
  def with_name
101
- name.blank? ? to_s : "#{name} <#{to_s}>"
102
- end
103
-
104
- # Returns the full email address (without the name)
105
- def to_s #:nodoc
106
- spec
107
- end
108
-
109
- private
110
- # Sets the time at which the verification code will expire
111
- def set_code_expiry
112
- self.code_expiry = 48.hour.from_now
113
- end
114
-
115
- # Parses the current spec and sets +@local_name+ and +@domain+ based on the
116
- # matching groups within the regular expression
117
- def parse_spec
118
- if !@local_name && !@domain && match = RFC822::EmailAddress.match(spec)
119
- @local_name = match.captures[0]
120
- @domain = match.captures[1]
121
- end
43
+ name.blank? ? spec : "#{name} <#{spec}>"
122
44
  end
123
45
  end
@@ -1,23 +1,14 @@
1
1
  class CreateEmailAddresses < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table :email_addresses do |t|
4
- t.column :emailable_id, :integer, :null => false, :references => nil
5
- t.column :emailable_type, :string, :null => false
6
- t.column :spec, :string, :null => false, :limit => 382
7
- t.column :verification_code, :string, :limit => 40
8
- t.column :code_expiry, :datetime
9
- t.column :created_at, :timestamp, :null => false
10
- t.column :updated_at, :datetime, :null => false
4
+ t.string :spec, :null => false, :limit => 382
5
+ t.string :name
6
+ t.timestamps
11
7
  end
12
- add_index :email_addresses, :spec, :unique => true
13
- add_index :email_addresses, :verification_code, :unique => true
14
-
15
- PluginAWeek::Has::States.migrate_up(:email_addresses)
8
+ add_index :email_addresses, [:spec, :name], :unique => true
16
9
  end
17
10
 
18
11
  def self.down
19
- PluginAWeek::Has::States.migrate_down(:email_addresses)
20
-
21
12
  drop_table :email_addresses
22
13
  end
23
14
  end
@@ -0,0 +1,106 @@
1
+ module PluginAWeek #:nodoc:
2
+ module HasEmails
3
+ module Extensions #:nodoc:
4
+ #
5
+ module ActionMailer
6
+ def self.included(base) #:nodoc:
7
+ base.class_eval do
8
+ @@default_subject_prefix = "[#{File.basename(File.expand_path(Rails.root)).camelize}] "
9
+ cattr_accessor :default_subject_prefix
10
+
11
+ # Specify the prefix to use for the subject. This defaults to the
12
+ # +default_subject_prefix+ specified for ApplicationMailer.
13
+ adv_attr_accessor :subject_prefix
14
+
15
+ include PluginAWeek::HasEmails::Extensions::ActionMailer::InstanceMethods
16
+ extend PluginAWeek::HasEmails::Extensions::ActionMailer::ClassMethods
17
+ end
18
+ end
19
+
20
+ module ClassMethods
21
+ def self.extended(base) #:nodoc:
22
+ class << base
23
+ alias_method_chain :method_missing, :has_emails
24
+ end
25
+ end
26
+
27
+ # Handles calls to queue_*
28
+ def method_missing_with_has_emails(method_symbol, *parameters)
29
+ case method_symbol.id2name
30
+ when /^queue_([_a-z]\w*)/
31
+ # Queues the mail so that it's processed in the background
32
+ new($1, *parameters).queue
33
+ else
34
+ # Handle the mail delivery as normal
35
+ method_missing_without_has_emails(method_symbol, *parameters)
36
+ end
37
+ end
38
+ end
39
+
40
+ module InstanceMethods
41
+ def self.included(base) #:nodoc:
42
+ base.class_eval do
43
+ alias_method_chain :initialize_defaults, :subject_prefix
44
+ alias_method_chain :subject, :prefix
45
+ alias_method :subject=, :subject_with_prefix
46
+ end
47
+ end
48
+
49
+ # Sets or gets the subject of the email. All subjects are prefixed with a
50
+ # value indicating the application it is coming from.
51
+ def subject_with_prefix(*parameters)
52
+ if parameters.empty?
53
+ subject_without_prefix
54
+ else
55
+ subject_without_prefix(subject_prefix + subject_without_prefix(*parameters))
56
+ end
57
+ end
58
+
59
+ # Sets the default subject prefix
60
+ def initialize_defaults_with_subject_prefix(method_name) #:nodoc
61
+ initialize_defaults_without_subject_prefix(method_name)
62
+ @subject_prefix ||= ::ActionMailer::Base.default_subject_prefix.dup
63
+ end
64
+
65
+ # Delivers an email based on the content in the specified email
66
+ def email(email)
67
+ @from = email.sender.with_name
68
+ @recipients = email.to.map(&:with_name)
69
+ @cc = email.cc.map(&:with_name)
70
+ @bcc = email.bcc.map(&:with_name)
71
+ @subject = email.subject || ''
72
+ @body = email.body || ''
73
+ @sent_on = email.updated_at
74
+ end
75
+
76
+ # Queues the current e-mail that has been constructed
77
+ def queue
78
+ Email.transaction do
79
+ # Create the main email
80
+ email = Email.new(
81
+ :sender => EmailAddress.find_or_create_by_address(from),
82
+ :subject => subject,
83
+ :body => body,
84
+ :to => email_addresses_for(:recipients),
85
+ :cc => email_addresses_for(:cc),
86
+ :bcc => email_addresses_for(:bcc)
87
+ )
88
+ email.queue!
89
+ end
90
+ end
91
+
92
+ private
93
+ # Finds or creates all of the email addresses for the given type of
94
+ # recipient (can be :recipients, :cc, or :bcc)
95
+ def email_addresses_for(kind)
96
+ [send(kind)].flatten.collect {|address| EmailAddress.find_or_create_by_address(address)}
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ ActionMailer::Base.class_eval do
105
+ include PluginAWeek::HasEmails::Extensions::ActionMailer
106
+ end