mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-29 22:01:49 +03:00
🐛 Fixed unsubscribe flow for comment reply emails (#15232)
refs https://github.com/TryGhost/Team/issues/1790 - Currently we go to the account settings when you click 'Manage your email preferences' in the footer of an email that informs a comment author that they received a reply. - Related Portal changes are here: https://github.com/TryGhost/Portal/pull/255
This commit is contained in:
parent
f6a7f75465
commit
a666b846e6
@ -18,6 +18,9 @@ module.exports = async function unsubscribeController(req, res) {
|
|||||||
if (query.newsletter) {
|
if (query.newsletter) {
|
||||||
redirectUrl.searchParams.append('newsletter', query.newsletter);
|
redirectUrl.searchParams.append('newsletter', query.newsletter);
|
||||||
}
|
}
|
||||||
|
if (query.comments) {
|
||||||
|
redirectUrl.searchParams.append('comments', query.comments);
|
||||||
|
}
|
||||||
redirectUrl.searchParams.append('action', 'unsubscribe');
|
redirectUrl.searchParams.append('action', 'unsubscribe');
|
||||||
|
|
||||||
return res.redirect(302, redirectUrl.href);
|
return res.redirect(302, redirectUrl.href);
|
||||||
|
@ -234,7 +234,7 @@ module.exports = {
|
|||||||
// static data for every recipient
|
// static data for every recipient
|
||||||
const data = {
|
const data = {
|
||||||
unique_id: recipient.member_uuid,
|
unique_id: recipient.member_uuid,
|
||||||
unsubscribe_url: postEmailSerializer.createUnsubscribeUrl(recipient.member_uuid, newsletterUuid)
|
unsubscribe_url: postEmailSerializer.createUnsubscribeUrl(recipient.member_uuid, {newsletterUuid})
|
||||||
};
|
};
|
||||||
|
|
||||||
// computed properties on recipients - TODO: better way of handling these
|
// computed properties on recipients - TODO: better way of handling these
|
||||||
|
@ -174,7 +174,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<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">
|
<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;"><a class="small" href="{{profileUrl}}" style="text-decoration: underline; color: #738A94; font-size: 11px;">Manage your email preferences</a></p>
|
<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;"><a class="small" href="{{profileUrl}}" style="text-decoration: underline; color: #738A94; font-size: 11px;">Unsubscribe from comment reply notifications</a></p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -9,5 +9,5 @@ ${data.postUrl}#ghost-comments
|
|||||||
---
|
---
|
||||||
|
|
||||||
Sent to ${data.toEmail} from ${data.siteDomain}.
|
Sent to ${data.toEmail} from ${data.siteDomain}.
|
||||||
You can manage your notification preferences at ${data.profileUrl}.`;
|
You can unsubscribe from these notifications at ${data.profileUrl}.`;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ const {promises: fs} = require('fs');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const htmlToPlaintext = require('@tryghost/html-to-plaintext');
|
const htmlToPlaintext = require('@tryghost/html-to-plaintext');
|
||||||
|
const postEmailSerializer = require('../mega/post-email-serializer');
|
||||||
|
|
||||||
class CommentsServiceEmails {
|
class CommentsServiceEmails {
|
||||||
constructor({config, logging, models, mailer, settingsCache, urlService, urlUtils}) {
|
constructor({config, logging, models, mailer, settingsCache, urlService, urlUtils}) {
|
||||||
@ -93,7 +94,7 @@ class CommentsServiceEmails {
|
|||||||
accentColor: this.settingsCache.get('accent_color'),
|
accentColor: this.settingsCache.get('accent_color'),
|
||||||
fromEmail: this.notificationFromAddress,
|
fromEmail: this.notificationFromAddress,
|
||||||
toEmail: to,
|
toEmail: to,
|
||||||
profileUrl: `${this.urlUtils.getSiteUrl()}#/portal/account/profile`
|
profileUrl: postEmailSerializer.createUnsubscribeUrl(member.get('uuid'), {comments: true})
|
||||||
};
|
};
|
||||||
|
|
||||||
const {html, text} = await this.renderEmailTemplate('new-comment-reply', templateData);
|
const {html, text} = await this.renderEmailTemplate('new-comment-reply', templateData);
|
||||||
|
@ -59,9 +59,11 @@ const getSite = () => {
|
|||||||
* In case of no member uuid, generates the preview unsubscribe url - `?preview=1`
|
* In case of no member uuid, generates the preview unsubscribe url - `?preview=1`
|
||||||
*
|
*
|
||||||
* @param {string} uuid post uuid
|
* @param {string} uuid post uuid
|
||||||
* @param {string} newsletterUuid newsletter uuid
|
* @param {Object} [options]
|
||||||
|
* @param {string} [options.newsletterUuid] newsletter uuid
|
||||||
|
* @param {boolean} [options.comments] Unsubscribe from comment emails
|
||||||
*/
|
*/
|
||||||
const createUnsubscribeUrl = (uuid, newsletterUuid) => {
|
const createUnsubscribeUrl = (uuid, options = {}) => {
|
||||||
const siteUrl = urlUtils.getSiteUrl();
|
const siteUrl = urlUtils.getSiteUrl();
|
||||||
const unsubscribeUrl = new URL(siteUrl);
|
const unsubscribeUrl = new URL(siteUrl);
|
||||||
unsubscribeUrl.pathname = `${unsubscribeUrl.pathname}/unsubscribe/`.replace('//', '/');
|
unsubscribeUrl.pathname = `${unsubscribeUrl.pathname}/unsubscribe/`.replace('//', '/');
|
||||||
@ -70,8 +72,11 @@ const createUnsubscribeUrl = (uuid, newsletterUuid) => {
|
|||||||
} else {
|
} else {
|
||||||
unsubscribeUrl.searchParams.set('preview', '1');
|
unsubscribeUrl.searchParams.set('preview', '1');
|
||||||
}
|
}
|
||||||
if (newsletterUuid) {
|
if (options.newsletterUuid) {
|
||||||
unsubscribeUrl.searchParams.set('newsletter', newsletterUuid);
|
unsubscribeUrl.searchParams.set('newsletter', options.newsletterUuid);
|
||||||
|
}
|
||||||
|
if (options.comments) {
|
||||||
|
unsubscribeUrl.searchParams.set('comments', '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
return unsubscribeUrl.href;
|
return unsubscribeUrl.href;
|
||||||
|
@ -137,7 +137,7 @@
|
|||||||
},
|
},
|
||||||
"portal": {
|
"portal": {
|
||||||
"url": "https://cdn.jsdelivr.net/npm/@tryghost/portal@~{version}/umd/portal.min.js",
|
"url": "https://cdn.jsdelivr.net/npm/@tryghost/portal@~{version}/umd/portal.min.js",
|
||||||
"version": "2.7"
|
"version": "2.8"
|
||||||
},
|
},
|
||||||
"sodoSearch": {
|
"sodoSearch": {
|
||||||
"url": "https://cdn.jsdelivr.net/npm/@tryghost/sodo-search@~{version}/umd/sodo-search.min.js",
|
"url": "https://cdn.jsdelivr.net/npm/@tryghost/sodo-search@~{version}/umd/sodo-search.min.js",
|
||||||
|
@ -236,16 +236,22 @@ describe('Post Email Serializer', function () {
|
|||||||
unsubscribeUrl.should.eql('https://site.com/blah/unsubscribe/?preview=1');
|
unsubscribeUrl.should.eql('https://site.com/blah/unsubscribe/?preview=1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('generates unsubscribe url with only post uuid', function () {
|
it('generates unsubscribe url with only member uuid', function () {
|
||||||
sinon.stub(urlUtils, 'getSiteUrl').returns('https://site.com/blah');
|
sinon.stub(urlUtils, 'getSiteUrl').returns('https://site.com/blah');
|
||||||
const unsubscribeUrl = createUnsubscribeUrl('post-abcd');
|
const unsubscribeUrl = createUnsubscribeUrl('member-abcd');
|
||||||
unsubscribeUrl.should.eql('https://site.com/blah/unsubscribe/?uuid=post-abcd');
|
unsubscribeUrl.should.eql('https://site.com/blah/unsubscribe/?uuid=member-abcd');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('generates unsubscribe url with both post and newsletter uuid', function () {
|
it('generates unsubscribe url with both post and newsletter uuid', function () {
|
||||||
sinon.stub(urlUtils, 'getSiteUrl').returns('https://site.com/blah');
|
sinon.stub(urlUtils, 'getSiteUrl').returns('https://site.com/blah');
|
||||||
const unsubscribeUrl = createUnsubscribeUrl('post-abcd', 'newsletter-abcd');
|
const unsubscribeUrl = createUnsubscribeUrl('member-abcd', {newsletterUuid: 'newsletter-abcd'});
|
||||||
unsubscribeUrl.should.eql('https://site.com/blah/unsubscribe/?uuid=post-abcd&newsletter=newsletter-abcd');
|
unsubscribeUrl.should.eql('https://site.com/blah/unsubscribe/?uuid=member-abcd&newsletter=newsletter-abcd');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generates unsubscribe url with comments', function () {
|
||||||
|
sinon.stub(urlUtils, 'getSiteUrl').returns('https://site.com/blah');
|
||||||
|
const unsubscribeUrl = createUnsubscribeUrl('member-abcd', {comments: true});
|
||||||
|
unsubscribeUrl.should.eql('https://site.com/blah/unsubscribe/?uuid=member-abcd&comments=1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user