mixpanel-mail 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in mixpanel-mail.gemspec
4
4
  gemspec
@@ -10,4 +10,5 @@ gem 'rake'
10
10
  group :development do
11
11
  gem "rspec", "~> 2.6.0"
12
12
  gem "webmock", "~> 1.7.4"
13
+ gem 'actionmailer', '~> 3.1.0'
13
14
  end
@@ -1,16 +1,55 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mixpanel-mail (0.1.0)
4
+ mixpanel-mail (0.1.2)
5
5
  multi_json
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
+ actionmailer (3.1.0)
11
+ actionpack (= 3.1.0)
12
+ mail (~> 2.3.0)
13
+ actionpack (3.1.0)
14
+ activemodel (= 3.1.0)
15
+ activesupport (= 3.1.0)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ i18n (~> 0.6)
19
+ rack (~> 1.3.2)
20
+ rack-cache (~> 1.0.3)
21
+ rack-mount (~> 0.8.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.0.0)
24
+ activemodel (3.1.0)
25
+ activesupport (= 3.1.0)
26
+ bcrypt-ruby (~> 3.0.0)
27
+ builder (~> 3.0.0)
28
+ i18n (~> 0.6)
29
+ activesupport (3.1.0)
30
+ multi_json (~> 1.0)
10
31
  addressable (2.2.6)
32
+ bcrypt-ruby (3.0.1)
33
+ builder (3.0.0)
11
34
  crack (0.3.1)
12
35
  diff-lcs (1.1.3)
36
+ erubis (2.7.0)
37
+ hike (1.2.1)
38
+ i18n (0.6.0)
39
+ mail (2.3.0)
40
+ i18n (>= 0.4.0)
41
+ mime-types (~> 1.16)
42
+ treetop (~> 1.4.8)
43
+ mime-types (1.16)
13
44
  multi_json (1.0.3)
45
+ polyglot (0.3.2)
46
+ rack (1.3.3)
47
+ rack-cache (1.0.3)
48
+ rack (>= 0.4)
49
+ rack-mount (0.8.3)
50
+ rack (>= 1.0.0)
51
+ rack-test (0.6.1)
52
+ rack (>= 1.0)
14
53
  rake (0.9.2)
15
54
  rspec (2.6.0)
16
55
  rspec-core (~> 2.6.0)
@@ -20,6 +59,14 @@ GEM
20
59
  rspec-expectations (2.6.0)
21
60
  diff-lcs (~> 1.1.2)
22
61
  rspec-mocks (2.6.0)
62
+ sprockets (2.0.0)
63
+ hike (~> 1.2)
64
+ rack (~> 1.0)
65
+ tilt (!= 1.3.0, ~> 1.1)
66
+ tilt (1.3.3)
67
+ treetop (1.4.10)
68
+ polyglot
69
+ polyglot (>= 0.3.1)
23
70
  webmock (1.7.6)
24
71
  addressable (> 2.2.5, ~> 2.2)
25
72
  crack (>= 0.1.7)
@@ -28,6 +75,7 @@ PLATFORMS
28
75
  ruby
29
76
 
30
77
  DEPENDENCIES
78
+ actionmailer (~> 3.1.0)
31
79
  mixpanel-mail!
32
80
  rake
33
81
  rspec (~> 2.6.0)
@@ -7,7 +7,8 @@ require 'digest/md5'
7
7
 
8
8
  module ActionMailer
9
9
  class MixpanelInterceptor
10
- cattr_accessor :token
10
+ cattr_accessor :token, :logger
11
+ self.logger = Rails.logger if defined?(Rails)
11
12
 
12
13
  class << self
13
14
  def activate!(token)
@@ -16,35 +17,36 @@ module ActionMailer
16
17
  end
17
18
 
18
19
  def delivering_email(mail)
19
- # Skip Mixpanel if the campaign is not specified
20
- return unless mail.header['mp_campaign']
21
-
22
- # Skip Mixpanel if we don't have HTML
23
- html = mail.html_part ? mail.html_part.body : nil
24
- return unless html.present?
25
-
26
- # Convert header options to mixpanel options
20
+ # Remove all the Mixpanel headers from the email
27
21
  opts = ::Mixpanel::Mail::OPTIONS.inject({}) do |sum, key|
28
- if value = pop_mp_header(mail, key)
29
- sum[key] = value
22
+ if field = pop_mp_header(mail, key)
23
+ sum[key] = field.value
30
24
  end
31
25
  sum
32
26
  end
33
27
 
28
+ # Skip Mixpanel if the campaign is not specified
29
+ return unless opts['campaign']
30
+
31
+ # Skip Mixpanel if we don't have HTML
32
+ html = mail.html_part ? mail.html_part.decoded : nil
33
+ return unless html.present?
34
+
34
35
  # Generate email distinct_id for Mixpanel
