From 41b847e081ff1608fcf683852383b902af8d5e6c Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Mon, 2 May 2016 20:32:33 +0530
Subject: [PATCH 1/9] AS#118090147171048, Mail chimp Integration

-- Added mail chimp angular service
-- Added user to member list on page load
---
 app/services/api.service.js                 |  2 +
 app/services/mailchimp.service.js           | 70 +++++++++++++++++++++
 app/skill-picker/skill-picker.controller.js | 19 +++++-
 app/topcoder.constants.js                   |  7 +++
 4 files changed, 96 insertions(+), 2 deletions(-)
 create mode 100644 app/services/mailchimp.service.js

diff --git a/app/services/api.service.js b/app/services/api.service.js
index 8881f4d4d..0c16d843e 100644
--- a/app/services/api.service.js
+++ b/app/services/api.service.js
@@ -74,6 +74,8 @@ import _ from 'lodash'
       case 'SUBMISSIONS':
       case 'USER':
         return _getRestangularV3(CONSTANTS.AUTH_API_URL)
+      case 'MAILCHIMP':
+        return _getRestangularV3(CONSTANTS.INTERNAL_API_URL)
       default:
         return _getRestangularV3()
       }
diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js
new file mode 100644
index 000000000..f9cc80ab1
--- /dev/null
+++ b/app/services/mailchimp.service.js
@@ -0,0 +1,70 @@
+import angular from 'angular'
+import _ from 'lodash'
+
+(function() {
+  'use strict'
+
+  angular.module('tc.services').factory('MailchimpService', MailchimpService)
+
+  MailchimpService.$inject = ['$http', 'logger', 'Restangular', 'CONSTANTS', 'ApiService', '$q']
+
+  function MailchimpService($http, logger, Restangular, CONSTANTS, ApiService, $q) {
+    var mailchimpApi = ApiService.getApiServiceProvider('MAILCHIMP')
+    var service = {
+      getMemberSubscription: getMemberSubscription,
+      addSubscription: addSubscription
+    }
+    return service
+
+    function getMemberSubscription(user) {
+      return $q(function(resolve, reject) {
+        mailchimpApi.one('mailchimp/lists', CONSTANTS.MAILCHIMP_LIST_ID)
+        .one('members', user.userId).get()
+        .then(function(resp) {
+          resolve(resp)
+        })
+        .catch(function(err) {
+          logger.error('Error adding member to subscription list', err)
+
+          var errorStatus = 'FATAL_ERROR'
+          reject({
+            status: errorStatus,
+            msg: err.data.result.content
+          })
+        })
+      })
+    }
+
+
+    function addSubscription(user) {
+      var subscription = {
+        userId: user.userId,
+        firstName: user.firstName,
+        lastName: user.lastName,
+        interests: {}
+      }
+      subscription.interests[CONSTANTS.MAILCHIMP_NL_TCO] = true
+      subscription.interests[CONSTANTS.MAILCHIMP_NL_IOS] = true
+      subscription.interests[CONSTANTS.MAILCHIMP_NL_DEV] = true
+      subscription.interests[CONSTANTS.MAILCHIMP_NL_DESIGN] = true
+      subscription.interests[CONSTANTS.MAILCHIMP_NL_DATA] = true
+      return $q(function(resolve, reject) {
+        mailchimpApi.one('mailchimp/lists', CONSTANTS.MAILCHIMP_LIST_ID)
+        .customPUT(subscription, 'members')
+        .then(function(resp) {
+          resolve(resp)
+        })
+        .catch(function(err) {
+          logger.error('Error adding member to subscription list', err)
+
+          var errorStatus = 'FATAL_ERROR'
+
+          reject({
+            status: errorStatus,
+            msg: err.data.result.content
+          })
+        })
+      })
+    }
+  }
+})()
diff --git a/app/skill-picker/skill-picker.controller.js b/app/skill-picker/skill-picker.controller.js
index 75b0668d0..39aa6a5c4 100644
--- a/app/skill-picker/skill-picker.controller.js
+++ b/app/skill-picker/skill-picker.controller.js
@@ -6,9 +6,9 @@ import _ from 'lodash'
 
   angular.module('tc.skill-picker').controller('SkillPickerController', SkillPickerController)
 
