Wired up storage of EmailSpamComplaintEvents

refs https://github.com/TryGhost/Team/issues/2337

This also removes the code which unsubscribes members from newsletters because
that is not the spec of the feature.
This commit is contained in:
Fabien "egg" O'Carroll 2022-11-30 18:50:30 +07:00
parent 9c691f3ea9
commit f9fdee1b28
3 changed files with 23 additions and 12 deletions

View File

@ -14,7 +14,7 @@ class EmailServiceWrapper {
}
const {EmailService, EmailController, EmailRenderer, SendingService, BatchSendingService, EmailSegmenter, EmailEventStorage, MailgunEmailProvider} = require('@tryghost/email-service');
const {Post, Newsletter, Email, EmailBatch, EmailRecipient, Member, EmailRecipientFailure} = require('../../models');
const {Post, Newsletter, Email, EmailBatch, EmailRecipient, Member, EmailRecipientFailure, EmailSpamComplaintEvent} = require('../../models');
const MailgunClient = require('@tryghost/mailgun-client');
const configService = require('../../../shared/config');
const settingsCache = require('../../../shared/settings-cache');
@ -114,7 +114,8 @@ class EmailServiceWrapper {
db,
membersRepository,
models: {
EmailRecipientFailure
EmailRecipientFailure,
EmailSpamComplaintEvent
}
});
this.eventStorage.listen(domainEvents);

View File

@ -767,10 +767,13 @@ describe('EmailEventStorage', function () {
const memberId = emailRecipient.member_id;
const providerId = emailBatch.provider_id;
const timestamp = new Date(2000, 0, 1);
const eventsURI = '/members/events/?' + encodeURIComponent(
`filter=type:-[comment_event,aggregated_click_event]+data.member_id:${memberId}`
);
// Check not unsubscribed
const memberInitial = await membersService.api.members.get({id: memberId}, {withRelated: ['newsletters']});
assert.notEqual(memberInitial.related('newsletters').length, 0, 'This test requires a member that is subscribed to at least one newsletter');
const {body: {events: [notSpamEvent]}} = await agent.get(eventsURI);
assert.notEqual(notSpamEvent.type, 'email_complaint_event', 'This test requires a member that does not have a spam event');
events = [{
event: 'complained',
@ -799,9 +802,9 @@ describe('EmailEventStorage', function () {
// Now wait for events processed
await sleep(200);
// Check if unsubscribed
const member = await membersService.api.members.get({id: memberId}, {withRelated: ['newsletters']});
assert.equal(member.related('newsletters').length, 0);
// Check if event exists
const {body: {events: [spamComplaintEvent]}} = await agent.get(eventsURI);
assert.equal(spamComplaintEvent.type, 'email_complaint_event');
});
it('Can handle unsubscribe events', async function () {

View File

@ -13,6 +13,9 @@ class EmailEventStorage {
this.#membersRepository = membersRepository;
}
/**
* @param {import('@tryghost/domain-events')} domainEvents
*/
listen(domainEvents) {
domainEvents.subscribe(EmailDeliveredEvent, async (event) => {
try {
@ -100,9 +103,9 @@ class EmailEventStorage {
/**
* @private
* @param {'temporary'|'permanent'} severity
* @param {import('@tryghost/email-events').EmailTemporaryBouncedEvent|import('@tryghost/email-events').EmailBouncedEvent} event
* @param {{transacting?: any}} options
* @returns
* @param {import('@tryghost/email-events').EmailTemporaryBouncedEvent|import('@tryghost/email-events').EmailBouncedEvent} event
* @param {{transacting?: any}} options
* @returns
*/
async saveFailure(severity, event, options = {}) {
if (!event.error) {
@ -144,7 +147,7 @@ class EmailEventStorage {
/// We can get events out of order, so only save the last one
return;
}
// Update the existing failure
await existing.save({
severity,
@ -162,7 +165,11 @@ class EmailEventStorage {
}
async handleComplained(event) {
return this.unsubscribeFromNewsletters(event);
await this.#models.EmailSpamComplaintEvent.add({
member_id: event.memberId,
email_id: event.emailId,
email_address: event.email
});
}
async unsubscribeFromNewsletters(event) {