35
36
  id = Digest::MD5.hexdigest(mail.header['To'].to_s)
36
37
 
37
38
  begin
38
39
  mail.html_part.body = mp_mail.add_tracking(id, html, opts)
39
40
  rescue => e
40
- Rails.logger.warn("Failed to Mixpanelize Mail: #{e}")
41
41
  mail.html_part.body = html
42
+ logger.warn("Failed to Mixpanelize Mail: #{e}")
43
+ logger.debug(e.backtrace.join("\n"))
42
44
  end
43
45
  end
44
46
 
45
47
  private
46
48
  def mp_mail
47
- @mixpanel_mail ||= Mixpanel::Mail.new(token, 'default')
49
+ @mixpanel_mail ||= Mixpanel::Mail.new(token)
48
50
  end
49
51
 
50
52
  def pop_mp_header(mail, key)
@@ -13,13 +13,14 @@ module Mixpanel
13
13
  ENDPOINT = 'http://api.mixpanel.com/email'
14
14
  ENDPOINT_URI = URI.parse(ENDPOINT)
15
15
  OPTIONS = %w(campaign type properties redirect_host click_tracking)
16
+ DEFAULT_CAMPAIGN = 'default'
16
17
 
17
18
  attr_accessor :params
18
19
 
19
- def initialize(token, campaign, options = {})
20
+ def initialize(token, options = {})
20
21
  @params = {}
21
22
  params['token'] = token
22
- params['campaign'] = campaign
23
+ params['campaign'] = DEFAULT_CAMPAIGN
23
24
  params.merge!(groom_options(options))
24
25
  end
25
26
 
@@ -1,5 +1,5 @@
1
1
  module Mixpanel
2
2
  class Mail
3
- VERSION = "0.1.1"
3
+ VERSION = "0.1.2"
4
4
  end
5
5
  end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+ require 'logger'
3
+ require 'mail'
4
+ require 'action_mailer'
5
+ require 'action_mailer/mixpanel_interceptor'
6
+
7
+ describe ActionMailer::MixpanelInterceptor do
8
+ MI = ActionMailer::MixpanelInterceptor
9
+ TOKEN = 'abcd123'
10
+ TO_ADDY = 'test@gemfury.com'
11
+ HTML_BODY = '<h1>HTML</h1>'
12
+
13
+ before do
14
+ MI.token = TOKEN
15
+ MI.logger = Logger.new($stdout)
16
+ end
17
+
18
+ describe '::delivering_email' do
19
+ before do
20
+ @mail = Mail::Message.new do
21
+ to TO_ADDY
22
+ body 'Hello World!'
23
+ end
24
+ end
25
+
26
+ it 'should ignore mails without any MP options' do
27
+ MI.delivering_email(@mail)
28
+ a_post.should_not have_been_made
29
+ end
30
+
31
+ ### Shared Examples for All Emails ###
32
+ shared_examples_for 'all emails' do
33
+ it 'should remove all Mixpanel headers' do
34
+ MI.delivering_email(@mail)
35
+ default_headers.keys do |key|
36
+ @mail.header[key].should be_nil
37
+ end
38
+ end
39
+ end
40
+
41
+ ### Shared Examples for Emails for non-Mixpanel emails ###
42
+ shared_examples_for 'ignored Mixpanel email' do
43
+ it_should_behave_like 'all emails'
44
+ it 'should not make a Mixpanel request' do
45
+ MI.delivering_email(@mail)
46
+ a_post.should_not have_been_made
47
+ end
48
+ end
49
+
50
+ describe 'with MP headers without mp_campaign' do
51
+ before do
52
+ apply_headers(@mail, default_headers(:campaign => nil))
53
+ @mail.html_part { body(HTML_BODY) }
54
+ end
55
+
56
+ it_should_behave_like 'ignored Mixpanel email'
57
+ end
58
+
59
+ describe 'with Mixpanel headers' do
60
+ before do
61
+ apply_headers(@mail, default_headers)
62
+ end
63
+
64
+ describe 'without HTML email part' do
65
+ it_should_behave_like 'ignored Mixpanel email'
66
+ end
67
+
68
+ describe 'with HTML email part' do
69
+ before do
70
+ @mail.html_part { body(HTML_BODY) }
71
+ stub_post
72
+ end
73
+
74
+ it_should_behave_like 'all emails'
75
+
76
+ it 'should make a request to Mixpanel' do
77
+ params = Mixpanel::Mail.new(TOKEN, default_params).params
78
+ params['distinct_id'] = Digest::MD5.hexdigest(TO_ADDY)
79
+ params['body'] = HTML_BODY
80
+
81
+ verify_mixpanel_requests(params) do
82
+ MI.delivering_email(@mail)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ private
90
+ def apply_headers(mail, headers)
91
+ headers.each { |k, v| mail.header[k] = v }
92
+ end
93
+
94
+ def default_headers(headers = {})
95
+ out = {}
96
+ default_params(headers).each do |key, value|
97
+ out["mp_#{key}".to_sym] = value
98
+ end
99
+ out
100
+ end
101
+
102
+ def default_params(headers = {})
103
+ { :campaign => 'my-test-campaign',
104
+ :properties => { :foo => :bar },
105
+ :redirect_host => 'mp.testhost.com',
106
+ :type => 'text' }.merge(headers)
107
+ end
108
+ end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mixpanel::Mail do
4
- TOKEN, CAMPAIGN = 'abcd123', 'my-email'
4
+ TOKEN, CAMPAIGN = 'abcd123', Mixpanel::Mail::DEFAULT_CAMPAIGN
5
5
 
