has_emails 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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