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
@@ -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