workarea-mail_chimp 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +15 -0
  3. data/.gitignore +55 -0
  4. data/.markdownlint.json +10 -0
  5. data/.rails-rubocop.yml +119 -0
  6. data/.rubocop.yml +8 -0
  7. data/.scss-lint.yml +188 -0
  8. data/CHANGELOG.md +244 -0
  9. data/Gemfile +9 -0
  10. data/README.md +115 -0
  11. data/Rakefile +53 -0
  12. data/app/assets/javascripts/workarea/storefront/mail_chimp/mail_chimp_tracking.js +15 -0
  13. data/app/controllers/workarea/storefront/application_controller.decorator +11 -0
  14. data/app/controllers/workarea/storefront/cart_items_controller.decorator +18 -0
  15. data/app/controllers/workarea/storefront/checkout/addresses_controller.decorator +13 -0
  16. data/app/controllers/workarea/storefront/checkout/shipping_controller.decorator +13 -0
  17. data/app/controllers/workarea/storefront/users/accounts_controller.decorator +37 -0
  18. data/app/models/workarea/catalog/product.decorator +7 -0
  19. data/app/models/workarea/mail_chimp/group.rb +39 -0
  20. data/app/models/workarea/mail_chimp/store.rb +26 -0
  21. data/app/models/workarea/order.decorator +9 -0
  22. data/app/models/workarea/user.decorator +31 -0
  23. data/app/services/workarea/mail_chimp/address.rb +28 -0
  24. data/app/services/workarea/mail_chimp/cart.rb +78 -0
  25. data/app/services/workarea/mail_chimp/order.rb +97 -0
  26. data/app/services/workarea/mail_chimp/product.rb +43 -0
  27. data/app/services/workarea/mail_chimp/variant.rb +43 -0
  28. data/app/view_models/workarea/storefront/user_view_model.decorator +16 -0
  29. data/app/views/workarea/storefront/mail_chimp/_ecommerce_javascript.html.haml +2 -0
  30. data/app/views/workarea/storefront/users/accounts/_edit.html.haml +12 -0
  31. data/app/views/workarea/storefront/users/accounts/_email_interests.html.haml +13 -0
  32. data/app/workers/workarea/mail_chimp/ecommerce/save_cart.rb +40 -0
  33. data/app/workers/workarea/mail_chimp/ecommerce/save_order.rb +31 -0
  34. data/app/workers/workarea/mail_chimp/ecommerce/save_product.rb +31 -0
  35. data/app/workers/workarea/mail_chimp/list_subscriber.rb +30 -0
  36. data/app/workers/workarea/mail_chimp/list_unsubscriber.rb +22 -0
  37. data/app/workers/workarea/mail_chimp/subscription_edit.rb +28 -0
  38. data/bin/rails +19 -0
  39. data/config/initializers/appends.rb +21 -0
  40. data/config/initializers/workarea.rb +14 -0
  41. data/config/locales/en.yml +15 -0
  42. data/lib/gibbon/request_decorator.rb +10 -0
  43. data/lib/integrations/workarea/mail_chimp/bogus_api_request.rb +30 -0
  44. data/lib/integrations/workarea/mail_chimp/bogus_gateway.rb +35 -0
  45. data/lib/integrations/workarea/mail_chimp/bogus_request.rb +78 -0
  46. data/lib/integrations/workarea/mail_chimp/gateway.rb +86 -0
  47. data/lib/integrations/workarea/mail_chimp/gateway/list.rb +47 -0
  48. data/lib/integrations/workarea/mail_chimp/gateway/members.rb +61 -0
  49. data/lib/integrations/workarea/mail_chimp/gateway/subscribe_argument_builder.rb +101 -0
  50. data/lib/tasks/mail_chimp.rake +71 -0
  51. data/lib/workarea/mail_chimp.rb +72 -0
  52. data/lib/workarea/mail_chimp/engine.rb +14 -0
  53. data/lib/workarea/mail_chimp/errors.rb +2 -0
  54. data/lib/workarea/mail_chimp/tasks/ecommerce.rb +43 -0
  55. data/lib/workarea/mail_chimp/version.rb +5 -0
  56. data/script/admin_ci +9 -0
  57. data/script/ci +11 -0
  58. data/script/core_ci +9 -0
  59. data/script/plugins_ci +9 -0
  60. data/script/storefront_ci +9 -0
  61. data/test/dummy/Rakefile +6 -0
  62. data/test/dummy/app/assets/config/manifest.js +4 -0
  63. data/test/dummy/app/assets/images/.keep +0 -0
  64. data/test/dummy/app/assets/javascripts/application.js +13 -0
  65. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  66. data/test/dummy/app/controllers/application_controller.rb +3 -0
  67. data/test/dummy/app/controllers/concerns/.keep +0 -0
  68. data/test/dummy/app/helpers/application_helper.rb +2 -0
  69. data/test/dummy/app/jobs/application_job.rb +2 -0
  70. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  71. data/test/dummy/app/models/concerns/.keep +0 -0
  72. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  73. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  74. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  75. data/test/dummy/bin/bundle +3 -0
  76. data/test/dummy/bin/rails +4 -0
  77. data/test/dummy/bin/rake +4 -0
  78. data/test/dummy/bin/setup +34 -0
  79. data/test/dummy/bin/update +29 -0
  80. data/test/dummy/config.ru +5 -0
  81. data/test/dummy/config/application.rb +23 -0
  82. data/test/dummy/config/boot.rb +5 -0
  83. data/test/dummy/config/cable.yml +9 -0
  84. data/test/dummy/config/environment.rb +5 -0
  85. data/test/dummy/config/environments/development.rb +56 -0
  86. data/test/dummy/config/environments/production.rb +86 -0
  87. data/test/dummy/config/environments/test.rb +43 -0
  88. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  89. data/test/dummy/config/initializers/assets.rb +11 -0
  90. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  91. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  92. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  93. data/test/dummy/config/initializers/inflections.rb +16 -0
  94. data/test/dummy/config/initializers/mime_types.rb +4 -0
  95. data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
  96. data/test/dummy/config/initializers/session_store.rb +3 -0
  97. data/test/dummy/config/initializers/workarea.rb +5 -0
  98. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  99. data/test/dummy/config/locales/en.yml +23 -0
  100. data/test/dummy/config/puma.rb +47 -0
  101. data/test/dummy/config/routes.rb +5 -0
  102. data/test/dummy/config/secrets.yml +22 -0
  103. data/test/dummy/config/spring.rb +6 -0
  104. data/test/dummy/db/seeds.rb +2 -0
  105. data/test/dummy/lib/assets/.keep +0 -0
  106. data/test/factories/mail_chimp.rb +50 -0
  107. data/test/integration/workarea/mailchimp/subscription_test.rb +52 -0
  108. data/test/integration/workarea/mailchimp/tracking_params_test.rb +50 -0
  109. data/test/integration/workarea/mailchimp/unsubscribe_test.rb +14 -0
  110. data/test/integration/workarea/storefront/mail_chimp_order_test.rb +106 -0
  111. data/test/integration/workarea/storefront/mail_chimp_product_test.rb +51 -0
  112. data/test/integration/workarea/storefront/mail_chimp_site_javascript_test.rb +25 -0
  113. data/test/lib/workarea/mailchimp/gateway/list_test.rb +48 -0
  114. data/test/lib/workarea/mailchimp/gateway_test.rb +196 -0
  115. data/test/lib/workarea/mailchimp/tasks/ecommerce_test.rb +40 -0
  116. data/test/services/workarea/mail_chimp/cart_test.rb +44 -0
  117. data/test/services/workarea/mail_chimp/order_test.rb +50 -0
  118. data/test/services/workarea/mail_chimp/product_test.rb +29 -0
  119. data/test/support/workarea/mail_chimp_api_config.rb +33 -0
  120. data/test/system/workarea/storefront/campaign_tracking_test.rb +14 -0
  121. data/test/system/workarea/storefront/group_test.rb +33 -0
  122. data/test/system/workarea/storefront/mail_chimp_accounts_system_test.rb +79 -0
  123. data/test/test_helper.rb +17 -0
  124. data/test/vcr_cassettes/get_default_list_interests.yml +104 -0
  125. data/test/vcr_cassettes/get_member_details_no_match.yml +51 -0
  126. data/test/vcr_cassettes/get_member_details_unsubscribed.yml +51 -0
  127. data/test/vcr_cassettes/interest_categories_read.yml +104 -0
  128. data/test/vcr_cassettes/mail_chimp/tasks/create_store-successful.yml +97 -0
  129. data/test/vcr_cassettes/mc_order_test.yml +381 -0
  130. data/test/vcr_cassettes/mc_product_test.yml +234 -0
  131. data/test/vcr_cassettes/subscribe_to_default_list.yml +254 -0
  132. data/test/vcr_cassettes/subscribe_to_default_list_interest_groups.yml +254 -0
  133. data/test/vcr_cassettes/subscribe_to_default_list_with_groupings.yml +254 -0
  134. data/test/vcr_cassettes/subscribe_to_default_list_with_user_details.yml +254 -0
  135. data/test/vcr_cassettes/unsubscribe_from_default_list.yml +53 -0
  136. data/test/vcr_cassettes/update_member_on_default_list_change_email.yml +254 -0
  137. data/test/vcr_cassettes/update_member_on_default_list_change_groupings.yml +254 -0
  138. data/test/workers/workarea/mail_chimp/ecommerce/save_cart_test.rb +28 -0
  139. data/test/workers/workarea/mail_chimp/ecommerce/save_order_test.rb +15 -0
  140. data/test/workers/workarea/mail_chimp/ecommerce/save_product_test.rb +15 -0
  141. data/workarea-mail_chimp.gemspec +20 -0
  142. metadata +212 -0
