From 848b2d82a192e482528dee696f07da00105106ae Mon Sep 17 00:00:00 2001 From: Simon Backx Date: Thu, 4 May 2023 14:47:04 +0200 Subject: [PATCH] Cleaned up suppressionList feature flag (#16736) no issue This pull request removes the `suppressionList` feature flag and all its dependencies from the codebase. It makes the suppression list feature the default and consistent behavior for all email events and newsletters. It simplifies the UI, logic, and data related to email events and newsletters. It affects several files in the `ghost/admin/app`, `ghost/core/core`, and `ghost/members-api` directories. --- .../components/gh-member-settings-form.hbs | 23 ---------- .../app/components/gh-member-settings-form.js | 11 +---- .../app/components/member/activity-feed.js | 4 +- .../member/newsletter-preference.hbs | 10 ++-- .../members-activity/event-type-filter.hbs | 46 ++++++------------- .../members-activity/event-type-filter.js | 15 +----- ghost/admin/app/components/members/filter.js | 6 +-- .../members/filters/email-received.js | 16 ------- .../components/members/filters/email-sent.js | 1 - .../app/components/members/filters/index.js | 1 - .../posts/feedback-events-chart.hbs | 13 ------ .../components/posts/post-activity-feed.hbs | 21 ++------- .../components/posts/post-activity-feed.js | 4 +- .../admin/app/controllers/members-activity.js | 4 -- ghost/admin/app/helpers/parse-member-event.js | 34 +++++--------- ghost/admin/app/services/feature.js | 1 - .../utils/serializers/output/members.js | 5 +- .../core/server/services/members/utils.js | 4 +- ghost/core/core/server/web/members/app.js | 2 +- ghost/core/core/shared/labs.js | 1 - .../admin/__snapshots__/settings.test.js.snap | 2 +- ghost/members-api/lib/MembersAPI.js | 3 -- ghost/members-api/lib/repositories/event.js | 8 +--- .../members-api/lib/services/member-bread.js | 27 ++++------- 24 files changed, 55 insertions(+), 207 deletions(-) delete mode 100644 ghost/admin/app/components/members/filters/email-received.js diff --git a/ghost/admin/app/components/gh-member-settings-form.hbs b/ghost/admin/app/components/gh-member-settings-form.hbs index d7a4f28d49..e3db595e66 100644 --- a/ghost/admin/app/components/gh-member-settings-form.hbs +++ b/ghost/admin/app/components/gh-member-settings-form.hbs @@ -64,29 +64,6 @@

Maximum: 500 characters. You’ve used {{gh-count-down-characters this.scratchMember.note 500}}

- {{#if this.canShowSingleNewsletter}} - -
-
-

Subscribed to newsletter

-

If disabled, member will not receive newsletter emails

-
-
- -
-
-
- {{/if}} diff --git a/ghost/admin/app/components/gh-member-settings-form.js b/ghost/admin/app/components/gh-member-settings-form.js index 49d2cab9b8..229ba2d8ee 100644 --- a/ghost/admin/app/components/gh-member-settings-form.js +++ b/ghost/admin/app/components/gh-member-settings-form.js @@ -116,18 +116,9 @@ export default class extends Component { return null; } - get canShowSingleNewsletter() { - return ( - this.newslettersList?.length === 1 - && this.settings.editorDefaultEmailRecipients !== 'disabled' - && !this.feature.get('suppressionList') - ); - } - get canShowMultipleNewsletters() { return ( - (this.newslettersList?.length > 1 || this.feature.get('suppressionList')) - && this.settings.editorDefaultEmailRecipients !== 'disabled' + this.settings.editorDefaultEmailRecipients !== 'disabled' ); } diff --git a/ghost/admin/app/components/member/activity-feed.js b/ghost/admin/app/components/member/activity-feed.js index b2351b78ba..29cbda7aff 100644 --- a/ghost/admin/app/components/member/activity-feed.js +++ b/ghost/admin/app/components/member/activity-feed.js @@ -6,9 +6,7 @@ export default class ActivityFeed extends Component { @service feature; linkScrollerTimeout = null; // needs to be global so can be cleared when needed across functions - excludedEventTypes = this.feature.get('suppressionList') - ? ['aggregated_click_event'] - : ['email_sent_event', 'aggregated_click_event']; + excludedEventTypes = ['aggregated_click_event']; @action enterLinkURL(event) { diff --git a/ghost/admin/app/components/member/newsletter-preference.hbs b/ghost/admin/app/components/member/newsletter-preference.hbs index db8e096b85..5f9b185bba 100644 --- a/ghost/admin/app/components/member/newsletter-preference.hbs +++ b/ghost/admin/app/components/member/newsletter-preference.hbs @@ -1,5 +1,5 @@

Newsletters

-
+
{{#unless this.suppressionData.suppressed}}
{{#each this.newsletters as |newsletter|}} @@ -7,7 +7,7 @@

{{newsletter.name}}

-
+
+ {{/each}} - \ No newline at end of file + diff --git a/ghost/admin/app/components/members-activity/event-type-filter.js b/ghost/admin/app/components/members-activity/event-type-filter.js index 00d1719592..76f6bcf6ec 100644 --- a/ghost/admin/app/components/members-activity/event-type-filter.js +++ b/ghost/admin/app/components/members-activity/event-type-filter.js @@ -2,19 +2,7 @@ import Component from '@glimmer/component'; import {action} from '@ember/object'; import {inject as service} from '@ember/service'; -// todo: replace function with const after suppressionList feature flag will be removed const ALL_EVENT_TYPES = [ - {event: 'signup_event', icon: 'filter-dropdown-signups', name: 'Signups'}, - {event: 'login_event', icon: 'filter-dropdown-logins', name: 'Logins'}, - {event: 'subscription_event', icon: 'filter-dropdown-paid-subscriptions', name: 'Paid subscriptions'}, - {event: 'payment_event', icon: 'filter-dropdown-payments', name: 'Payments'}, - {event: 'newsletter_event', icon: 'filter-dropdown-email-subscriptions', name: 'Email subscriptions'}, - {event: 'email_opened_event', icon: 'filter-dropdown-email-opened', name: 'Email opens'}, - {event: 'email_delivered_event', icon: 'filter-dropdown-email-received', name: 'Email deliveries'}, - {event: 'email_failed_event', icon: 'filter-dropdown-email-bounced', name: 'Email failures'} -]; - -const ALL_EVENT_TYPES_SUPPRESSION = [ {event: 'signup_event', icon: 'filter-dropdown-signups', name: 'Signups', group: 'auth'}, {event: 'login_event', icon: 'filter-dropdown-logins', name: 'Logins', group: 'auth'}, {event: 'subscription_event', icon: 'filter-dropdown-paid-subscriptions', name: 'Paid subscriptions', group: 'payments'}, @@ -31,8 +19,7 @@ export default class MembersActivityEventTypeFilter extends Component { @service feature; get availableEventTypes() { - // todo: remove condition when feature will be enabled - const extended = this.feature.suppressionList ? [...ALL_EVENT_TYPES_SUPPRESSION] : [...ALL_EVENT_TYPES]; + const extended = ALL_EVENT_TYPES; if (this.settings.commentsEnabled !== 'off') { extended.push({event: 'comment_event', icon: 'filter-dropdown-comments', name: 'Comments', group: 'others'}); diff --git a/ghost/admin/app/components/members/filter.js b/ghost/admin/app/components/members/filter.js index ea8ea5a40b..febad7c715 100644 --- a/ghost/admin/app/components/members/filter.js +++ b/ghost/admin/app/components/members/filter.js @@ -1,7 +1,7 @@ import Component from '@glimmer/component'; import moment from 'moment-timezone'; import nql from '@tryghost/nql-lang'; -import {AUDIENCE_FEEDBACK_FILTER, CREATED_AT_FILTER, EMAIL_CLICKED_FILTER, EMAIL_COUNT_FILTER, EMAIL_FILTER, EMAIL_OPENED_COUNT_FILTER, EMAIL_OPENED_FILTER, EMAIL_OPEN_RATE_FILTER, EMAIL_RECEIVED_FILTER, EMAIL_SENT_FILTER, LABEL_FILTER, LAST_SEEN_FILTER, NAME_FILTER, NEWSLETTERS_FILTER, NEXT_BILLING_DATE_FILTER, OFFERS_FILTER, PLAN_INTERVAL_FILTER, SIGNUP_ATTRIBUTION_FILTER, STATUS_FILTER, SUBSCRIBED_FILTER, SUBSCRIPTION_ATTRIBUTION_FILTER, SUBSCRIPTION_START_DATE_FILTER, SUBSCRIPTION_STATUS_FILTER, TIER_FILTER} from './filters'; +import {AUDIENCE_FEEDBACK_FILTER, CREATED_AT_FILTER, EMAIL_CLICKED_FILTER, EMAIL_COUNT_FILTER, EMAIL_FILTER, EMAIL_OPENED_COUNT_FILTER, EMAIL_OPENED_FILTER, EMAIL_OPEN_RATE_FILTER, EMAIL_SENT_FILTER, LABEL_FILTER, LAST_SEEN_FILTER, NAME_FILTER, NEWSLETTERS_FILTER, NEXT_BILLING_DATE_FILTER, OFFERS_FILTER, PLAN_INTERVAL_FILTER, SIGNUP_ATTRIBUTION_FILTER, STATUS_FILTER, SUBSCRIBED_FILTER, SUBSCRIPTION_ATTRIBUTION_FILTER, SUBSCRIPTION_START_DATE_FILTER, SUBSCRIPTION_STATUS_FILTER, TIER_FILTER} from './filters'; import {TrackedArray} from 'tracked-built-ins'; import {action} from '@ember/object'; import {inject as service} from '@ember/service'; @@ -43,7 +43,6 @@ const FILTER_GROUPS = [ EMAIL_COUNT_FILTER, EMAIL_OPENED_COUNT_FILTER, EMAIL_OPEN_RATE_FILTER, - EMAIL_RECEIVED_FILTER, EMAIL_SENT_FILTER, EMAIL_OPENED_FILTER, EMAIL_CLICKED_FILTER, @@ -145,7 +144,7 @@ export default class MembersFilter extends Component { ]); newsletters; - + get filterProperties() { let availableFilters = FILTER_PROPERTIES; @@ -167,7 +166,6 @@ export default class MembersFilter extends Component { // exclude any filters that are behind disabled feature flags availableFilters = availableFilters.filter(prop => !prop.feature || this.feature[prop.feature]); availableFilters = availableFilters.filter(prop => !prop.setting || this.settings[prop.setting]); - availableFilters = availableFilters.filter(prop => !prop.excludeForFeature || !this.feature[prop.excludeForFeature]); return availableFilters; } diff --git a/ghost/admin/app/components/members/filters/email-received.js b/ghost/admin/app/components/members/filters/email-received.js deleted file mode 100644 index 6e852bb506..0000000000 --- a/ghost/admin/app/components/members/filters/email-received.js +++ /dev/null @@ -1,16 +0,0 @@ -import {MATCH_RELATION_OPTIONS} from './relation-options'; - -export const EMAIL_RECEIVED_FILTER = { - label: 'Received email', - name: 'emails.post_id', - valueType: 'string', - resource: 'email', - excludeForFeature: 'suppressionList', - relationOptions: MATCH_RELATION_OPTIONS, - columnLabel: 'Received email', - getColumnValue: (member, filter) => { - return { - text: filter.resource?.title ?? '' - }; - } -}; diff --git a/ghost/admin/app/components/members/filters/email-sent.js b/ghost/admin/app/components/members/filters/email-sent.js index d1a7cb48fc..45fdbb4d6e 100644 --- a/ghost/admin/app/components/members/filters/email-sent.js +++ b/ghost/admin/app/components/members/filters/email-sent.js @@ -5,7 +5,6 @@ export const EMAIL_SENT_FILTER = { name: 'emails.post_id', valueType: 'string', resource: 'email', - feature: 'suppressionList', relationOptions: MATCH_RELATION_OPTIONS, columnLabel: 'Sent email', getColumnValue: (member, filter) => { diff --git a/ghost/admin/app/components/members/filters/index.js b/ghost/admin/app/components/members/filters/index.js index e098f63bbc..6b10fa69ee 100644 --- a/ghost/admin/app/components/members/filters/index.js +++ b/ghost/admin/app/components/members/filters/index.js @@ -18,7 +18,6 @@ export * from './email-clicked'; export * from './email-opened-count'; export * from './email-open-rate'; export * from './email-clicked'; -export * from './email-received'; export * from './email-sent'; export * from './audience-feedback'; export * from './offers'; diff --git a/ghost/admin/app/components/posts/feedback-events-chart.hbs b/ghost/admin/app/components/posts/feedback-events-chart.hbs index 75cc80a524..c8a2da2de3 100644 --- a/ghost/admin/app/components/posts/feedback-events-chart.hbs +++ b/ghost/admin/app/components/posts/feedback-events-chart.hbs @@ -29,18 +29,5 @@ {{this.tooltipData.label}}
- - {{#if (and this.tooltipData.href (not (feature "suppressionList")))}} - - {{/if}}
diff --git a/ghost/admin/app/components/posts/post-activity-feed.hbs b/ghost/admin/app/components/posts/post-activity-feed.hbs index c227be9558..2691002f8c 100644 --- a/ghost/admin/app/components/posts/post-activity-feed.hbs +++ b/ghost/admin/app/components/posts/post-activity-feed.hbs @@ -84,23 +84,10 @@ {{/if}}
- {{#if (feature "suppressionList")}} - - {{/if}} - - {{#if (and @linkQuery (not (feature "suppressionList")))}} - - {{svg-jar "filter"}} - View members - - {{/if}} +
{{#if (compute (fn this.isPaginationNotNeeded eventsFetcher))}} diff --git a/ghost/admin/app/components/posts/post-activity-feed.js b/ghost/admin/app/components/posts/post-activity-feed.js index c71fa92b5f..937123a2d7 100644 --- a/ghost/admin/app/components/posts/post-activity-feed.js +++ b/ghost/admin/app/components/posts/post-activity-feed.js @@ -7,9 +7,7 @@ export default class PostActivityFeed extends Component { _pageSize = 5; _eventTypes = { - sent: this.feature.get('suppressionList') - ? ['email_sent_event', 'email_delivered_event', 'email_failed_event'] - : ['email_sent_event'], + sent: ['email_sent_event', 'email_delivered_event', 'email_failed_event'], opened: ['email_opened_event'], clicked: ['aggregated_click_event'], feedback: ['feedback_event'], diff --git a/ghost/admin/app/controllers/members-activity.js b/ghost/admin/app/controllers/members-activity.js index b85ef46e7f..36989fc776 100644 --- a/ghost/admin/app/controllers/members-activity.js +++ b/ghost/admin/app/controllers/members-activity.js @@ -27,10 +27,6 @@ export default class MembersActivityController extends Controller { if (!this.member) { hiddenEvents.push(...EMAIL_EVENTS); - } else { - if (!this.feature.get('suppressionList')) { - hiddenEvents.push('email_sent_event'); - } } hiddenEvents.push('aggregated_click_event'); diff --git a/ghost/admin/app/helpers/parse-member-event.js b/ghost/admin/app/helpers/parse-member-event.js index 2ee681ce7a..3bb6e3c167 100644 --- a/ghost/admin/app/helpers/parse-member-event.js +++ b/ghost/admin/app/helpers/parse-member-event.js @@ -78,18 +78,12 @@ export default class ParseMemberEventHelper extends Helper { icon = 'opened-email'; } - if (this.feature.get('suppressionList')) { - if (event.type === 'email_sent_event') { - icon = 'sent-email'; - } + if (event.type === 'email_sent_event') { + icon = 'sent-email'; + } - if (event.type === 'email_delivered_event') { - icon = 'received-email'; - } - } else { - if (event.type === 'email_delivered_event' || event.type === 'email_sent_event') { - icon = 'received-email'; - } + if (event.type === 'email_delivered_event') { + icon = 'received-email'; } if (event.type === 'email_failed_event') { @@ -169,22 +163,16 @@ export default class ParseMemberEventHelper extends Helper { return 'opened email'; } - if (this.feature.get('suppressionList')) { - if (event.type === 'email_sent_event') { - return 'sent email'; - } + if (event.type === 'email_sent_event') { + return 'sent email'; + } - if (event.type === 'email_delivered_event') { - return 'received email'; - } - } else { - if (event.type === 'email_delivered_event' || event.type === 'email_sent_event') { - return 'received email'; - } + if (event.type === 'email_delivered_event') { + return 'received email'; } if (event.type === 'email_failed_event') { - return this.feature.get('suppressionList') ? 'bounced email' : 'failed to receive email'; + return 'bounced email'; } if (event.type === 'email_complaint_event') { diff --git a/ghost/admin/app/services/feature.js b/ghost/admin/app/services/feature.js index 58fbc4ddc1..7725f018e9 100644 --- a/ghost/admin/app/services/feature.js +++ b/ghost/admin/app/services/feature.js @@ -65,7 +65,6 @@ export default class FeatureService extends Service { @feature('lexicalEditor') lexicalEditor; @feature('lexicalMultiplayer') lexicalMultiplayer; @feature('audienceFeedback') audienceFeedback; - @feature('suppressionList') suppressionList; @feature('webmentions') webmentions; @feature('emailErrors') emailErrors; @feature('websockets') websockets; diff --git a/ghost/core/core/server/api/endpoints/utils/serializers/output/members.js b/ghost/core/core/server/api/endpoints/utils/serializers/output/members.js index 344dc294b5..055faececc 100644 --- a/ghost/core/core/server/api/endpoints/utils/serializers/output/members.js +++ b/ghost/core/core/server/api/endpoints/utils/serializers/output/members.js @@ -2,7 +2,6 @@ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output:members'); const {unparse} = require('@tryghost/members-csv'); const mappers = require('./mappers'); -const labs = require('../../../../../../shared/labs'); module.exports = { browse: createSerializer('browse', paginatedMembers), @@ -172,9 +171,7 @@ function serializeMember(member, options) { delete subscription.price.product; } - if (labs.isSet('suppressionList')) { - serialized.email_suppression = json.email_suppression; - } + serialized.email_suppression = json.email_suppression; if (json.newsletters) { serialized.newsletters = json.newsletters diff --git a/ghost/core/core/server/services/members/utils.js b/ghost/core/core/server/services/members/utils.js index 80ecf3329e..089310d67c 100644 --- a/ghost/core/core/server/services/members/utils.js +++ b/ghost/core/core/server/services/members/utils.js @@ -1,5 +1,3 @@ -const labsService = require('../../../shared/labs'); - function formatNewsletterResponse(newsletters) { return newsletters.map(({id, name, description, sort_order: sortOrder}) => { return {id, name, description, sort_order: sortOrder}; @@ -27,7 +25,7 @@ module.exports.formattedMemberResponse = function formattedMemberResponse(member data.newsletters = formatNewsletterResponse(member.newsletters); } - if (labsService.isSet('suppressionList') && member.email_suppression) { + if (member.email_suppression) { data.email_suppression = member.email_suppression; } diff --git a/ghost/core/core/server/web/members/app.js b/ghost/core/core/server/web/members/app.js index 6f558d73be..287a0b5c57 100644 --- a/ghost/core/core/server/web/members/app.js +++ b/ghost/core/core/server/web/members/app.js @@ -47,7 +47,7 @@ module.exports = function setupMembersApp() { membersApp.post('/api/member/email', bodyParser.json({limit: '50mb'}), (req, res) => membersService.api.middleware.updateEmailAddress(req, res)); // Remove email from suppression list - membersApp.delete('/api/member/suppression', labs.enabledMiddleware('suppressionList'), middleware.deleteSuppression); + membersApp.delete('/api/member/suppression', middleware.deleteSuppression); // Manage session membersApp.get('/api/session', middleware.getIdentityToken); diff --git a/ghost/core/core/shared/labs.js b/ghost/core/core/shared/labs.js index 214899e8dc..ba5b02700f 100644 --- a/ghost/core/core/shared/labs.js +++ b/ghost/core/core/shared/labs.js @@ -15,7 +15,6 @@ const messages = { // flags in this list always return `true`, allows quick global enable prior to full flag removal const GA_FEATURES = [ - 'suppressionList', 'sourceAttribution', 'memberAttribution', 'audienceFeedback', diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/settings.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/settings.test.js.snap index 4e6bf0c2d8..1358df9d47 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/settings.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/settings.test.js.snap @@ -718,7 +718,7 @@ exports[`Settings API Edit Can edit a setting 2: [headers] 1`] = ` Object { "access-control-allow-origin": "http://127.0.0.1:2369", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", - "content-length": "4093", + "content-length": "4068", "content-type": "application/json; charset=utf-8", "content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, diff --git a/ghost/members-api/lib/MembersAPI.js b/ghost/members-api/lib/MembersAPI.js index 5990e831cd..0c9ae0982e 100644 --- a/ghost/members-api/lib/MembersAPI.js +++ b/ghost/members-api/lib/MembersAPI.js @@ -351,9 +351,6 @@ module.exports = function MembersAPI({ bus.emit('ready'); DomainEvents.subscribe(EmailSuppressedEvent, async function (event) { - if (!labsService.isSet('suppressionList')) { - return; - } const member = await memberRepository.get({email: event.data.emailAddress}); if (!member) { return; diff --git a/ghost/members-api/lib/repositories/event.js b/ghost/members-api/lib/repositories/event.js index 47ef1b4c85..898bed2c47 100644 --- a/ghost/members-api/lib/repositories/event.js +++ b/ghost/members-api/lib/repositories/event.js @@ -84,9 +84,7 @@ module.exports = class EventRepository { pageActions.push({type: 'email_failed_event', action: 'getEmailFailedEvents'}); } - if (this._labsService.isSet('suppressionList')) { - pageActions.push({type: 'email_complained_event', action: 'getEmailSpamComplaintEvents'}); - } + pageActions.push({type: 'email_complained_event', action: 'getEmailSpamComplaintEvents'}); if (this._labsService.isSet('audienceFeedback')) { pageActions.push({type: 'feedback_event', action: 'getFeedbackEvents'}); @@ -505,9 +503,7 @@ module.exports = class EventRepository { } async getEmailSentEvents(options = {}, filter) { - const filterStr = this._labsService.isSet('suppressionList') - ? 'failed_at:null+processed_at:-null+delivered_at:null+custom:true' - : 'failed_at:null+processed_at:-null+custom:true'; + const filterStr = 'failed_at:null+processed_at:-null+delivered_at:null+custom:true'; options = { ...options, withRelated: ['member', 'email'], diff --git a/ghost/members-api/lib/services/member-bread.js b/ghost/members-api/lib/services/member-bread.js index d5c6efb2b9..962dde8bd4 100644 --- a/ghost/members-api/lib/services/member-bread.js +++ b/ghost/members-api/lib/services/member-bread.js @@ -243,13 +243,11 @@ module.exports = class MemberBREADService { await this.attachAttributionsToMember(member, subscriptionIdMap); } - if (this.labsService.isSet('suppressionList')) { - const suppressionData = await this.emailSuppressionList.getSuppressionData(member.email); - member.email_suppression = { - suppressed: suppressionData.suppressed, - info: suppressionData.info - }; - } + const suppressionData = await this.emailSuppressionList.getSuppressionData(member.email); + member.email_suppression = { + suppressed: suppressionData.suppressed, + info: suppressionData.info + }; return member; } @@ -402,10 +400,7 @@ module.exports = class MemberBREADService { const members = page.data.map(model => model.toJSON(options)); - let bulkSuppressionData; - if (this.labsService.isSet('suppressionList')) { - bulkSuppressionData = await this.emailSuppressionList.getBulkSuppressionData(members.map(member => member.email)); - } + const bulkSuppressionData = await this.emailSuppressionList.getBulkSuppressionData(members.map(member => member.email)); const data = members.map((member, index) => { member.subscriptions = member.subscriptions.filter(sub => !!sub.price); @@ -414,12 +409,10 @@ module.exports = class MemberBREADService { if (!originalWithRelated.includes('products')) { delete member.products; } - if (this.labsService.isSet('suppressionList')) { - member.email_suppression = { - suppressed: bulkSuppressionData[index].suppressed, - info: bulkSuppressionData[index].info - }; - } + member.email_suppression = { + suppressed: bulkSuppressionData[index].suppressed, + info: bulkSuppressionData[index].info + }; return member; });