6
- it 'should intialize token & campaign' do
6
+ it 'should intialize token & default campaign' do
7
7
  lambda {
8
8
  mail = mp_mail
9
9
  mail.params['token'].should eq(TOKEN)
@@ -88,7 +88,7 @@ describe Mixpanel::Mail do
88
88
 
89
89
  private
90
90
  def mp_mail(options = {})
91
- ::Mixpanel::Mail.new(TOKEN, CAMPAIGN, options)
91
+ ::Mixpanel::Mail.new(TOKEN, options)
92
92
  end
93
93
 
94
94
  def mp_option_check(key, value_expectations = {})
@@ -99,14 +99,15 @@ private
99
99
  end
100
100
 
101
101
  def verify_request_with_options(options = {}, expectations = {})
102
- stub_post
103
- mp_mail(options).add_tracking('my-dist-id', 'Hello World!')
104
- mp_mail.add_tracking('my-dist-id', 'Hello World!', options)
105
- a_post.with(:body => expectations.merge(
106
- 'token' => TOKEN,
107
- 'campaign' => CAMPAIGN,
108
- 'distinct_id' => 'my-dist-id',
109
- 'body' => 'Hello World!'
110
- )).should have_been_made.twice
102
+ expectations = expectations.merge(
103
+ 'token' => TOKEN,
104
+ 'campaign' => CAMPAIGN,
105
+ 'distinct_id' => 'my-dist-id',
106
+ 'body' => 'Hello World!')
107
+
108
+ verify_mixpanel_requests(expectations, 2) do
109
+ mp_mail(options).add_tracking('my-dist-id', 'Hello World!')
110
+ mp_mail.add_tracking('my-dist-id', 'Hello World!', options)
111
+ end
111
112
  end
112
113
  end
@@ -7,4 +7,11 @@
7
7
  self.class.send(:define_method, "stub_#{method}") do
8
8
  stub_request(method, Mixpanel::Mail::ENDPOINT)
9
9
  end
10
+ end
11
+
12
+ # Allow to set expectations for a mixpanel request
13
+ def verify_mixpanel_requests(body = {}, num = 1, &block)
14
+ stub_post
15
+ block && block.call
16
+ a_post.with(:body => body).should have_been_made.times(num)
10
17
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixpanel-mail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-27 00:00:00.000000000Z
12
+ date: 2011-09-28 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
16
- requirement: &70109454407540 !ruby/object:Gem::Requirement
16
+ requirement: &70185098031860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70109454407540
24
+ version_requirements: *70185098031860
25
25
  description: Helpers for Mixpanel Tracking in Emails
26
26
  email:
27
27
  - mrykov@gmail.com
@@ -40,6 +40,7 @@ files:
40
40
  - lib/mixpanel_mail/vendor/active_support/core_ext/hash/slice.rb
41
41
  - lib/mixpanel_mail/version.rb
42
42
  - mixpanel-mail.gemspec
43
+ - spec/action_mailer/mixpanel_interceptor_spec.rb
43
44
  - spec/mixpanel/mail_spec.rb
44
45
  - spec/spec_helper.rb
45
46
  - spec/support/webmock.rb
@@ -68,6 +69,7 @@ signing_key:
68
69
  specification_version: 3
69
70
  summary: Helpers for Mixpanel Tracking in Emails
70
71
  test_files:
72
+ - spec/action_mailer/mixpanel_interceptor_spec.rb
71
73
  - spec/mixpanel/mail_spec.rb
72
74
  - spec/spec_helper.rb
73
75
  - spec/support/webmock.rb