-  SkillPickerController.$inject = ['$scope', 'CONSTANTS', 'ProfileService', '$state', 'userProfile', 'featuredSkills', 'logger', 'toaster', 'MemberCertService', '$q']
+  SkillPickerController.$inject = ['$scope', 'CONSTANTS', 'ProfileService', '$state', 'userProfile', 'featuredSkills', 'logger', 'toaster', 'MemberCertService', '$q', 'MailchimpService']
 
-  function SkillPickerController($scope, CONSTANTS, ProfileService, $state, userProfile, featuredSkills, logger, toaster, MemberCertService, $q) {
+  function SkillPickerController($scope, CONSTANTS, ProfileService, $state, userProfile, featuredSkills, logger, toaster, MemberCertService, $q, MailchimpService) {
     var vm = this
     vm.ASSET_PREFIX = CONSTANTS.ASSET_PREFIX
     vm.IOS_PROGRAM_ID = CONSTANTS.SWIFT_PROGRAM_ID
@@ -32,6 +32,7 @@ import _ from 'lodash'
      * Activates the controller.
      */
     function activate() {
+      addToMailingList()
       initCommunities()
       checkCommunityStatus()
     }
@@ -137,6 +138,20 @@ import _ from 'lodash'
       }
     }
 
+    function addToMailingList() {
+      return MailchimpService.getMemberSubscription(userProfile).then(function(subscription) {
+        console.log(subscription)
+        if (!subscription) {
+          return MailchimpService.addSubscription(userProfile).then(function(resp) {
+            console.log(resp)
+          })
+        }
+      }).catch(function(err) {
+        //TODO some error alert to community admin
+        console.log('error in adding user to member list')
+      })
+    }
+
     /**
      * Persists the user's altered information.
      */
