Ghost/ghost/core/test/integration/services/q-email-addresses.test.js

490 lines
21 KiB
JavaScript
Raw Normal View History

Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
const DomainEvents = require('@tryghost/domain-events');
const {Mention} = require('@tryghost/webmentions');
const mentionsService = require('../../../core/server/services/mentions');
const assert = require('assert/strict');
const {agentProvider, fixtureManager, mockManager} = require('../../utils/e2e-framework');
const configUtils = require('../../utils/configUtils');
const {mockLabsDisabled, mockLabsEnabled, mockSetting} = require('../../utils/e2e-framework-mock-manager');
const ObjectId = require('bson-objectid').default;
const {sendEmail, getDefaultNewsletter, getLastEmail} = require('../../utils/batch-email-utils');
const urlUtils = require('../../utils/urlUtils');
let emailMockReceiver, agent, membersAgent;
async function sendNewsletter() {
// Prepare a post and email model
await sendEmail(agent);
}
async function sendRecommendationNotification() {
// incoming recommendation in this case
const webmention = await Mention.create({
source: 'https://www.otherghostsite.com/.well-known/recommendations.json',
target: 'https://www.mysite.com/',
timestamp: new Date(),
payload: null,
resourceId: null,
resourceType: null,
sourceTitle: 'Other Ghost Site',
sourceSiteTitle: 'Other Ghost Site',
sourceAuthor: null,
sourceExcerpt: null,
sourceFavicon: null,
sourceFeaturedImage: null
});
// Mark it as verified
webmention.verify('{"url": "https://www.mysite.com/"}', 'application/json');
assert.ok(webmention.verified);
// Save to repository
await mentionsService.repository.save(webmention);
await DomainEvents.allSettled();
}
async function sendFreeMemberSignupNotification() {
const email = ObjectId().toHexString() + '@email.com';
const membersService = require('../../../core/server/services/members');
await membersService.api.members.create({email, name: 'Member Test'});
await DomainEvents.allSettled();
}
async function sendCommentNotification() {
const postId = fixtureManager.get('posts', 0).id;
await membersAgent
.post(`/api/comments/`)
.body({comments: [{
post_id: postId,
parent_id: fixtureManager.get('comments', 0).id,
html: 'This is a reply'
}]})
.expectStatus(201);
}
function configureSite({siteUrl}) {
configUtils.set('url', new URL(siteUrl).href);
}
async function configureNewsletter({sender_email, sender_reply_to, sender_name}) {
const defaultNewsletter = await getDefaultNewsletter();
defaultNewsletter.set('sender_email', sender_email || null);
defaultNewsletter.set('sender_reply_to', sender_reply_to || 'newsletter');
defaultNewsletter.set('sender_name', sender_name || null);
await defaultNewsletter.save();
}
function assertFromAddress(from, replyTo) {
let i = 0;
while (emailMockReceiver.getSentEmail(i)) {
const email = emailMockReceiver.getSentEmail(i);
assert.equal(email.from, from, `From address (${email.from}) of ${i + 1}th email (${email.subject}) does not match ${from}`);
if (!replyTo) {
assert(email.replyTo === null || email.replyTo === undefined, `Unexpected reply-to address (${email.replyTo}) of ${i + 1}th email (${email.subject}), expected none`);
} else {
assert.equal(email.replyTo, replyTo, `ReplyTo address (${email.replyTo}) of ${i + 1}th email (${email.subject}) does not match ${replyTo}`);
}
i += 1;
}
assert(i > 0, 'No emails were sent');
}
async function assertFromAddressNewsletter(aFrom, aReplyTo) {
const email = (await getLastEmail());
const {from} = email;
const replyTo = email['h:Reply-To'];
assert.equal(from, aFrom, `From address (${from}) does not match ${aFrom}`);
if (!aReplyTo) {
assert(replyTo === null || replyTo === undefined, `Unexpected reply-to address (${replyTo}), expected none`);
} else {
assert.equal(replyTo, aReplyTo, `ReplyTo address (${replyTo}) does not match ${aReplyTo}`);
}
}
// Tests the from and replyTo addresses for most emails send from within Ghost.
describe('Email addresses', function () {
before(async function () {
// Can only set site URL once because otherwise agents are messed up
configureSite({
siteUrl: 'http://blog.acme.com'
});
const agents = await agentProvider.getAgentsForMembers();
agent = agents.adminAgent;
membersAgent = agents.membersAgent;
await fixtureManager.init('newsletters', 'members:newsletters', 'users', 'posts', 'comments');
await agent.loginAsAdmin();
await membersAgent.loginAs('member@example.com');
});
beforeEach(async function () {
emailMockReceiver = mockManager.mockMail();
mockManager.mockMailgun();
mockLabsDisabled('newEmailAddresses');
configureSite({
siteUrl: 'http://blog.acme.com'
});
mockSetting('title', 'Example Site');
mockSetting('members_support_address', 'support@address.com');
mockSetting('comments_enabled', 'all');
configUtils.set('mail:from', '"Postmaster" <postmaster@examplesite.com>');
});
afterEach(async function () {
await configUtils.restore();
urlUtils.restore();
mockManager.restore();
});
describe('Legacy setup', function () {
it('[STAFF] sends recommendation notification emails from mail.from', async function () {
await sendRecommendationNotification();
assertFromAddress('"Postmaster" <postmaster@examplesite.com>');
});
it('[STAFF] sends new member notification emails from ghost@domain', async function () {
await sendFreeMemberSignupNotification();
assertFromAddress('"Example Site" <ghost@blog.acme.com>');
});
it('[MEMBERS] send a comment reply notification from the generated noreply email address if support address is set to noreply', async function () {
mockSetting('members_support_address', 'noreply');
await sendCommentNotification();
assertFromAddress('"Example Site" <noreply@blog.acme.com>');
});
it('[MEMBERS] send a comment reply notification from the generated noreply email address if no support address is set', async function () {
mockSetting('members_support_address', '');
await sendCommentNotification();
assertFromAddress('"Example Site" <noreply@blog.acme.com>');
});
it('[MEMBERS] send a comment reply notification from the support address', async function () {
await sendCommentNotification();
assertFromAddress('"Example Site" <support@address.com>');
});
it('[NEWSLETTER] Allows to send a newsletter from any configured email address', async function () {
await configureNewsletter({
sender_email: 'anything@possible.com',
sender_name: 'Anything Possible',
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <anything@possible.com>', '"Anything Possible" <anything@possible.com>');
});
it('[NEWSLETTER] Sends from a generated noreply by default', async function () {
await configureNewsletter({
sender_email: null,
sender_name: 'Anything Possible',
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <noreply@blog.acme.com>', '"Anything Possible" <noreply@blog.acme.com>');
});
it('[NEWSLETTER] Can set the reply to to the support address', async function () {
await configureNewsletter({
sender_email: null,
sender_name: 'Anything Possible',
sender_reply_to: 'support'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <noreply@blog.acme.com>', 'support@address.com');
});
it('[NEWSLETTER] Uses site title as default sender name', async function () {
await configureNewsletter({
sender_email: null,
sender_name: null,
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Example Site" <noreply@blog.acme.com>', '"Example Site" <noreply@blog.acme.com>');
});
});
describe('Custom sending domain', function () {
beforeEach(async function () {
configUtils.set('hostSettings:managedEmail:enabled', true);
configUtils.set('hostSettings:managedEmail:sendingDomain', 'sendingdomain.com');
configUtils.set('mail:from', '"Default Address" <default@sendingdomain.com>');
});
it('[STAFF] sends recommendation emails from mail.from config variable', async function () {
await sendRecommendationNotification();
assertFromAddress('"Default Address" <default@sendingdomain.com>');
});
it('[STAFF] sends new member notification emails from mail.from config variable', async function () {
await sendFreeMemberSignupNotification();
assertFromAddress('"Default Address" <default@sendingdomain.com>');
});
it('[STAFF] Uses site title as email address name if no name set in mail:from', async function () {
configUtils.set('mail:from', 'default@sendingdomain.com');
await sendFreeMemberSignupNotification();
assertFromAddress('"Example Site" <default@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification from the configured sending domain if support address is set to noreply', async function () {
mockSetting('members_support_address', 'noreply');
await sendCommentNotification();
assertFromAddress('"Example Site" <noreply@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification from the default email address if no support address is set', async function () {
mockSetting('members_support_address', '');
await sendCommentNotification();
assertFromAddress('"Default Address" <default@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification from the support address only if it matches the sending domain', async function () {
mockSetting('members_support_address', 'support@sendingdomain.com');
await sendCommentNotification();
assertFromAddress('"Example Site" <support@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification with replyTo set to the support address if it doesn\'t match the sending domain', async function () {
await sendCommentNotification();
assertFromAddress('"Default Address" <default@sendingdomain.com>', 'support@address.com');
});
it('[NEWSLETTER] Does not allow to send a newsletter from any email address (instead uses mail.from), but allows reply-to to be set', async function () {
Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
await configureNewsletter({
sender_email: 'anything@possible.com',
sender_name: 'Anything Possible',
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <default@sendingdomain.com>', '"Anything Possible" <anything@possible.com>');
Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
});
it('[NEWSLETTER] Does allow to send a newsletter from a custom sending domain', async function () {
await configureNewsletter({
sender_email: 'anything@sendingdomain.com',
sender_name: 'Anything Possible',
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <anything@sendingdomain.com>');
Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
});
it('[NEWSLETTER] Does allow to set the replyTo address to any address', async function () {
await configureNewsletter({
sender_email: 'anything@sendingdomain.com',
sender_name: 'Anything Possible',
sender_reply_to: 'anything@possible.com'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <anything@sendingdomain.com>', 'anything@possible.com');
});
it('[NEWSLETTER] Can set the reply to to the support address', async function () {
await configureNewsletter({
sender_email: null,
sender_name: 'Anything Possible',
sender_reply_to: 'support'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <default@sendingdomain.com>', 'support@address.com');
});
it('[NEWSLETTER] Uses site title as default sender name', async function () {
await configureNewsletter({
sender_email: null,
sender_name: null,
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Example Site" <default@sendingdomain.com>');
Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
});
});
describe('Managed email without custom sending domain', function () {
beforeEach(async function () {
configUtils.set('hostSettings:managedEmail:enabled', true);
configUtils.set('hostSettings:managedEmail:sendingDomain', undefined);
configUtils.set('mail:from', 'default@sendingdomain.com');
});
it('[STAFF] sends recommendation emails from mail.from config variable', async function () {
await sendRecommendationNotification();
assertFromAddress('"Example Site" <default@sendingdomain.com>');
});
it('[STAFF] sends new member notification emails from mail.from config variable', async function () {
await sendFreeMemberSignupNotification();
assertFromAddress('"Example Site" <default@sendingdomain.com>');
});
it('[STAFF] Prefers to use the mail:from sending name if set above the site name', async function () {
configUtils.set('mail:from', '"Default Address" <default@sendingdomain.com>');
await sendFreeMemberSignupNotification();
assertFromAddress('"Default Address" <default@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification from mail.from if support address is set to noreply', async function () {
mockSetting('members_support_address', 'noreply');
await sendCommentNotification();
assertFromAddress('"Example Site" <default@sendingdomain.com>', 'noreply@blog.acme.com');
});
it('[MEMBERS] send a comment reply notification from mail.from if no support address is set, without a replyTo', async function () {
mockSetting('members_support_address', '');
await sendCommentNotification();
assertFromAddress('"Example Site" <default@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification from mail.from with member support address set as replyTo', async function () {
mockSetting('members_support_address', 'hello@acme.com');
await sendCommentNotification();
assertFromAddress('"Example Site" <default@sendingdomain.com>', 'hello@acme.com');
});
it('[NEWSLETTER] Does not allow to send a newsletter from any email address (instead uses mail.from), but allow reply-to to be set', async function () {
Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
await configureNewsletter({
sender_email: 'anything@possible.com',
sender_name: 'Anything Possible',
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <default@sendingdomain.com>', '"Anything Possible" <anything@possible.com>');
Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
});
it('[NEWSLETTER] Does allow to set the replyTo address to any address', async function () {
await configureNewsletter({
sender_email: 'anything@possible.com',
sender_name: 'Anything Possible',
sender_reply_to: 'anything@possible.com'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <default@sendingdomain.com>', 'anything@possible.com');
});
it('[NEWSLETTER] Can set the reply to to the support address', async function () {
await configureNewsletter({
sender_email: null,
sender_name: 'Anything Possible',
sender_reply_to: 'support'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <default@sendingdomain.com>', 'support@address.com');
});
it('[NEWSLETTER] Uses site title as default sender name', async function () {
await configureNewsletter({
sender_email: null,
sender_name: null,
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Example Site" <default@sendingdomain.com>');
Added email address alignment protections (#19094) ref GRO-54 fixes GRO-63 fixes GRO-62 fixes GRO-69 When the config `hostSettings:managedEmail:enabled` is enabled, or the new flag (`newEmailAddresses`) is enabled for self-hosters, we'll start to check the from addresses of all outgoing emails more strictly. - Current flow: nothing changes if the managedEmail config is not set or the `newEmailAddresses` feature flag is not set - When managedEmail is enabled: never allow to send an email from any chosen email. We always use `mail.from` for all outgoing emails. Custom addresses should be set as replyTo instead. Changing the newsletter sender_email is not allowed anymore (and ignored if it is set). - When managedEmail is enabled with a custom sending domain: if a from address doesn't match the sending domain, we'll default to mail.from and use the original as a replyTo if appropriate and only when no other replyTo was set. A newsletter sender email addresss can only be set to an email address on this domain. - When `newEmailAddresses` is enabled: self hosters are free to set all email addresses to whatever they want, without verification. In addition to that, we stop making up our own email addresses and send from `mail.from` by default instead of generating a `noreply`+ `@` + `sitedomain.com` address A more in depth example of all cases can be seen in `ghost/core/test/integration/services/email-addresses.test.js` Includes lots of new E2E tests for most new situations. Apart from that, all email snapshots are changed because the from and replyTo addresses are now included in snapshots (so we can see unexpected changes in the future). Dropped test coverage requirement, because tests were failing coverage locally, but not in CI Fixed settings test that set the site title to an array - bug tracked in GRO-68
2023-11-23 12:25:30 +03:00
});
});
describe('Self-hosted', function () {
beforeEach(async function () {
mockLabsEnabled('newEmailAddresses');
configUtils.set('hostSettings:managedEmail:enabled', false);
configUtils.set('hostSettings:managedEmail:sendingDomain', undefined);
configUtils.set('mail:from', '"Default Address" <default@sendingdomain.com>');
});
it('[STAFF] sends recommendation emails from mail.from config variable', async function () {
await sendRecommendationNotification();
assertFromAddress('"Default Address" <default@sendingdomain.com>');
});
it('[STAFF] sends new member notification emails from mail.from config variable', async function () {
await sendFreeMemberSignupNotification();
assertFromAddress('"Default Address" <default@sendingdomain.com>');
});
it('[STAFF] Uses site title as email address name if no name set in mail:from', async function () {
configUtils.set('mail:from', 'default@sendingdomain.com');
await sendFreeMemberSignupNotification();
assertFromAddress('"Example Site" <default@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification with noreply support address', async function () {
mockSetting('members_support_address', 'noreply');
await sendCommentNotification();
assertFromAddress('"Example Site" <noreply@blog.acme.com>');
});
it('[MEMBERS] send a comment reply notification without support address', async function () {
mockSetting('members_support_address', '');
await sendCommentNotification();
// Use default
assertFromAddress('"Default Address" <default@sendingdomain.com>');
});
it('[MEMBERS] send a comment reply notification from chosen support address', async function () {
mockSetting('members_support_address', 'hello@acme.com');
await sendCommentNotification();
assertFromAddress('"Example Site" <hello@acme.com>');
});
it('[NEWSLETTER] Does allow to send a newsletter from any configured email address', async function () {
await configureNewsletter({
sender_email: 'anything@possible.com',
sender_name: 'Anything Possible',
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <anything@possible.com>', '"Anything Possible" <anything@possible.com>');
});
it('[NEWSLETTER] Does allow to set the replyTo address to any address', async function () {
await configureNewsletter({
sender_email: 'anything@possible.com',
sender_name: 'Anything Possible',
sender_reply_to: 'anything@noreply.com'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <anything@possible.com>', 'anything@noreply.com');
});
it('[NEWSLETTER] Can set the reply to to the support address', async function () {
await configureNewsletter({
sender_email: null,
sender_name: 'Anything Possible',
sender_reply_to: 'support'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Anything Possible" <default@sendingdomain.com>', 'support@address.com');
});
it('[NEWSLETTER] Uses site title as default sender name', async function () {
await configureNewsletter({
sender_email: null,
sender_name: null,
sender_reply_to: 'newsletter'
});
await sendNewsletter();
await assertFromAddressNewsletter('"Example Site" <default@sendingdomain.com>', '"Example Site" <default@sendingdomain.com>');
});
});
});