Removed email notifications for new mentions

These are no longer desired and will be replaced with a digest style
email.
This commit is contained in:
Fabien 'egg' O'Carroll 2023-03-13 18:33:57 +07:00 committed by GitHub
parent 8b978b1eb3
commit 4525c7293c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1 additions and 379 deletions

View File

@ -19,7 +19,6 @@ async function allSettled() {
describe('Webmentions (receiving)', function () {
let agent;
let emailMockReceiver;
before(async function () {
agent = await agentProvider.getWebmentionsAPIAgent();
@ -31,7 +30,6 @@ describe('Webmentions (receiving)', function () {
mockManager.disableNetwork();
mockManager.mockLabsEnabled('webmentions');
mockManager.mockLabsEnabled('webmentionEmails');
emailMockReceiver = mockManager.mockMail();
});
afterEach(async function () {
@ -251,152 +249,6 @@ describe('Webmentions (receiving)', function () {
assert.equal(mention.get('payload'), JSON.stringify({}));
});
it('can send an email notification for a new webmention', async function () {
const targetUrl = new URL('integrations/', urlUtils.getSiteUrl());
const sourceUrl = new URL('http://testpage.com/external-article-123-email-test/');
const html = `
<html><head><title>Test Page</title><meta name="description" content="Test description"><meta name="author" content="John Doe"></head><body></body></html>
`;
nock(targetUrl.origin)
.head(targetUrl.pathname)
.reply(200);
nock(sourceUrl.origin)
.get(sourceUrl.pathname)
.reply(200, html, {'Content-Type': 'text/html'});
await agent.post('/receive/')
.body({
source: sourceUrl.href,
target: targetUrl.href
})
.expectStatus(202);
await allSettled();
const users = await models.User.getEmailAlertUsers('mention-received');
for (const user of users) {
await mockManager.assert.sentEmail({
subject: /New mention from/,
to: user.email
});
}
emailMockReceiver.sentEmailCount(users.length);
});
it('can display post title in notification email', async function () {
const targetUrl = new URL('integrations/', urlUtils.getSiteUrl());
const sourceUrl = new URL('http://testpage.com/external-article-1234-email-test/');
const html = `
<html><head><title>Test Page</title><meta name="description" content="Test description"><meta name="author" content="John Doe"></head><body></body></html>
`;
nock(targetUrl.origin).persist()
.head(targetUrl.pathname)
.reply(200);
nock(sourceUrl.origin).persist()
.get(sourceUrl.pathname)
.reply(200, html, {'Content-Type': 'text/html'});
await agent.post('/receive/')
.body({
source: sourceUrl.href,
target: targetUrl.href
})
.expectStatus(202);
await allSettled();
emailMockReceiver.matchHTMLSnapshot();
});
it('can display page title in notification email', async function () {
const targetUrl = new URL('about/', urlUtils.getSiteUrl());
const sourceUrl = new URL('http://testpage.com/external-article-12345-email-test/');
const html = `
<html><head><title>Test Page</title><meta name="description" content="Test description"><meta name="author" content="John Doe"></head><body></body></html>
`;
nock(targetUrl.origin).persist()
.head(targetUrl.pathname)
.reply(200);
nock(sourceUrl.origin).persist()
.get(sourceUrl.pathname)
.reply(200, html, {'Content-Type': 'text/html'});
await agent.post('/receive/')
.body({
source: sourceUrl.href,
target: targetUrl.href
})
.expectStatus(202);
await allSettled();
emailMockReceiver.matchHTMLSnapshot();
});
it('does not send notification with flag disabled', async function () {
mockManager.mockLabsDisabled('webmentions');
const targetUrl = new URL('integrations/', urlUtils.getSiteUrl());
const sourceUrl = new URL('http://testpage.com/external-article-123-email-test/');
const html = `
<html><head><title>Test Page</title><meta name="description" content="Test description"><meta name="author" content="John Doe"></head><body></body></html>
`;
nock(targetUrl.origin)
.head(targetUrl.pathname)
.reply(200);
nock(sourceUrl.origin)
.get(sourceUrl.pathname)
.reply(200, html, {'Content-Type': 'text/html'});
await agent.post('/receive/')
.body({
source: sourceUrl.href,
target: targetUrl.href
})
.expectStatus(202);
await allSettled();
emailMockReceiver.sentEmailCount(0);
});
it('does not send notification with email flag disabled', async function () {
mockManager.mockLabsDisabled('webmentionEmails');
const targetUrl = new URL('integrations/', urlUtils.getSiteUrl());
const sourceUrl = new URL('http://testpage.com/external-article-123-email-test-2/');
const html = `
<html><head><title>Test Page</title><meta name="description" content="Test description"><meta name="author" content="John Doe"></head><body></body></html>
`;
nock(targetUrl.origin)
.head(targetUrl.pathname)
.reply(200);
nock(sourceUrl.origin)
.get(sourceUrl.pathname)
.reply(200, html, {'Content-Type': 'text/html'});
await agent.post('/receive/')
.body({
source: sourceUrl.href,
target: targetUrl.href
})
.expectStatus(202);
await allSettled();
emailMockReceiver.sentEmailCount(0);
});
it('can verify a webmention <a> link', async function () {
const targetUrl = new URL(urlUtils.getSiteUrl());
const sourceUrl = new URL('http://testpage.com/external-article-2/');

View File

@ -1,136 +0,0 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>💌 New mention from:{{#if sourceSiteTitle}}{{sourceSiteTitle}}{{else}}{{sourceUrl}}{{/if}}</title>
{{> styles}}
</head>
<body style="background-color: #ffffff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
<tr>
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">&nbsp;</td>
<td class="container" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; padding: 10px;">
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 600px; padding: 30px 20px;">
<!-- START CENTERED CONTAINER -->
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 8px;">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; box-sizing: border-box;">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
<tr>
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 20px; color: #15212A; font-weight: bold; line-height: 25px; margin: 0; margin-bottom: 15px;">Hey there,</p>
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 16px;">Your {{#if resource.type}} {{resource.type}} {{else}} page {{/if}} <a href="{{targetUrl}}" style="font-weight: bold; color: #15212A;">{{#if resource.name}}{{resource.name}}{{else}}{{targetUrl}}{{/if}}</a> was mentioned in:</p>
<!--[if !mso !vml]-->
<figure style="margin:0 0 1.5em;padding:0;width:100%;">
<a style="display:flex;min-height:148px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;background:#F9F9FA;border-radius:3px;border:1px solid #F9F9FA;color:#15171a;text-decoration:none" href="{{sourceUrl}}">
<div style="display:inline-block; width:100%; padding:20px">
<div style="color:#15212a;font-size:16px;line-height:1.3em;font-weight:600">{{sourceTitle}}</div>
<div style="display:-webkit-box;overflow-y:hidden;margin-top:12px;max-height:40px;color:#738a94;font-size:13px;line-height:1.5em;font-weight:400">{{sourceExcerpt}}</div>
<div style="display:flex;margin-top:14px;color:#15212a;font-size:13px;font-weight:400">
{{#if sourceFavicon}}<img style="border:none;max-width:100%;margin-right:8px;width:22px;height:22px" src="{{sourceFavicon}}" alt="">{{/if}}
{{#if sourceSiteTitle}}<span style="font-size:13px;line-height:1.5em">{{sourceSiteTitle}}</span>{{/if}}
{{#if sourceAuthor}}<span style="font-size:13px;line-height:1.5em">&nbsp;&#x2022;&nbsp;{{sourceAuthor}}</span>{{/if}}
</div>
</div>
{{#if sourceFeaturedImage}}
<div style="position: relative;flex-grow: 1;min-width: 33%;min-width: 140px; max-width: 180px;" style="background-image: url('{{sourceFeaturedImage}}')" class="new-mention-thumbnail">
<img src="{{sourceFeaturedImage}}" style="border: none; -ms-interpolation-mode: bicubic; max-width: 100%; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 0 3px 3px 0; object-fit: cover; max-height: 100%;"/>
</div>
{{/if}}
</a>
</figure>
<!--[endif]-->
<!--[if vml]>
<table style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; width: 100%; border: 1px solid #f9f9fa; background: #f9f9fa; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;">
<tr>
<td width="100%" style="padding: 20px;">
<table style="margin: 0; padding: 0; border-collapse: collapse; border-spacing: 0;">
<tr>
<td><a style="color: #15212A; font-size: 15px; line-height: 1.5em; font-weight: 600; text-decoration: none;" href="{{sourceUrl}}">{{sourceTitle}}</a></td>
</tr>
<tr>
<td><div><a href="{{sourceUrl}}" style="margin-top: 12px; color: #738a94; font-size: 13px; line-height: 1.5em; font-weight: 400;text-decoration: none;">{{sourceExcerpt}}</a></div></td>
</tr>
<tr>
<td style="padding-top: 14px; color: #15212A; font-size: 13px; font-weight: 400; line-height: 1.5em;">
<table style="margin: 0; padding: 0; border-collapse: collapse; border-spacing: 0;">
<tr>
{{#if sourceFavicon}}
<td valign="middle" style="padding-right: 8px; font-size: 0; line-height: 1.5em">
<a href="{{sourceUrl}}" style="color: #15212A; text-decoration: none;"><img src="{{sourceFavicon}}" width="22" height="22" alt=" "></a>
</td>
{{/if}}
<td valign="middle">
<a href="{{sourceUrl}}" style="color: #15212A; text-decoration: none;">
{{sourceSiteTitle}}
{{#if sourceAuthor}}&nbsp;&#x2022;&nbsp;{{/if}}
{{sourceAuthor}}
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<![endif]-->
<table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box;">
<tbody>
<tr>
<td align="left" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; vertical-align: top; padding-top: 32px; padding-bottom: 12px;">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
<tbody>
<tr>
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; vertical-align: top; background-color: {{accentColor}}; border-radius: 5px; text-align: center;"> <a href="{{siteUrl}}ghost/#/mentions" target="_blank" style="display: inline-block; color: #ffffff; background-color: {{accentColor}}; border: solid 1px {{accentColor}}; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: {{accentColor}};">View mentions</a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<hr/>
<p style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; color: #3A464C; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 5px;">You can also copy & paste this URL into your browser:</p>
<p class="text-link" style="word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;">{{siteUrl}}ghost/#/mentions</p>
</td>
</tr>
<!-- START FOOTER -->
<tr>
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; padding-top: 80px;">
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 18px; font-size: 11px; color: #738A94; font-weight: normal; margin: 0; margin-bottom: 2px;">This message was sent from <a class="small" href="{{siteUrl}}" style="text-decoration: underline; color: #738A94; font-size: 11px;">{{siteDomain}}</a> to <a class="small" href="mailto:{{toEmail}}" style="text-decoration: underline; color: #738A94; font-size: 11px;">{{toEmail}}</a></p>
</td>
</tr>
<tr>
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; padding-top: 2px">
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 18px; font-size: 11px; color: #738A94; font-weight: normal; margin: 0; margin-bottom: 2px;">Dont want to receive these emails? Manage your preferences <a class="small" href="{{staffUrl}}" style="text-decoration: underline; color: #738A94; font-size: 11px;">here</a>.</p>
</td>
</tr>
<!-- END FOOTER -->
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- END CENTERED CONTAINER -->
</div>
</td>
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">&nbsp;</td>
</tr>
</table>
</body>
</html>

View File

@ -1,11 +0,0 @@
module.exports = function (data) {
// Be careful when you indent the email, because whitespaces are visible in emails!
return `
You have been mentioned by ${data.sourceUrl}.
---
Sent to ${data.toEmail} from ${data.siteDomain}.
If you would no longer like to receive these notifications you can adjust your settings at ${data.staffUrl}.
`;
};

View File

@ -162,58 +162,6 @@ class StaffServiceEmails {
}
}
async notifyMentionReceived({mention}) {
const users = await this.models.User.getEmailAlertUsers('mention-received');
let resource = null;
if (mention.resourceId) {
try {
const postModel = await this.models.Post.findOne({id: mention.resourceId.toString()});
// console.log(postModel.toJSON());
if (postModel) {
resource = {
id: postModel.id,
name: postModel.get('title'),
type: postModel.get('type') || 'post'
};
}
} catch (err) {
this.logging.error(err);
}
}
for (const user of users) {
const to = user.email;
const subject = `💌 New mention from: ${mention.sourceSiteTitle}`;
const templateData = {
targetUrl: mention.target,
sourceUrl: mention.source,
sourceTitle: mention.sourceTitle,
sourceExcerpt: mention.sourceExcerpt,
sourceSiteTitle: mention.sourceSiteTitle,
sourceFavicon: mention.sourceFavicon,
sourceAuthor: mention.sourceAuthor,
sourceFeaturedImage: mention.sourceFeaturedImage,
resource,
siteTitle: this.settingsCache.get('title'),
siteUrl: this.urlUtils.getSiteUrl(),
siteDomain: this.siteDomain,
accentColor: this.settingsCache.get('accent_color'),
fromEmail: this.fromEmailAddress,
toEmail: to,
staffUrl: this.urlUtils.urlJoin(this.urlUtils.urlFor('admin', true), '#', `/settings/staff/${user.slug}`)
};
const {html, text} = await this.renderEmailTemplate('new-mention-received', templateData);
await this.sendMail({
to,
subject,
html,
text
});
}
}
/**
*
* @param {object} eventData

View File

@ -1,5 +1,4 @@
const {MemberCreatedEvent, SubscriptionCancelledEvent, SubscriptionActivatedEvent} = require('@tryghost/member-events');
const {MentionCreatedEvent} = require('@tryghost/webmentions');
const {MilestoneCreatedEvent} = require('@tryghost/milestones');
// @NOTE: 'StaffService' is a vague name that does not describe what it's actually doing.
@ -79,10 +78,6 @@ class StaffService {
/** @private */
async handleEvent(type, event) {
if (type === MentionCreatedEvent && event.data.mention && this.labs.isSet('webmentions') && this.labs.isSet('webmentionEmails')) {
return await this.emails.notifyMentionReceived(event.data);
}
if (type === MilestoneCreatedEvent && event.data.milestone && this.labs.isSet('milestoneEmails')) {
await this.emails.notifyMilestoneReceived(event.data);
}
@ -161,15 +156,6 @@ class StaffService {
}
});
// Trigger email when a new webmention is received
this.DomainEvents.subscribe(MentionCreatedEvent, async (event) => {
try {
await this.handleEvent(MentionCreatedEvent, event);
} catch (e) {
this.logging.error(e, `Failed to notify webmention`);
}
});
// Trigger email when a new milestone is reached
this.DomainEvents.subscribe(MilestoneCreatedEvent, async (event) => {
try {

View File

@ -2,7 +2,6 @@
// const testUtils = require('./utils');
const sinon = require('sinon');
const {MemberCreatedEvent, SubscriptionCancelledEvent, SubscriptionActivatedEvent} = require('@tryghost/member-events');
const {MentionCreatedEvent} = require('@tryghost/webmentions');
const {MilestoneCreatedEvent} = require('@tryghost/milestones');
require('./utils');
@ -186,11 +185,10 @@ describe('StaffService', function () {
describe('subscribeEvents', function () {
it('subscribes to events', async function () {
service.subscribeEvents();
subscribeStub.callCount.should.eql(5);
subscribeStub.callCount.should.eql(4);
subscribeStub.calledWith(SubscriptionActivatedEvent).should.be.true();
subscribeStub.calledWith(SubscriptionCancelledEvent).should.be.true();
subscribeStub.calledWith(MemberCreatedEvent).should.be.true();
subscribeStub.calledWith(MentionCreatedEvent).should.be.true();
subscribeStub.calledWith(MilestoneCreatedEvent).should.be.true();
});
});
@ -336,21 +334,6 @@ describe('StaffService', function () {
).should.be.true();
});
it('handles new mention notification', async function () {
await service.handleEvent(MentionCreatedEvent, {
data: {
mention: {
source: 'https://exmaple.com/some-post',
target: 'https://exmaple.com/some-mentioned-post',
sourceSiteTitle: 'Exmaple'
}
}
});
mailStub.calledWith(
sinon.match({subject: `💌 New mention from: Exmaple`})
).should.be.true();
});
it('handles milestone created event', async function () {
await service.handleEvent(MilestoneCreatedEvent, {
data: {