diff --git a/app/topcoder.constants.js b/app/topcoder.constants.js
index cab991847..98dacbb52 100644
--- a/app/topcoder.constants.js
+++ b/app/topcoder.constants.js
@@ -4,6 +4,7 @@ angular.module('CONSTANTS', []).constant('CONSTANTS', {
   'API_URL'                 : process.env.API_URL,
   'AUTH_API_URL'            : process.env.AUTH_API_URL,
   'API_URL_V2'              : process.env.API_URL_V2,
+  'INTERNAL_API_URL'        : process.env.INTERNAL_API_URL,
   'ASSET_PREFIX'            : process.env.ASSET_PREFIX || '',
   'auth0Callback'           : process.env.auth0Callback,
   'auth0Domain'             : process.env.auth0Domain,
@@ -19,6 +20,12 @@ angular.module('CONSTANTS', []).constant('CONSTANTS', {
   'PHOTO_LINK_LOCATION'     : process.env.PHOTO_LINK_LOCATION,
   'SWIFT_PROGRAM_URL'       : process.env.SWIFT_PROGRAM_URL,
   'TCO16_URL'               : process.env.TCO16_URL,
+  'MAILCHIMP_LIST_ID'       : process.env.MAILCHIMP_LIST_ID,
+  'MAILCHIMP_NL_TCO'        : process.env.MAILCHIMP_NL_TCO,
+  'MAILCHIMP_NL_IOS'        : process.env.MAILCHIMP_NL_IOS,
+  'MAILCHIMP_NL_DEV'        : process.env.MAILCHIMP_NL_DEV,
+  'MAILCHIMP_NL_DESIGN'     : process.env.MAILCHIMP_NL_DESIGN,
+  'MAILCHIMP_NL_DATA'       : process.env.MAILCHIMP_NL_DATA,
 
   'NEW_CHALLENGES_URL'     : 'https://www.topcoder.com/challenges/develop/upcoming/',
   'SWIFT_PROGRAM_ID'       : 3445,

From a2ce169687e7db83b73b0cee24c907d9bfd05e2a Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Tue, 3 May 2016 11:36:08 +0530
Subject: [PATCH 2/9] AS#118090147171048, Mail chimp Integration

-- Fixed lint errors
-- Updated webpack-config version
---
 app/services/mailchimp.service.js           | 1 -
 app/skill-picker/skill-picker.controller.js | 6 +++---
 package.json                                | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js
index f9cc80ab1..3eec695d4 100644
--- a/app/services/mailchimp.service.js
+++ b/app/services/mailchimp.service.js
@@ -1,5 +1,4 @@
 import angular from 'angular'
-import _ from 'lodash'
 
 (function() {
   'use strict'
diff --git a/app/skill-picker/skill-picker.controller.js b/app/skill-picker/skill-picker.controller.js
index 39aa6a5c4..ec0c104fa 100644
--- a/app/skill-picker/skill-picker.controller.js
+++ b/app/skill-picker/skill-picker.controller.js
@@ -140,15 +140,15 @@ import _ from 'lodash'
 
     function addToMailingList() {
       return MailchimpService.getMemberSubscription(userProfile).then(function(subscription) {
-        console.log(subscription)
+        logger.debug(subscription)
         if (!subscription) {
           return MailchimpService.addSubscription(userProfile).then(function(resp) {
-            console.log(resp)
+            logger.debug(resp)
           })
         }
       }).catch(function(err) {
         //TODO some error alert to community admin
-        console.log('error in adding user to member list')
+        logger.debug('error in adding user to member list')
       })
     }
 
diff --git a/package.json b/package.json
index 97f576d82..8f93e9e96 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
   },
   "devDependencies": {
     "angular-mocks": "^1.4.9",
-    "appirio-tech-webpack-config": "^0.2.0",
+    "appirio-tech-webpack-config": "^0.3.0",
     "babel-polyfill": "^6.7.2",
     "bardjs": "^0.1.8",
     "bower": "^1.6.8",

From 85b1be33a6084a1c94ab9f16cab84e54ecef8dad Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Tue, 3 May 2016 11:37:51 +0530
Subject: [PATCH 3/9] AS#118090147171048, Mail chimp Integration

-- Temporary travis build
---
 .travis.yml | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 7f699e053..667e45a5d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,16 @@ script:
 - npm run lint && npm test && npm run build
 sudo: false
 deploy:
+- provider: s3
+  cache_control: private, no-store, no-cache, must-revalidate, max-age=0
+  detect_encoding: true
+  access_key_id: $AWS_KEY
+  secret_access_key: $AWS_SECRET
+  bucket: app.topcoder-dev.com
+  skip_cleanup: true
+  local_dir: dist
+  on:
+    branch: feature/mailchimp
 - provider: s3
   cache_control: private, no-store, no-cache, must-revalidate, max-age=0
   detect_encoding: true

From 506b88899367a0edd4218281a9975ea77dfc91e0 Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Tue, 3 May 2016 12:32:51 +0530
Subject: [PATCH 4/9] AS#118090147171048, Mail chimp Integration

-- Fixed unit tests
---
 app/skill-picker/skill-picker.spec.js | 60 ++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 2 deletions(-)

diff --git a/app/skill-picker/skill-picker.spec.js b/app/skill-picker/skill-picker.spec.js
index 7a2100fc7..70dd236c1 100644
--- a/app/skill-picker/skill-picker.spec.js
+++ b/app/skill-picker/skill-picker.spec.js
@@ -3,12 +3,12 @@ const mockData = require('../../tests/test-helpers/mock-data')
 
 describe('Skill Picker Controller', function() {
   var vm
-  var toasterSvc, memberCertService, profileService, state
+  var toasterSvc, memberCertService, profileService, mailchimpService, state
   var mockProfile = mockData.getMockProfile()
 
   beforeEach(function() {
     bard.appModule('tc.skill-picker')
-    bard.inject(this, '$controller', '$rootScope', '$q', 'MemberCertService', 'ProfileService', 'toaster', 'CONSTANTS')
+    bard.inject(this, '$controller', '$rootScope', '$q', 'MemberCertService', 'ProfileService', 'MailchimpService', 'toaster', 'CONSTANTS')
 
     memberCertService = MemberCertService
     profileService = ProfileService
@@ -52,6 +52,29 @@ describe('Skill Picker Controller', function() {
       return deferred.promise
     })
 
+    mailchimpService = MailchimpService
+    sinon.stub(mailchimpService, 'getMemberSubscription', function(user) {
+      var deferred = $q.defer()
+      if (user.userId === 10336829) {
+        deferred.resolve()
+      } else if (user.userId === 12345) {
+        var resp = { id: 'sdku34i5kdk', email_address: user.email}
+        deferred.resolve(resp)
+      } else {
+        deferred.reject()
+      }
+      return deferred.promise
+    })
+    sinon.stub(mailchimpService, 'addSubscription', function(user) {
+      var deferred = $q.defer()
+      if (user.userId === 10336829) {
+        deferred.resolve()
+      } else {
+        deferred.reject()
+      }
+      return deferred.promise
+    })
+
     // mocks the toaster service
     toasterSvc = toaster
     bard.mockService(toaster, {
@@ -115,6 +138,39 @@ describe('Skill Picker Controller', function() {
     CONSTANTS.SWIFT_PROGRAM_ID = origSwiftProgId
   })
 
+  it('should call mailchimp service to add subscription', function() {
+    expect(vm).to.exist
+    // getMemberSubscription should always be called
+    expect(mailchimpService.getMemberSubscription).to.be.calledOnce
+    // addSubscription should be called once if not subscribed
+    // getMemberSubscription service mock returns null for mockProfile.userId
+    expect(mailchimpService.addSubscription).to.be.calledOnce
+  })
+
+  it('should not call mailchimp service to add subscription', function() {
+    // reset getMemberSubscription, addSubscription spy's called count
+    mailchimpService.getMemberSubscription.reset()
+    mailchimpService.addSubscription.reset()
+    var scope = $rootScope.$new()
+
+    var profile = angular.copy(mockProfile)
+    // update userId to return valid object in service mock
+    profile.userId = 12345
+    vm = $controller('SkillPickerController', {
+      $scope: scope,
+      userProfile: profile,
+      featuredSkills: [],
+      $state: state
+    })
+    $rootScope.$digest()
+    expect(vm).to.exist
+    // getMemberSubscription should always be called
+    expect(mailchimpService.getMemberSubscription).to.be.calledOnce
+    // addSubscription should not be called if already subscribed
+    // getMemberSubscription service mock returns valid object for userId 12345
+    expect(mailchimpService.addSubscription).not.to.be.called
+  })
+
   it('should add skill ', function() {
     vm.toggleSkill(409)
     expect(vm.mySkills).to.exist.have.length(1)

From 37714596196ee30d87d3bfa753e518fde8ab2c47 Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Tue, 3 May 2016 15:07:06 +0530
Subject: [PATCH 5/9] AS#118090147171048, Mail chimp Integration

-- Misc fixes to get it working
---
 app/services/api.service.js                 |  4 ++++
 app/services/mailchimp.service.js           | 11 ++++++++---
 app/skill-picker/skill-picker.controller.js |  5 +++++
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/app/services/api.service.js b/app/services/api.service.js
index 0c16d843e..9f7735975 100644
--- a/app/services/api.service.js
+++ b/app/services/api.service.js
@@ -95,6 +95,10 @@ import _ from 'lodash'
           })
           .setDefaultHeaders({ 'Content-Type': 'application/json' })
           .addRequestInterceptor(function(element, operation, what, url) {
+            // for mailchimp api, don't add param field in the body
+            if (url.indexOf('mailchimp') > -1) {
+              return element
+            }
             if (url.indexOf('members') > -1 || (operation.toLowerCase() === 'post' && url.indexOf('profiles') > -1)) {
               return {
                 param: element
diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js
index 3eec695d4..da355780c 100644
--- a/app/services/mailchimp.service.js
+++ b/app/services/mailchimp.service.js
@@ -23,12 +23,17 @@ import angular from 'angular'
           resolve(resp)
         })
         .catch(function(err) {
-          logger.error('Error adding member to subscription list', err)
+          if (err.status === 404) {
+            logger.debug('Member subscription not found')
+            resolve()
+            return
+          }
+          logger.error('Error getting member to subscription list', err)
 
           var errorStatus = 'FATAL_ERROR'
           reject({
             status: errorStatus,
-            msg: err.data.result.content
+            msg: err.errorMessage
           })
         })
       })
@@ -60,7 +65,7 @@ import angular from 'angular'
 
           reject({
             status: errorStatus,
-            msg: err.data.result.content
+            msg: err.errorMessage
           })
         })
       })
diff --git a/app/skill-picker/skill-picker.controller.js b/app/skill-picker/skill-picker.controller.js
index ec0c104fa..a564c876c 100644
--- a/app/skill-picker/skill-picker.controller.js
+++ b/app/skill-picker/skill-picker.controller.js
@@ -144,9 +144,14 @@ import _ from 'lodash'
         if (!subscription) {
           return MailchimpService.addSubscription(userProfile).then(function(resp) {
             logger.debug(resp)
+          }).catch(function(err) {
+            // no error to user
+            //TODO some error alert to community admin
+            logger.debug('error in adding user to member list')    
           })
         }
       }).catch(function(err) {
+        // no error to user
         //TODO some error alert to community admin
         logger.debug('error in adding user to member list')
       })

From 4b145c7cff6f2a2c20ff4839a04638066391f2d6 Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Wed, 4 May 2016 11:53:41 +0530
Subject: [PATCH 6/9] AS#118090147171050, Email settings tab UI

-- Added settings tab with required functionality
---
 app/index.js                           |   1 +
 app/services/mailchimp.service.js      |  16 ++--
 app/settings/email/email.controller.js | 105 +++++++++++++++++++++++++
 app/settings/email/email.jade          |  30 +++++++
 app/settings/settings.jade             |   3 +
 app/settings/settings.routes.js        |  17 ++++
 app/topcoder.constants.js              |   1 +
 assets/css/settings/email.scss         |  92 ++++++++++++++++++++++
 8 files changed, 259 insertions(+), 6 deletions(-)
 create mode 100644 app/settings/email/email.controller.js
 create mode 100644 app/settings/email/email.jade
 create mode 100644 assets/css/settings/email.scss

diff --git a/app/index.js b/app/index.js
index 88d8a918b..30f039869 100644
--- a/app/index.js
+++ b/app/index.js
@@ -63,6 +63,7 @@ require('../assets/css/sitemap/sitemap.scss')
 require('../assets/css/settings/update-password.scss')
 require('../assets/css/settings/settings.scss')
 require('../assets/css/settings/preferences.scss')
+require('../assets/css/settings/email.scss')
 require('../assets/css/settings/edit-profile.scss')
 require('../assets/css/settings/account-info.scss')
 require('../assets/css/profile/subtrack.scss')
diff --git a/app/services/mailchimp.service.js b/app/services/mailchimp.service.js
index da355780c..5b5cbfdbd 100644
--- a/app/services/mailchimp.service.js
+++ b/app/services/mailchimp.service.js
@@ -40,18 +40,22 @@ import angular from 'angular'
     }
 
 
-    function addSubscription(user) {
+    function addSubscription(user, preferences) {
       var subscription = {
         userId: user.userId,
         firstName: user.firstName,
         lastName: user.lastName,
         interests: {}
       }
-      subscription.interests[CONSTANTS.MAILCHIMP_NL_TCO] = true
-      subscription.interests[CONSTANTS.MAILCHIMP_NL_IOS] = true
-      subscription.interests[CONSTANTS.MAILCHIMP_NL_DEV] = true
-      subscription.interests[CONSTANTS.MAILCHIMP_NL_DESIGN] = true
-      subscription.interests[CONSTANTS.MAILCHIMP_NL_DATA] = true
+      if (!preferences) {
+        subscription.interests[CONSTANTS.MAILCHIMP_NL_TCO] = true
+        subscription.interests[CONSTANTS.MAILCHIMP_NL_IOS] = true
+        subscription.interests[CONSTANTS.MAILCHIMP_NL_DEV] = true
+        subscription.interests[CONSTANTS.MAILCHIMP_NL_DESIGN] = true
+        subscription.interests[CONSTANTS.MAILCHIMP_NL_DATA] = true
+      } else {
+        subscription.interests = preferences
+      }
       return $q(function(resolve, reject) {
         mailchimpApi.one('mailchimp/lists', CONSTANTS.MAILCHIMP_LIST_ID)
         .customPUT(subscription, 'members')
diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js
new file mode 100644
index 000000000..0e61e861f
--- /dev/null
+++ b/app/settings/email/email.controller.js
@@ -0,0 +1,105 @@
+import angular from 'angular'
+import _ from 'lodash'
+
+(function () {
+  'use strict'
+
+  angular.module('tc.settings').controller('EmailSettingsController', EmailSettingsController)
+
+  EmailSettingsController.$inject = ['$rootScope', 'userProfile', 'ProfileService', 'MailchimpService', 'logger', 'CONSTANTS', 'toaster', '$q', '$scope']
+
+  function EmailSettingsController($rootScope, userProfile, ProfileService, MailchimpService, logger, CONSTANTS, toaster, $q, $scope) {
+    var vm = this
+    vm.loading = false
+    vm.saving = false
+    vm.isDirty = isDirty
+    vm.save = save
+
+    activate()
+
+    function activate() {
+      vm.newsletters = [
+        {
+          id: CONSTANTS.MAILCHIMP_NL_DEV,
+          name: 'Developer Newsletter',
+          desc: 'Software architecture, component assembly, application development and bug hunting',
+          enabled: false,
+          dirty: false
+        },
+        {
+          id: CONSTANTS.MAILCHIMP_NL_DESIGN,
+          name: 'Design Newsletter',
+          desc: 'Website, mobile, and product design; UI and UX',
+          enabled: false,
+          dirty: false
+        },
+        {
+          id: CONSTANTS.MAILCHIMP_NL_DATA,
+          name: 'Data Science Newsletter',
+          desc: 'Algorithm and data structures, statistical analysis',
+          enabled: false,
+          dirty: false
+        },
+        {
+          id: CONSTANTS.MAILCHIMP_NL_TCO,
+          name: 'TCO Newsletter',
+          desc: 'Software architecture, component assembly, application development and bug hunting',
+          enabled: false,
+          dirty: false
+        },
+        {
+          id: CONSTANTS.MAILCHIMP_NL_IOS,
+          name: 'iOS Community Newsletter',
+          desc: 'Software architecture, component assembly, application development and bug hunting',
+          enabled: false,
+          dirty: false
+        }
+      ]
+
+      vm.loading = true
+      MailchimpService.getMemberSubscription(userProfile).then(function(resp) {
+        vm.loading = false
+        if (resp.interests) {
+          vm.newsletters.forEach(function(newsletter) {
+            if (resp.interests[newsletter.id]) {
+              newsletter.enabled = true
+            }
+          })
+        }
+      })
+    }
+
+    function isDirty() {
+      var dirty = false
+      vm.newsletters.forEach(function(newsletter) {
+        if (newsletter.dirty){
+          dirty = true
+        }
+      })
+      return dirty
+    }
+
+    function save() {
+      vm.saving = true
+      var preferences = {}
+      vm.newsletters.forEach(function(newsletter) {
+        preferences[newsletter.id] = newsletter.enabled
+      })
+      MailchimpService.addSubscription(userProfile, preferences).then(function(resp) {
+        vm.loading = false
+        vm.saving = false
+        // reset dirty state for all newsletter options
+        vm.newsletters.forEach(function(newsletter) {
+          newsletter.dirty = false
+        })
+        toaster.pop('success', 'Success!', 'Preferences updated.')
+      }).catch(function(err) {
+        logger.error('Could not update email preferences', err)
+        vm.loading = false
+        vm.saving = false
+
+        toaster.pop('error', 'Whoops!', 'Something went wrong. Please try again later.')
+      })
+    }
+  }
+})()
diff --git a/app/settings/email/email.jade b/app/settings/email/email.jade
new file mode 100644
index 000000000..37977606f
--- /dev/null
+++ b/app/settings/email/email.jade
@@ -0,0 +1,30 @@
+.email-preferences-container
+  .settings-section.newsletters
+    .section-info
+      h2 Always be up to date
+      .description Select the email notifications that you'd like to receive. We send them once every week, so you can be up to date with latest news, events and callenges.
+
+    .section-fields
+      .processing(ng-show="vm.loading")
+        i.fa.fa-spinner.fa-spin
+      .newsletters(ng-hide="vm.loading")
+        .newsletter(ng-repeat="newsletter in vm.newsletters")
+
+          .content(ng-class="{ disabled: !newsletter.enabled }")
+            .newsletter-details
+              .text
+                span.title {{newsletter.name}}
+                .description
+                  span(ng-bind="newsletter.desc")
+
+            .onoffswitch
+              input.onoffswitch-checkbox(type='checkbox', name='onoffswitch', checked='', ng-model="newsletter.enabled", id="{{newsletter.name}}-onoffswitch", ng-change="newsletter.dirty = !newsletter.dirty")
+              label.onoffswitch-label(for='{{newsletter.name}}-onoffswitch')
+                span.onoffswitch-inner
+                span.onoffswitch-switch
+  .save-section
+    button.tc-btn.tc-btn-l.done-button(
+      type="button",
+      tc-busy-button, tc-busy-when="vm.saving",
+      ng-click="vm.save()",
+      ng-disabled="!vm.isDirty()") Save
diff --git a/app/settings/settings.jade b/app/settings/settings.jade
index 8c3cd2d0a..8923a13f5 100644
--- a/app/settings/settings.jade
+++ b/app/settings/settings.jade
@@ -10,6 +10,9 @@
       li
         a(ui-sref="settings.account", ui-sref-active="active-tab") Account
 
+      li
+        a(ui-sref="settings.email", ui-sref-active="active-tab") Email
+
       li
         a(ui-sref="settings.preferences", ui-sref-active="active-tab") Preferences
 
diff --git a/app/settings/settings.routes.js b/app/settings/settings.routes.js
index 0dce4be57..031faed38 100644
--- a/app/settings/settings.routes.js
+++ b/app/settings/settings.routes.js
@@ -47,6 +47,23 @@ import angular from 'angular'
           title: 'Account Info'
         }
       },
+      'settings.email': {
+        url: 'email/',
+        template: require('./email/email')(),
+        controller: 'EmailSettingsController',
+        controllerAs: 'vm',
+        data: {
+          title: 'Email Preferences'
+        },
+        resolve: {
+          userIdentity: ['UserService', function(UserService) {
+            return UserService.getUserIdentity()
+          }],
+          userProfile: ['userIdentity', 'ProfileService', function(userIdentity, ProfileService) {
+            return ProfileService.getUserProfile(userIdentity.handle.toLowerCase())
+          }]
+        }
+      },
       'settings.preferences': {
         url: 'preferences/',
         template: require('./preferences/preferences')(),
diff --git a/app/topcoder.constants.js b/app/topcoder.constants.js
index 98dacbb52..bf5f73ea4 100644
--- a/app/topcoder.constants.js
+++ b/app/topcoder.constants.js
@@ -21,6 +21,7 @@ angular.module('CONSTANTS', []).constant('CONSTANTS', {
   'SWIFT_PROGRAM_URL'       : process.env.SWIFT_PROGRAM_URL,
   'TCO16_URL'               : process.env.TCO16_URL,
   'MAILCHIMP_LIST_ID'       : process.env.MAILCHIMP_LIST_ID,
+  'MAILCHIMP_NL_CATEGORY_ID': process.env.MAILCHIMP_NL_CATEGORY_ID,
   'MAILCHIMP_NL_TCO'        : process.env.MAILCHIMP_NL_TCO,
   'MAILCHIMP_NL_IOS'        : process.env.MAILCHIMP_NL_IOS,
   'MAILCHIMP_NL_DEV'        : process.env.MAILCHIMP_NL_DEV,
diff --git a/assets/css/settings/email.scss b/assets/css/settings/email.scss
new file mode 100644
index 000000000..2dab3612b
--- /dev/null
+++ b/assets/css/settings/email.scss
@@ -0,0 +1,92 @@
+@import 'topcoder/tc-includes';
+
+.email-preferences-container {
+  width: 100%;
+  padding: 0 60px 30px;
+
+  .processing {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .newsletters {
+    .newsletter {
+      width: 100%;
+      display: flex;
+      flex-direction: column;
+      align-items: left;
+
+      .content {
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        padding: 15px 0;
+        border-bottom: 1px solid $gray-light;
+        width: 100%;
+        transition: background-color .15s;
+
+        &.disabled {
+          background-color: $gray-lightest;
+        }
+
+        .newsletter-details {
+          display: flex;
+          flex-direction: row;
+          align-items: center;
+          padding-left: 10px;
+
+          .icon {
+            &.disabled {
+              color: #b7b7b7;
+            }
+            img {
+              height: 32px;
+              width: 32px;
+            }
+            span {
+              @include font-with-weight('Sofia Pro', 500);
+              font-size: 16px;
+            }
+          }
+        }
+      }
+      .text {
+        margin-left: 15px;
+        .title {
+          font-size: 16px;
+          line-height: 28px;
+          @include sofia-pro-medium;
+          text-transform: uppercase;
+          transition: .1s color;
+          &.disabled {
+            color: #b7b7b7;
+          }
+        }
+        .description {
+          @include merriweather-sans-regular;
+          font-size: 13px;
+          margin-top: 4px;
+          color: $accent-gray;
+        }
+      }
+    }
+  }
+
+  .save-section {
+    width: 100%;
+    margin: 0 auto;
+    background-color: #fcfcfc;
+    border-top: 1px solid #f0f0f0;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+
+    button.save {
+      margin-bottom: 15px;
+      margin-top: 15px;
+      width: 100px;
+    }
+  }
+}
\ No newline at end of file

From aca36b2f8ee4e1fda3763e5f2148e8a337360a07 Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Wed, 4 May 2016 12:07:23 +0530
Subject: [PATCH 7/9] AS#118090147171050, Email settings tab UI

-- Fixed lint error
---
 app/settings/email/email.controller.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/app/settings/email/email.controller.js b/app/settings/email/email.controller.js
index 0e61e861f..dbee69659 100644
--- a/app/settings/email/email.controller.js
+++ b/app/settings/email/email.controller.js
@@ -1,5 +1,4 @@
 import angular from 'angular'
-import _ from 'lodash'
 
 (function () {
   'use strict'

From 64bb8f4276ab3cf1dd31670a107236da9be0148c Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Wed, 4 May 2016 12:29:19 +0530
Subject: [PATCH 8/9] AS#118090147171050, Email settings tab UI

-- Removed preferences option from preferences tab for email
---
 app/settings/preferences/preferences.jade | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/app/settings/preferences/preferences.jade b/app/settings/preferences/preferences.jade
index 7e9c5f3b2..b836ce4dd 100644
--- a/app/settings/preferences/preferences.jade
+++ b/app/settings/preferences/preferences.jade
@@ -1,12 +1,5 @@
 .preferences-container
     ul
-      li
-        a(href="http://thecloud.appirio.com/email_prefs_request.html", target="_blank")
-          .icon
-            i.fa.fa-envelope
-          span Email Preferences
-          .description Specify what kind of email you would like to receive from us
-
       li
         a(href="https://apps.{{DOMAIN}}/forums/?module=Settings", target="_blank")
           .icon

From 4a74ae9058c9ff370da4eb91fe14d8ced1f95cef Mon Sep 17 00:00:00 2001
From: vikasrohit <vikas.agarwal@appirio.com>
Date: Wed, 4 May 2016 13:22:26 +0530
Subject: [PATCH 9/9] AS#118090147171048, Mail chimp Integration

-- Removed temporary build
---
 .travis.yml | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 667e45a5d..7f699e053 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,16 +7,6 @@ script:
 - npm run lint && npm test && npm run build
 sudo: false
 deploy:
-- provider: s3
-  cache_control: private, no-store, no-cache, must-revalidate, max-age=0
-  detect_encoding: true
-  access_key_id: $AWS_KEY
-  secret_access_key: $AWS_SECRET
-  bucket: app.topcoder-dev.com
-  skip_cleanup: true
-  local_dir: dist
-  on:
-    branch: feature/mailchimp
 - provider: s3
   cache_control: private, no-store, no-cache, must-revalidate, max-age=0
   detect_encoding: true