workarea-mail_chimp 3.0.2

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