@@ -0,0 +1,22 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class ListUnsubscriber
4
+ include Sidekiq::Worker
5
+ include Sidekiq::CallbacksWorker
6
+
7
+ sidekiq_options(
8
+ enqueue_on: {
9
+ Email::Signup => [:destroy],
10
+ with: -> { [email] }
11
+ },
12
+ queue: "low",
13
+ retry: true
14
+ )
15
+
16
+ def perform(email)
17
+ User.find_by_email(email)&.update_attributes(email_signup: false)
18
+ Workarea::MailChimp.gateway.unsubscribe(email)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class SubscriptionEdit
4
+ include Sidekiq::Worker
5
+ include Sidekiq::CallbacksWorker
6
+
7
+ sidekiq_options(
8
+ enqueue_on: {
9
+ User => [:save],
10
+ ignore_if: -> { !SubscriptionEdit.should_enqueue?(id) }
11
+ },
12
+ queue: "low",
13
+ retry: true
14
+ )
15
+
16
+ def self.should_enqueue?(id)
17
+ user = User.find(id)
18
+ user.email_signup
19
+ end
20
+
21
+ def perform(id)
22
+ user = User.find(id)
23
+
24
+ Workarea::MailChimp.gateway.subscribe(user.email, user: user)
25
+ end
26
+ end
27
+ end
28
+ end
data/bin/rails ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path("../..", __FILE__)
6
+ ENGINE_PATH = File.expand_path("../../lib/mail_chimp/engine", __FILE__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
10
+ require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
11
+
12
+ require "rails"
13
+ require "action_controller/railtie"
14
+ require "action_view/railtie"
15
+ require "action_mailer/railtie"
16
+ require "rails/test_unit/railtie"
17
+ require "sprockets/railtie"
18
+
19
+ require "rails/engine/commands"
@@ -0,0 +1,21 @@
1
+ module Workarea
2
+ Plugin.append_partials(
3
+ "storefront.edit_account_details",
4
+ "workarea/storefront/users/accounts/edit"
5
+ )
6
+
7
+ Plugin.append_partials(
8
+ "storefront.show_account_details",
9
+ "workarea/storefront/users/accounts/email_interests"
10
+ )
11
+
12
+ Plugin.append_javascripts(
13
+ 'storefront.modules',
14
+ 'workarea/storefront/mail_chimp/mail_chimp_tracking'
15
+ )
16
+
17
+ Plugin.append_partials(
18
+ 'storefront.javascript',
19
+ 'workarea/storefront/mail_chimp/ecommerce_javascript'
20
+ )
21
+ end
@@ -0,0 +1,14 @@
1
+ Workarea.configure do |config|
2
+ config.mail_chimp = ActiveSupport::Configurable::Configuration.new
3
+
4
+ config.mail_chimp.default_list_id = ''
5
+ config.mail_chimp.email_interests_id = ''
6
+
7
+ config.mail_chimp.default_store = {
8
+ id: "" ,
9
+ list_id: "",
10
+ name: "Ecommerce Store",
11
+ email_address: "",
12
+ currency_code: "USD"
13
+ }
14
+ end
@@ -0,0 +1,15 @@
1
+ en:
2
+ workarea:
3
+ storefront:
4
+ users:
5
+ edit:
6
+ subscribe_to_emails: Subscribe to Emails
7
+ email_interests: Email Interests
8
+ email_preferences:
9
+ email_subscriptions: Email Subscriptions
10
+ interests: Interests
11
+ none: None
12
+ subscribed: Subscribed
13
+ unsubscribe: Unsubscribe
14
+ unsubscribed: Unsubscribed
15
+ update_interests: Update Interests
@@ -0,0 +1,10 @@
1
+ module Gibbon
2
+ decorate Request, with: :mail_chimp do
3
+ # hack to add to the path keeping '_' intact
4
+ def add_path_part(part)
5
+ @path_parts << part.to_s.downcase
6
+ @path_parts.flatten!
7
+ self
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class BogusAPIRequest
4
+
5
+ def initialize(builder: nil)
6
+ @request_builder = builder
7
+ end
8
+
9
+ def post(params: nil, headers: nil, body: nil)
10
+ Gibbon::Response.new(headers: {}, body: {})
11
+ end
12
+
13
+ def patch(params: nil, headers: nil, body: nil)
14
+ Gibbon::Response.new(headers: {}, body: {})
15
+ end
16
+
17
+ def put(params: nil, headers: nil, body: nil)
18
+ Gibbon::Response.new(headers: {}, body: {})
19
+ end
20
+
21
+ def get(params: nil, headers: nil)
22
+ Gibbon::Response.new(headers: {}, body: {})
23
+ end
24
+
25
+ def delete(params: nil, headers: nil)
26
+ Gibbon::Response.new(headers: {}, body: {})
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class BogusGateway
4
+ delegate :interests, to: :list
5
+
6
+ class BogusList
7
+ def interests
8
+ [
9
+ Workarea::MailChimp::Group.new(
10
+ _id: 9,
11
+ name: "Email Interests",
12
+ interests: {
13
+ "7ca6cc1d86" => "Specials and Promotions",
14
+ "8911545594" => "Local Events",
15
+ "542a7ec7bb" => "Restaurant News and Events",
16
+ "6908d70674" => "Corporate Gifts and Awards"
17
+ }
18
+ )
19
+ ]
20
+ end
21
+ end
22
+
23
+ @@supported_methods = Workarea::MailChimp::Gateway.public_instance_methods
24
+
25
+ def list
26
+ BogusList.new
27
+ end
28
+
29
+ def method_missing(method, *args)
30
+ return true if @@supported_methods.include? method
31
+ super
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,78 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class BogusRequest
4
+
5
+ def initialize(*)
6
+ @path_parts = []
7
+ end
8
+
9
+ def method_missing(method, *args)
10
+ # To support underscores, we replace them with hyphens when calling the API
11
+ @path_parts << method.to_s.gsub("_", "-").downcase
12
+ @path_parts << args if args.length > 0
13
+ @path_parts.flatten!
14
+
15
+ self
16
+ end
17
+
18
+ def respond_to_missing?(method_name, include_private = false)
19
+ true
20
+ end
21
+
22
+ def send(*args)
23
+ if args.length == 0
24
+ method_missing(:send, args)
25
+ else
26
+ __send__(*args)
27
+ end
28
+ end
29
+
30
+ def path
31
+ @path_parts.join('/')
32
+ end
33
+
34
+ def create(params: nil, headers: nil, body: nil)
35
+ BogusAPIRequest.new(builder: self).post(params: params, headers: headers, body: body)
36
+ reset
37
+ end
38
+
39
+ def update(params: nil, headers: nil, body: nil)
40
+ BogusAPIRequest.new(builder: self).patch(params: params, headers: headers, body: body)
41
+ reset
42
+ end
43
+
44
+ def upsert(params: nil, headers: nil, body: nil)
45
+ BogusAPIRequest.new(builder: self).put(params: params, headers: headers, body: body)
46
+ reset
47
+ end
48
+
49
+ def retrieve(params: nil, headers: nil)
50
+ BogusAPIRequest.new(builder: self).get(params: params, headers: headers)
51
+ reset
52
+ end
53
+
54
+ def delete(params: nil, headers: nil)
55
+ BogusAPIRequest.new(builder: self).delete(params: params, headers: headers)
56
+ reset
57
+ end
58
+
59
+ protected
60
+
61
+ def reset
62
+ @path_parts = []
63
+ end
64
+
65
+ class << self
66
+ attr_accessor :api_key, :timeout, :open_timeout, :api_endpoint, :proxy, :faraday_adapter, :symbolize_keys, :debug, :logger
67
+
68
+ def method_missing(sym, *args, &block)
69
+ new.send(sym, *args, &block)
70
+ end
71
+
72
+ def respond_to_missing?(method_name, include_private = false)
73
+ true
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,86 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class Gateway
4
+ class MailChimpSubscriptionError < StandardError; end
5
+
6
+ attr_reader :default_list_id, :email_interests_id
7
+
8
+ delegate :details, to: :members
9
+ delegate :interests, to: :list
10
+
11
+ def self.acceptable_failure_codes
12
+ [
13
+ 232, # Email_NotExists
14
+ 220, # List_InvalidImport (banned user / invalid email)
15
+ 400, # Member exists and cannot be subscribed
16
+ 404, # User not found
17
+ 500 # Inexplicable intermittent MailChimp-side error
18
+ ]
19
+ end
20
+
21
+ # Use this for new or current subscriptions
22
+ #
23
+ # email: String
24
+ # new_email: String
25
+ # user: User
26
+ #
27
+ def subscribe(email, options = {})
28
+ members.subscribe(
29
+ SubscribeArgumentBuilder.new(
30
+ email,
31
+ options,
32
+ default_list_id,
33
+ email_interests_id
34
+ ).build
35
+ )
36
+ end
37
+
38
+ # Unsubscribe email from default list. This does not delete the record in
39
+ # MailChimp.
40
+ #
41
+ # email: String
42
+ #
43
+ def unsubscribe(email, options = {})
44
+ members.unsubscribe(email)
45
+ end
46
+
47
+ def members
48
+ @members ||= MailChimp::Gateway::Members.new(default_list_id)
49
+ end
50
+
51
+ def list
52
+ @list ||=
53
+ MailChimp::Gateway::List.new(
54
+ default_list_id,
55
+ email_interests_id
56
+ )
57
+ end
58
+
59
+ private
60
+
61
+ def acceptable_failure?(error)
62
+ self.class.acceptable_failure_codes.include?(error.body["status"])
63
+ end
64
+
65
+ def response_error_handler(error)
66
+ if !acceptable_failure?(error)
67
+ raise MailChimpSubscriptionError, error.message
68
+ end
69
+
70
+ error_hash(error)
71
+ end
72
+
73
+ def error_hash(error)
74
+ { "error" => error.message }
75
+ end
76
+
77
+ def default_list_id
78
+ Workarea::MailChimp.config.default_list_id
79
+ end
80
+
81
+ def email_interests_id
82
+ Workarea::MailChimp.config.email_interests_id
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,47 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class Gateway::List < Gateway
4
+ def initialize(list_id, email_interests_id)
5
+ @list_id = list_id
6
+ @email_interests_id = email_interests_id
7
+ end
8
+
9
+ # Get the interest groups for the default list.
10
+ #
11
+ def interests
12
+ begin
13
+ response = MailChimp.request.lists(@list_id).interest_categories.retrieve
14
+
15
+ response.body["categories"].map do |grouping|
16
+ MailChimp::Group.new(
17
+ _id: grouping["id"],
18
+ name: grouping["title"],
19
+ interests: groupings(grouping["id"])
20
+ )
21
+ end
22
+
23
+ rescue StandardError => e
24
+ message = "MAIL CHIMP ERROR: Error - #{e}"
25
+ message += "Response - #{response['error']}" if response.is_a?(Hash)
26
+ []
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def groupings(category_id)
33
+ response = MailChimp.request.lists(@list_id).interest_categories(category_id).interests.retrieve
34
+
35
+ sort_by_display_order(response.body)
36
+ end
37
+
38
+ def sort_by_display_order(grouping)
39
+ grouping["interests"].sort do |a, b|
40
+ a["display_order"].to_i <=> b["display_order"].to_i
41
+ end.each_with_object({}) do |interest, hash|
42
+ hash[interest["id"]] = interest["name"]
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,61 @@
1
+ module Workarea
2
+ module MailChimp
3
+ class Gateway::Members < Gateway
4
+ def initialize( default_list_id)
5
+ @default_list_id = default_list_id
6
+ end
7
+
8
+ # Returns Hash or nil
9
+ #
10
+ def details(email)
11
+ response ||= begin
12
+ MailChimp.request.lists(@default_list_id).members(digest_email(email)).retrieve
13
+ rescue ::Gibbon::MailChimpError => e
14
+ response_error_handler(e)
15
+ end
16
+
17
+ extract_member_details(response)
18
+ end
19
+
20
+ def unsubscribe(email, options = {})
21
+ begin
22
+ MailChimp.request.lists(@default_list_id).members(digest_email(email)).update(body: { status: "unsubscribed" })
23
+ rescue ::Gibbon::MailChimpError => e
24
+ response_error_handler(e)
25
+ end
26
+ end
27
+
28
+ def subscribe(subscribe_argument)
29
+ return unless subscribe_argument[:email_address]
30
+ begin
31
+ MailChimp.request.lists(@default_list_id).members(digest_email(subscribe_argument[:email_address])).upsert(body: subscribe_argument.merge("status" => "subscribed"))
32
+ rescue ::Gibbon::MailChimpError => e
33
+ response_error_handler(e)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ # Returns
40
+ # * Hash of details for subscribed emails
41
+ # * nil if email does not exist
42
+ # * nil if email is unsubscribed
43
+ #
44
+ def extract_member_details(details)
45
+ if details["error"].present?
46
+ nil
47
+ elsif details["status"] == "unsubscribed"
48
+ nil
49
+ else
50
+ details
51
+ end
52
+ end
53
+
54
+ def digest_email(email)
55
+ md5 = Digest::MD5.new
56
+ md5.update(email.downcase)
57
+ md5.hexdigest
58
+ end
59
+ end
60
+ end
61
+ end