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
@@ -1,85 +0,0 @@
1
- # Provides base operations for emailing
2
- class ApplicationMailer < ActionMailer::Base
3
- @@default_subject_prefix = "[#{File.basename(File.expand_path(RAILS_ROOT)).camelize}] "
4
- cattr_accessor :default_subject_prefix
5
-
6
- # Specify the prefix to use for the subject. This defaults to the
7
- # +default_subject_prefix+ specified for ApplicationMailer.
8
- adv_attr_accessor :subject_prefix
9
-
10
- class << self
11
- def method_missing(method_symbol, *parameters) #:nodoc:
12
- case method_symbol.id2name
13
- when /^queue_([_a-z]\w*)/ then new($1, *parameters).queue
14
- else super
15
- end
16
- end
17
- end
18
-
19
- alias_method :to, :recipients
20
-
21
- # Sets or gets the subject of the email. All subjects are prefixed with a
22
- # value indicating the application it is coming from.
23
- def subject(*parameters)
24
- if parameters.empty?
25
- super
26
- else
27
- super(subject_prefix + super)
28
- end
29
- end
30
- alias_method :subject=, :subject
31
-
32
- # Delivers an email based on the content in the specified email
33
- def email(email)
34
- @from = email.sender
35
- @recipients = email.to
36
- @cc = email.cc
37
- @bcc = email.bcc
38
- @subject = email.subject
39
- @body = email.body
40
- @sent_on = email.sent_at || Time.now
41
- end
42
-
43
- # Queues the current e-mail that has been constructed
44
- def queue
45
- Email.transaction do
46
- # Create the main email
47
- email = Email.create!(
48
- :sender => from,
49
- :subject => subject,
50
- :body => body
51
- )
52
-
53
- # Add recipients
54
- email.to = [to].flatten
55
- email.cc = [cc].flatten
56
- email.bcc = [bcc].flatten
57
- email.queue!
58
- end
59
- end
60
-
61
- private
62
- def initialize_defaults(method_name) #:nodoc
63
- @sent_on ||= Time.now
64
- @subject_prefix ||= @@default_subject_prefix.dup
65
- @recipients ||= []
66
- @cc ||= []
67
- @bcc ||= []
68
-
69
- super
70
- end
71
-
72
- def quote_address_if_necessary_with_conversion(address, charset) #:nodoc
73
- # Uses is_a? instead of === because of AssociationProxy
74
- if !address.is_a?(Array)
75
- if EmailAddress === address || EmailRecipient === address
76
- address = address.with_name
77
- elsif !(String === address)
78
- address = EmailAddress.convert_from(address).to_s
79
- end
80
- end
81
-
82
- quote_address_if_necessary_without_conversion(address, charset)
83
- end
84
- alias_method_chain :quote_address_if_necessary, :conversion
85
- end
@@ -1,78 +0,0 @@
1
- # Represents a recipient on an email
2
- class EmailRecipient < MessageRecipient
3
- validates_presence_of :receiver_spec
4
- validates_as_email_address :receiver_spec,
5
- :allow_nil => true
6
-
7
- before_save :ensure_exclusive_references
8
-
9
- # Alias for domain-specific language
10
- alias_method :email, :message
11
- alias_method :email=, :message=
12
- alias_attribute :email_id, :message_id
13
-
14
- delegate :to_s,
15
- :to => :email_address
16
-
17
- # Returns the receiver of the message. This can be a string if being sent
18
- # to an arbitrary e-mail address.
19
- def receiver_with_spec
20
- receiver_without_spec || receiver_spec
21
- end
22
- alias_method_chain :receiver, :spec
23
-
24
- # If receiver is a string, then sets the spec, otherwise uses the original
25
- # receiver setter
26
- def receiver_with_spec=(value)
27
- self.receiver_spec = EmailAddress.convert_from(value).spec
28
- self.receiver_without_spec = value if !value.is_a?(String)
29
- end
30
- alias_method_chain :receiver=, :spec
31
-
32
- # Converts the receiver into an Email Address, whether it be a string,
33
- # EmailAddress, or other model type
34
- def email_address
35
- EmailAddress.convert_from(receiver_spec)
36
- end
37
-
38
- # The name of the person whose receiving the email
39
- def name
40
- receiver_without_spec ? EmailAddress.convert_from(receiver_without_spec).name : email_address.name
41
- end
42
-
43
- # Returns a string version of the email address plus any name like
44
- # "John Doe <john.doe@gmail.com>"..
45
- def with_name
46
- address = self.email_address
47
- address.name = self.name
48
- address.with_name
49
- end
50
-
51
- private
52
- def validate_on_create #:nodoc:
53
- begin
54
- email_address if receiver
55
- true
56
- rescue ArgumentError
57
- errors.add 'receiver_id', 'must be a string, have a email_address attribute, or be a class that has_email_addresses'
58
- end
59
- end
60
-
61
- # Strings are allowed to participate in messaging
62
- def model_participant?
63
- receiver_id && receiver_type || receiver_spec.nil?
64
- end
65
-
66
- # Ensures that the country id/user region combo is not set at the same time as
67
- # the region id
68
- def ensure_exclusive_references
69
- if model_participant?
70
- self.receiver_spec = nil
71
- else
72
- self.receiver_id = nil
73
- self.receiver_type = nil
74
- end
75
-
76
- true
77
- end
78
- end
@@ -1,7 +0,0 @@
1
- module EmailRecipientBuildExtension #:nodoc:
2
- # Checks if the recipient and record are equal, using the recipient's
3
- # email_address
4
- def is_recipient_equal?(recipient, record) #:nodoc:
5
- recipient.email_address.to_s == EmailAddress.convert_from(record).to_s
6
- end
7
- end
@@ -1,4 +0,0 @@
1
- verify:
2
- id: 601
3
- name: verify
4
- owner_type: EmailAddress
@@ -1,9 +0,0 @@
1
- unverified:
2
- id: 601
3
- name: unverified
4
- owner_type: EmailAddress
5
-
6
- verified:
7
- id: 602
8
- name: verified
9
- owner_type: EmailAddress
@@ -1,18 +0,0 @@
1
- class AddEmailSpecs < ActiveRecord::Migration
2
- def self.up
3
- # Workaround change_column not allowing change to :null => true
4
- remove_column :messages, :sender_id
5
- remove_column :messages, :sender_type
6
-
7
- add_column :messages, :sender_id, :integer, :null => true, :default => nil, :references => nil
8
- add_column :messages, :sender_type, :string, :null => true, :default => nil
9
- add_column :messages, :sender_spec, :string, :limit => 320
10
- end
11
-
12
- def self.down
13
- remove_column :messages, :sender_spec
14
-
15
- change_column :messages, :sender_id, :integer, :null => false, :references => nil
16
- change_column :messages, :sender_type, :string, :null => false
17
- end
18
- end
@@ -1,18 +0,0 @@
1
- class AddEmailRecipientSpecs < ActiveRecord::Migration
2
- def self.up
3
- # Workaround change_column not allowing change to :null => true
4
- remove_column :message_recipients, :receiver_id
5
- remove_column :message_recipients, :receiver_type
6
-
7
- add_column :message_recipients, :receiver_id, :integer, :null => true, :default => nil, :references => nil
8
- add_column :message_recipients, :receiver_type, :string, :null => true, :default => nil
9
- add_column :message_recipients, :receiver_spec, :string, :limit => 320
10
- end
11
-
12
- def self.down
13
- remove_column :message_recipients, :receiver_spec
14
-
15
- change_column :message_recipients, :receiver_id, :integer, :null => false, :references => nil
16
- change_column :message_recipients, :receiver_type, :string, :null => false
17
- end
18
- end
@@ -1,2 +0,0 @@
1
- class Department < ActiveRecord::Base
2
- end
@@ -1,3 +0,0 @@
1
- class User < ActiveRecord::Base
2
- has_email_addresses
3
- end
@@ -1,11 +0,0 @@
1
- class CreateUsers < ActiveRecord::Migration
2
- def self.up
3
- create_table :users do |t|
4
- t.column :login, :string, :null => false
5
- end
6
- end
7
-
8
- def self.down
9
- drop_table :users
10
- end
11
- end
@@ -1,12 +0,0 @@
1
- class CreateDepartments < ActiveRecord::Migration
2
- def self.up
3
- create_table :departments do |t|
4
- t.column :name, :string, :null => false
5
- t.column :email_address, :string, :null => false
6
- end
7
- end
8
-
9
- def self.down
10
- drop_table :departments
11
- end
12
- end
@@ -1,9 +0,0 @@
1
- marketing:
2
- id: 1
3
- name: Marketing
4
- email_address: marketing@companyxyz.com
5
-
6
- testing:
7
- id: 2
8
- name: Testing
9
- email_address: testing@companyxyz.com
@@ -1,32 +0,0 @@
1
- bob:
2
- id: 1
3
- emailable_id: 1
4
- emailable_type: User
5
- spec: bob@bob.com
6
- verification_code: c2e4f499bf610fa95b8ee3a4e8013dbe
7
- code_expiry: <%= Time.now.to_s(:db) %>
8
- created_at: <%= Time.now.to_s(:db) %>
9
- updated_at: <%= Time.now.to_s(:db) %>
10
- state_id: 601
11
-
12
- john:
13
- id: 2
14
- emailable_id: 2
15
- emailable_type: User
16
- spec: john@john.com
17
- verification_code: 1d3955ee0d05ce5bb847f29d56b990cc
18
- code_expiry: <%= Time.now.to_s(:db) %>
19
- created_at: <%= Time.now.to_s(:db) %>
20
- updated_at: <%= Time.now.to_s(:db) %>
21
- state_id: 602
22
-
23
- mary:
24
- id: 3
25
- emailable_id: 3
26
- emailable_type: User
27
- spec: mary@mary.com
28
- verification_code: 8323145e816cb063d405f5e365d14807
29
- code_expiry: <%= Time.now.to_s(:db) %>
30
- created_at: <%= Time.now.to_s(:db) %>
31
- updated_at: <%= Time.now.to_s(:db) %>
32
- state_id: 602
@@ -1,85 +0,0 @@
1
- bob_to_john:
2
- id: 1
3
- message_id: 1
4
- receiver_id: 2
5
- receiver_type: EmailAddress
6
- receiver_spec: john@john.com
7
- kind: to
8
- position: 1
9
- state_id: 511
10
- type: EmailRecipient
11
-
12
- bob_to_mary:
13
- id: 2
14
- message_id: 1
15
- receiver_id: 3
16
- receiver_type: EmailAddress
17
- receiver_spec: mary@mary.com
18
- kind: cc
19
- position: 1
20
- state_id: 510
21
- type: EmailRecipient
22
-
23
- bob_to_random:
24
- id: 3
25
- message_id: 1
26
- receiver_spec: random@random.com
27
- kind: cc
28
- position: 2
29
- state_id: 510
30
- type: EmailRecipient
31
-
32
- bob_to_marketing:
33
- id: 4
34
- message_id: 1
35
- receiver_id: 1
36
- receiver_type: Department
37
- receiver_spec: marketing@companyxyz.com
38
- kind: cc
39
- position: 3
40
- state_id: 510
41
- type: EmailRecipient
42
-
43
- mary_to_john:
44
- id: 5
45
- message_id: 2
46
- receiver_id: 2
47
- receiver_type: EmailAddress
48
- receiver_spec: john@john.com
49
- kind: bcc
50
- position: 1
51
- state_id: 510
52
- type: EmailRecipient
53
-
54
- unsent_bob_to_john:
55
- id: 6
56
- message_id: 3
57
- receiver_id: 2
58
- receiver_type: EmailAddress
59
- receiver_spec: john@john.com
60
- kind: to
61
- position: 1
62
- state_id: 510
63
- type: EmailRecipient
64
-
65
- unsent_bob_to_mary:
66
- id: 7
67
- message_id: 3
68
- receiver_id: 3
69
- receiver_type: EmailAddress
70
- receiver_spec: mary@mary.com
71
- kind: cc
72
- position: 1
73
- state_id: 510
74
- type: EmailRecipient
75
-
76
- queued_bob_to_john:
77
- id: 8
78
- message_id: 4
79
- receiver_id: 2
80
- receiver_type: User
81
- receiver_spec: john@john.com
82
- kind: to
83
- position: 1
84
- state_id: 510
85
- type: EmailRecipient
@@ -1,52 +0,0 @@
1
- sent_from_bob:
2
- id: 1
3
- sender_id: 1
4
- sender_type: EmailAddress
5
- sender_spec: bob@bob.com
6
- subject: "Funny joke"
7
- body: "Why can't dinosaurs talk? ...Because they're dead!"
8
- created_at: <%= Time.now.to_s(:db) %>
9
- state_id: 502
10
- type: Email
11
-
12
- sent_from_mary:
13
- id: 2
14
- sender_id: 3
15
- sender_type: EmailAddress
16
- sender_spec: mary@mary.com
17
- subject: "FW: Funny joke"
18
- body: "> Why can't dinosaurs talk? ...Because they're dead!"
19
- created_at: <%= Time.now.to_s(:db) %>
20
- state_id: 502
21
- type: Email
22
-
23
- unsent_from_bob:
24
- id: 3
25
- sender_id: 1
26
- sender_type: EmailAddress
27
- sender_spec: bob@bob.com
28
- subject: "Another funny joke"
29
- body: "Where do cows go on a date? ...To the moovies!"
30
- created_at: <%= Time.now.to_s(:db) %>
31
- state_id: 500
32
- type: Email
33
-
34
- queued_from_bob:
35
- id: 4
36
- sender_id: 1
37
- sender_type: EmailAddress
38
- sender_spec: bob@bob.com
39
- subject: ""
40
- body: ""
41
- created_at: <%= Time.now.to_s(:db) %>
42
- state_id: 501
43
- type: Email
44
-
45
- unsent_from_stranger:
46
- id: 5
47
- sender_spec: stranger@somewhere.com
48
- subject: "Do you know where I am?"
49
- body: "Just wondering..."
50
- created_at: <%= Time.now.to_s(:db) %>
51
- state_id: 500
52
- type: Email
@@ -1,128 +0,0 @@
1
- # Emails
2
- sent_from_bob_unsent:
3
- id: 1
4
- stateful_id: 1
5
- stateful_type: Email
6
- to_state_id: 500
7
- occurred_at: <%= Time.now.to_s(:db) %>
8
-
9
- sent_from_bob_sent:
10
- id: 2
11
- stateful_id: 1
12
- stateful_type: Email
13
- from_state_id: 500
14
- to_state_id: 502
15
- event_id: 500
16
- occurred_at: <%= Time.now.to_s(:db) %>
17
-
18
- sent_from_mary_unsent:
19
- id: 3
20
- stateful_id: 2
21
- stateful_type: Email
22
- to_state_id: 500
23
- occurred_at: <%= Time.now.to_s(:db) %>
24
-
25
- sent_from_mary_sent:
26
- id: 4
27
- stateful_id: 2
28
- stateful_type: Email
29
- from_state_id: 500
30
- to_state_id: 502
31
- event_id: 500
32
- occurred_at: <%= Time.now.to_s(:db) %>
33
-
34
- unsent_from_bob_unsent:
35
- id: 5
36
- stateful_id: 3
37
- stateful_type: Email
38
- to_state_id: 500
39
- occurred_at: <%= Time.now.to_s(:db) %>
40
-
41
- queued_from_bob_unsent:
42
- id: 6
43
- stateful_id: 4
44
- stateful_type: Email
45
- to_state_id: 500
46
- occurred_at: <%= Time.now.to_s(:db) %>
47
-
48
- queued_from_bob_queued:
49
- id: 7
50
- stateful_id: 4
51
- stateful_type: Email
52
- from_state_id: 500
53
- to_state_id: 501
54
- event_id: 501
55
- occurred_at: <%= Time.now.to_s(:db) %>
56
-
57
- unsent_from_stranger_unsent:
58
- id: 8
59
- stateful_id: 5
60
- stateful_type: Email
61
- to_state_id: 500
62
- occurred_at: <%= Time.now.to_s(:db) %>
63
-
64
- # EmailRecipients
65
- bob_to_john_unread:
66
- id: 9
67
- stateful_id: 1
68
- stateful_type: EmailRecipient
69
- to_state_id: 510
70
- occurred_at: <%= Time.now.to_s(:db) %>
71
-
72
- bob_to_john_read:
73
- id: 10
74
- stateful_id: 1
75
- stateful_type: EmailRecipient
76
- from_state_id: 510
77
- to_state_id: 511
78
- event_id: 510
79
- occurred_at: <%= Time.now.to_s(:db) %>
80
-
81
- bob_to_mary_unread:
82
- id: 11
83
- stateful_id: 2
84
- stateful_type: EmailRecipient
85
- to_state_id: 510
86
- occurred_at: <%= Time.now.to_s(:db) %>
87
-
88
- bob_to_random_unread:
89
- id: 12
90
- stateful_id: 3
91
- stateful_type: EmailRecipient
92
- to_state_id: 510
93
- occurred_at: <%= Time.now.to_s(:db) %>
94
-
95
- bob_to_marketing_unread:
96
- id: 13
97
- stateful_id: 4
98
- stateful_type: EmailRecipient
99
- to_state_id: 510
100
- occurred_at: <%= Time.now.to_s(:db) %>
101
-
102
- mary_to_john_unread:
103
- id: 14
104
- stateful_id: 5
105
- stateful_type: EmailRecipient
106
- to_state_id: 510
107
- occurred_at: <%= Time.now.to_s(:db) %>
108
-
109
- unsent_bob_to_john_unread:
110
- id: 15
111
- stateful_id: 6
112
- stateful_type: EmailRecipient
113
- to_state_id: 510
114
- occurred_at: <%= Time.now.to_s(:db) %>
115
-
116
- unsent_bob_to_mary_unread:
117
- id: 16
118
- stateful_id: 7
119
- stateful_type: EmailRecipient
120
- to_state_id: 510
121
- occurred_at: <%= Time.now.to_s(:db) %>
122
-
123
- queued_bob_to_john_unread:
124
- id: 17
125
- stateful_id: 8
126
- stateful_type: EmailRecipient
127
- to_state_id: 510
128
- occurred_at: <%= Time.now.to_s(:db) %>
@@ -1,11 +0,0 @@
1
- bob:
2
- id: 1
3
- login: bob
4
-
5
- john:
6
- id: 2
7
- login: john
8
-
9
- mary:
10
- id: 3
11
- login: mary
@@ -1,69 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- class ApplicationMailerTest < Test::Unit::TestCase
4
- fixtures :users, :email_addresses, :messages, :message_recipients, :state_changes
5
-
6
- class TestMailer < ApplicationMailer
7
- def signed_up(recipient)
8
- recipients recipient
9
- subject 'Thanks for signing up'
10
- from 'welcome@mywebapp.com'
11
- cc 'nobody@mywebapp.com'
12
- bcc 'root@mywebapp.com'
13
- body 'Congratulations!'
14
- end
15
- end
16
-
17
- def setup
18
- ActionMailer::Base.delivery_method = :test
19
- ActionMailer::Base.perform_deliveries = true
20
- ActionMailer::Base.raise_delivery_errors = true
21
- ActionMailer::Base.deliveries = []
22
-
23
- @original_logger = TestMailer.logger
24
- @recipient = email_addresses(:bob)
25
- end
26
-
27
- def test_should_use_camelized_application_name_for_default_subject_prefix
28
- assert_equal '[AppRoot] ', ApplicationMailer.default_subject_prefix
29
- end
30
-
31
- def test_should_queue_email
32
- assert_nothing_raised { TestMailer.queue_signed_up(@recipient) }
33
- assert_equal 6, Email.count
34
-
35
- email = Email.find(6)
36
- assert_equal '[AppRoot] Thanks for signing up', email.subject
37
- assert_equal 'Congratulations!', email.body
38
- assert_equal [@recipient], email.to.map(&:receiver)
39
- assert_equal 'welcome@mywebapp.com', email.sender
40
- assert_equal ['nobody@mywebapp.com'], email.cc.map(&:receiver)
41
- assert_equal ['root@mywebapp.com'], email.bcc.map(&:receiver)
42
- end
43
-
44
- def test_should_deliver_email
45
- freeze_time do
46
- expected = new_mail
47
- expected.to = 'john@john.com'
48
- expected.cc = 'mary@mary.com'
49
- expected.subject = 'Another funny joke'
50
- expected.body = 'Where do cows go on a date? ...To the moovies!'
51
- expected.from = 'bob@bob.com'
52
- expected.date = Time.now
53
-
54
- assert_nothing_raised { ApplicationMailer.deliver_email(messages(:unsent_from_bob)) }
55
- assert_not_nil ActionMailer::Base.deliveries.first
56
- assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
57
- end
58
- end
59
-
60
- private
61
- def new_mail( charset="utf-8" )
62
- mail = TMail::Mail.new
63
- mail.mime_version = "1.0"
64
- if charset
65
- mail.set_content_type "text", "plain", { "charset" => charset }
66
- end
67
- mail
68
- end
69
- end