mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-22 19:32:54 +03:00
Added calculated email address settings (#19115)
fixes GRO-73 We need to avoid duplicating the complex logic for determining the default email address and the support email address. So these are now exposed as calculated settings.
This commit is contained in:
parent
a8083960d8
commit
a037ce3dde
@ -79,9 +79,8 @@ export const isManagedEmail = (config: Config) => {
|
||||
};
|
||||
|
||||
export const hasSendingDomain = (config: Config) => {
|
||||
const isDomain = /[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
|
||||
const sendingDomain = config?.hostSettings?.managedEmail?.sendingDomain;
|
||||
return typeof sendingDomain === 'string' && isDomain.test(sendingDomain);
|
||||
return typeof sendingDomain === 'string' && sendingDomain.length > 0;
|
||||
};
|
||||
|
||||
export const sendingDomain = (config: Config) => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {createQuery} from '../utils/api/hooks';
|
||||
import {Config, hasSendingDomain, isManagedEmail, sendingDomain} from './config';
|
||||
|
||||
// Types
|
||||
|
||||
@ -35,7 +36,11 @@ export function getHomepageUrl(siteData: SiteData): string {
|
||||
return `${url.origin}${subdir}`;
|
||||
}
|
||||
|
||||
export function getEmailDomain(siteData: SiteData): string {
|
||||
export function getEmailDomain(siteData: SiteData, config: Config): string {
|
||||
if (isManagedEmail(config) && hasSendingDomain(config)) {
|
||||
return sendingDomain(config) || '';
|
||||
}
|
||||
|
||||
const domain = new URL(siteData.url).hostname || '';
|
||||
if (domain.startsWith('www.')) {
|
||||
return domain.replace(/^(www)\.(?=[^/]*\..{2,5})/, '');
|
||||
@ -43,7 +48,7 @@ export function getEmailDomain(siteData: SiteData): string {
|
||||
return domain;
|
||||
}
|
||||
|
||||
export function fullEmailAddress(value: 'noreply' | string, siteData: SiteData) {
|
||||
const emailDomain = getEmailDomain(siteData);
|
||||
export function fullEmailAddress(value: 'noreply' | string, siteData: SiteData, config: Config) {
|
||||
const emailDomain = getEmailDomain(siteData, config);
|
||||
return value === 'noreply' ? `noreply@${emailDomain}` : value;
|
||||
}
|
||||
|
@ -315,6 +315,14 @@
|
||||
{
|
||||
"key": "firstpromoter_account",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"key": "default_email_address",
|
||||
"value": "default@example.com"
|
||||
},
|
||||
{
|
||||
"key": "support_email_address",
|
||||
"value": "support@example.com"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
|
@ -63,6 +63,10 @@ const features = [{
|
||||
title: 'TK Reminders',
|
||||
description: 'Enables the TK Reminders feature in the editor',
|
||||
flag: 'tkReminders'
|
||||
},{
|
||||
title: 'New email addresses',
|
||||
description: 'For self hosters, forces the usage of the mail.from config as from address for all outgoing emails',
|
||||
flag: 'newEmailAddresses'
|
||||
}];
|
||||
|
||||
const AlphaFeatures: React.FC = () => {
|
||||
|
@ -5,27 +5,36 @@ import useFeatureFlag from '../../../../hooks/useFeatureFlag';
|
||||
import useSettingGroup from '../../../../hooks/useSettingGroup';
|
||||
import validator from 'validator';
|
||||
import {Button, ButtonGroup, ColorPickerField, ConfirmationModal, Form, Heading, Hint, HtmlField, Icon, ImageUpload, LimitModal, PreviewModalContent, Select, SelectOption, Separator, SettingGroupContent, Tab, TabView, TextArea, TextField, Toggle, ToggleGroup, showToast} from '@tryghost/admin-x-design-system';
|
||||
import {Config, hasSendingDomain, isManagedEmail, sendingDomain} from '@tryghost/admin-x-framework/api/config';
|
||||
import {ErrorMessages, useForm, useHandleError} from '@tryghost/admin-x-framework/hooks';
|
||||
import {HostLimitError, useLimiter} from '../../../../hooks/useLimiter';
|
||||
import {Newsletter, useBrowseNewsletters, useEditNewsletter} from '@tryghost/admin-x-framework/api/newsletters';
|
||||
import {RoutingModalProps, useRouting} from '@tryghost/admin-x-framework/routing';
|
||||
import {SiteData} from '@tryghost/admin-x-framework/api/site';
|
||||
import {fullEmailAddress} from '@tryghost/admin-x-framework/api/site';
|
||||
import {getImageUrl, useUploadImage} from '@tryghost/admin-x-framework/api/images';
|
||||
import {getSettingValues} from '@tryghost/admin-x-framework/api/settings';
|
||||
import {hasSendingDomain, isManagedEmail, sendingDomain} from '@tryghost/admin-x-framework/api/config';
|
||||
import {textColorForBackgroundColor} from '@tryghost/color-utils';
|
||||
import {useGlobalData} from '../../../providers/GlobalDataProvider';
|
||||
|
||||
const renderReplyToEmail = (newsletter: Newsletter, siteData: SiteData, membersSupportAddress?: string) => {
|
||||
const renderFrom = (newsletter: Newsletter, config: Config, defaultEmailAddress: string|undefined) => {
|
||||
if (isManagedEmail(config) && defaultEmailAddress) {
|
||||
if (!hasSendingDomain(config)) {
|
||||
// Not changeable: sender_email is ignored
|
||||
return defaultEmailAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return newsletter.sender_email || defaultEmailAddress || '';
|
||||
};
|
||||
|
||||
const renderReplyToEmail = (newsletter: Newsletter, config: Config, supportEmailAddress: string|undefined, defaultEmailAddress: string|undefined) => {
|
||||
if (!newsletter.sender_reply_to) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (newsletter.sender_reply_to === 'newsletter') {
|
||||
return fullEmailAddress(newsletter.sender_email || 'noreply', siteData);
|
||||
return renderFrom(newsletter, config, defaultEmailAddress);
|
||||
} else if (newsletter.sender_reply_to === 'support') {
|
||||
return fullEmailAddress(membersSupportAddress || 'noreply', siteData);
|
||||
return supportEmailAddress || defaultEmailAddress || '';
|
||||
} else {
|
||||
return newsletter.sender_reply_to;
|
||||
}
|
||||
@ -42,7 +51,7 @@ const Sidebar: React.FC<{
|
||||
const {mutateAsync: editNewsletter} = useEditNewsletter();
|
||||
const limiter = useLimiter();
|
||||
const {settings, siteData, config} = useGlobalData();
|
||||
const [membersSupportAddress, icon] = getSettingValues<string>(settings, ['members_support_address', 'icon']);
|
||||
const [icon, defaultEmailAddress, supportEmailAddress] = getSettingValues<string>(settings, ['icon', 'default_email_address', 'support_email_address']);
|
||||
const {mutateAsync: uploadImage} = useUploadImage();
|
||||
const [selectedTab, setSelectedTab] = useState('generalSettings');
|
||||
const hasEmailCustomization = useFeatureFlag('emailCustomization');
|
||||
@ -50,12 +59,11 @@ const Sidebar: React.FC<{
|
||||
const [siteTitle] = getSettingValues(localSettings, ['title']) as string[];
|
||||
const handleError = useHandleError();
|
||||
|
||||
const newsletterAddress = fullEmailAddress(newsletter.sender_email || 'noreply', siteData);
|
||||
const supportAddress = fullEmailAddress(membersSupportAddress || 'noreply', siteData);
|
||||
let newsletterAddress = renderFrom(newsletter, config, defaultEmailAddress);
|
||||
|
||||
const replyToEmails = [
|
||||
{label: `Newsletter address (${newsletterAddress})`, value: 'newsletter'},
|
||||
{label: `Support address (${supportAddress})`, value: 'support'}
|
||||
{label: `Support address (${supportEmailAddress})`, value: 'support'}
|
||||
];
|
||||
|
||||
const fontOptions: SelectOption[] = [
|
||||
@ -156,7 +164,7 @@ const Sidebar: React.FC<{
|
||||
{
|
||||
heading: 'Sender email address',
|
||||
key: 'sender-email-addresss',
|
||||
value: `${newsletter.sender_email}`,
|
||||
value: `${defaultEmailAddress}`,
|
||||
hint: <span className="text-xs text-grey-700">To customise, set up a <a className="text-green" href="#">custom sending domain</a></span>
|
||||
}
|
||||
]}
|
||||
@ -206,7 +214,7 @@ const Sidebar: React.FC<{
|
||||
hint={errors.sender_reply_to}
|
||||
placeholder={newsletterAddress}
|
||||
title="Reply-to email"
|
||||
value={renderReplyToEmail(newsletter, siteData, membersSupportAddress)}
|
||||
value={renderReplyToEmail(newsletter, config, supportEmailAddress, defaultEmailAddress)}
|
||||
onBlur={validate}
|
||||
onChange={e => updateNewsletter({sender_reply_to: e.target.value})}
|
||||
onKeyDown={() => clearError('sender_reply_to')}
|
||||
@ -514,11 +522,11 @@ const Sidebar: React.FC<{
|
||||
|
||||
const NewsletterDetailModalContent: React.FC<{newsletter: Newsletter; onlyOne: boolean;}> = ({newsletter, onlyOne}) => {
|
||||
const modal = useModal();
|
||||
const {siteData, settings, config} = useGlobalData();
|
||||
const {settings, config} = useGlobalData();
|
||||
const {mutateAsync: editNewsletter} = useEditNewsletter();
|
||||
const {updateRoute} = useRouting();
|
||||
const handleError = useHandleError();
|
||||
const [membersSupportAddress] = getSettingValues<string>(settings, ['members_support_address', 'icon']);
|
||||
const [supportEmailAddress, defaultEmailAddress] = getSettingValues<string>(settings, ['support_email_address', 'default_email_address']);
|
||||
|
||||
const {formState, saveState, updateForm, setFormState, handleSave, validate, errors, clearError, okProps} = useForm({
|
||||
initialState: newsletter,
|
||||
@ -527,13 +535,15 @@ const NewsletterDetailModalContent: React.FC<{newsletter: Newsletter; onlyOne: b
|
||||
const {newsletters, meta} = await editNewsletter(formState);
|
||||
if (meta?.sent_email_verification) {
|
||||
if (meta?.sent_email_verification[0] === 'sender_email') {
|
||||
const previousFrom = renderFrom(newsletters[0], config, defaultEmailAddress);
|
||||
|
||||
NiceModal.show(ConfirmationModal, {
|
||||
title: 'Confirm newsletter email address',
|
||||
prompt: <>
|
||||
We‘ve sent a confirmation email to <strong>{formState.sender_email}</strong>.
|
||||
Until the address has been verified newsletters will be sent from the
|
||||
{newsletters[0].sender_email ? ' previous' : ' default'} email address
|
||||
({fullEmailAddress(newsletters[0].sender_email || 'noreply', siteData)}).
|
||||
({previousFrom}).
|
||||
</>,
|
||||
cancelLabel: '',
|
||||
onOk: (confirmModal) => {
|
||||
@ -543,7 +553,7 @@ const NewsletterDetailModalContent: React.FC<{newsletter: Newsletter; onlyOne: b
|
||||
}
|
||||
});
|
||||
} else if (meta?.sent_email_verification[0] === 'sender_reply_to') {
|
||||
const previousReplyTo = renderReplyToEmail(newsletters[0], siteData, membersSupportAddress);
|
||||
const previousReplyTo = renderReplyToEmail(newsletters[0], config, supportEmailAddress, defaultEmailAddress);
|
||||
|
||||
NiceModal.show(ConfirmationModal, {
|
||||
title: 'Confirm reply-to address',
|
||||
|
@ -2,16 +2,15 @@ import NewsletterPreviewContent from './NewsletterPreviewContent';
|
||||
import React from 'react';
|
||||
import useFeatureFlag from '../../../../hooks/useFeatureFlag';
|
||||
import {Newsletter} from '@tryghost/admin-x-framework/api/newsletters';
|
||||
import {fullEmailAddress} from '@tryghost/admin-x-framework/api/site';
|
||||
import {getSettingValues} from '@tryghost/admin-x-framework/api/settings';
|
||||
import {hasSendingDomain, isManagedEmail, sendingDomain} from '@tryghost/admin-x-framework/api/config';
|
||||
import {hasSendingDomain, isManagedEmail} from '@tryghost/admin-x-framework/api/config';
|
||||
import {textColorForBackgroundColor} from '@tryghost/color-utils';
|
||||
import {useGlobalData} from '../../../providers/GlobalDataProvider';
|
||||
|
||||
const NewsletterPreview: React.FC<{newsletter: Newsletter}> = ({newsletter}) => {
|
||||
const hasEmailCustomization = useFeatureFlag('emailCustomization');
|
||||
const {currentUser, settings, siteData, config} = useGlobalData();
|
||||
const [title, icon, commentsEnabled] = getSettingValues<string>(settings, ['title', 'icon', 'comments_enabled']);
|
||||
const [title, icon, commentsEnabled, defaultEmailAddress] = getSettingValues<string>(settings, ['title', 'icon', 'comments_enabled', 'default_email_address']);
|
||||
|
||||
let headerTitle: string | null = null;
|
||||
if (newsletter.show_header_title) {
|
||||
@ -94,12 +93,13 @@ const NewsletterPreview: React.FC<{newsletter: Newsletter}> = ({newsletter}) =>
|
||||
|
||||
const renderSenderEmail = () => {
|
||||
if (isManagedEmail(config)) {
|
||||
if (hasSendingDomain(config)) {
|
||||
return newsletter.sender_email || 'noreply@' + sendingDomain(config);
|
||||
if (!hasSendingDomain(config)) {
|
||||
// Sender email is ignored
|
||||
return defaultEmailAddress || '';
|
||||
}
|
||||
}
|
||||
|
||||
return fullEmailAddress(newsletter.sender_email || 'noreply', siteData);
|
||||
return newsletter.sender_email || defaultEmailAddress || '';
|
||||
};
|
||||
|
||||
return <NewsletterPreviewContent
|
||||
|
@ -7,11 +7,11 @@ import {useGlobalData} from '../../../providers/GlobalDataProvider';
|
||||
const AccountPage: React.FC<{
|
||||
updateSetting: (key: string, setting: SettingValue) => void
|
||||
}> = ({updateSetting}) => {
|
||||
const {siteData, settings} = useGlobalData();
|
||||
const {siteData, settings, config} = useGlobalData();
|
||||
const [membersSupportAddress] = getSettingValues(settings, ['members_support_address']);
|
||||
const emailDomain = getEmailDomain(siteData!);
|
||||
const emailDomain = getEmailDomain(siteData!, config);
|
||||
|
||||
const [value, setValue] = useState(fullEmailAddress(membersSupportAddress?.toString() || '', siteData!));
|
||||
const [value, setValue] = useState(fullEmailAddress(membersSupportAddress?.toString() || '', siteData!, config));
|
||||
|
||||
const updateSupportAddress: FocusEventHandler<HTMLInputElement> = (e) => {
|
||||
let supportAddress = e.target.value;
|
||||
@ -19,11 +19,11 @@ const AccountPage: React.FC<{
|
||||
let settingValue = emailDomain && supportAddress === `noreply@${emailDomain}` ? 'noreply' : supportAddress;
|
||||
|
||||
updateSetting('members_support_address', settingValue);
|
||||
setValue(fullEmailAddress(settingValue, siteData!));
|
||||
setValue(fullEmailAddress(settingValue, siteData!, config));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setValue(fullEmailAddress(membersSupportAddress?.toString() || '', siteData!));
|
||||
setValue(fullEmailAddress(membersSupportAddress?.toString() || '', siteData!, config));
|
||||
}, [membersSupportAddress, siteData]);
|
||||
|
||||
return <div className='mt-7'><Form>
|
||||
|
@ -66,7 +66,7 @@ const PortalModal: React.FC = () => {
|
||||
const [selectedPreviewTab, setSelectedPreviewTab] = useState('signup');
|
||||
|
||||
const handleError = useHandleError();
|
||||
const {settings, siteData} = useGlobalData();
|
||||
const {settings, siteData, config} = useGlobalData();
|
||||
const {mutateAsync: editSettings} = useEditSettings();
|
||||
const {data: {tiers: allTiers} = {}} = useBrowseTiers();
|
||||
// const tiers = getPaidActiveTiers(allTiers || []);
|
||||
@ -141,7 +141,7 @@ const PortalModal: React.FC = () => {
|
||||
title: 'Confirm email address',
|
||||
prompt: <>
|
||||
We've sent a confirmation email to <strong>{newEmail}</strong>.
|
||||
Until verified, your support address will remain {fullEmailAddress(currentEmail?.toString() || 'noreply', siteData!)}.
|
||||
Until verified, your support address will remain {fullEmailAddress(currentEmail?.toString() || 'noreply', siteData!, config)}.
|
||||
</>,
|
||||
okLabel: 'Close',
|
||||
cancelLabel: '',
|
||||
|
@ -125,7 +125,7 @@ test.describe('Newsletter settings', async () => {
|
||||
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveCount(1);
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveText(/Confirm newsletter email address/);
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveText(/default email address \(noreply@test.com\)/);
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveText(/default email address \(default@example.com\)/);
|
||||
});
|
||||
|
||||
test('Displays the current email when changing sender address', async ({page}) => {
|
||||
@ -246,7 +246,7 @@ test.describe('Newsletter settings', async () => {
|
||||
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveCount(1);
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveText(/Confirm reply-to address/);
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveText(/previous reply-to address \(noreply@test.com\)/);
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveText(/previous reply-to address \(support@example.com\)/);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -128,6 +128,10 @@ class SettingsHelpers {
|
||||
* @deprecated Use getDefaultEmail().address (without name) or EmailAddressParser.stringify(this.getDefaultEmail()) (with name) instead
|
||||
*/
|
||||
getNoReplyAddress() {
|
||||
return this.getDefaultEmailAddress();
|
||||
}
|
||||
|
||||
getDefaultEmailAddress() {
|
||||
return this.getDefaultEmail().address;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,10 @@ module.exports = {
|
||||
fields.push(new CalculatedField({key: 'firstpromoter_account', type: 'string', group: 'firstpromoter', fn: settingsHelpers.getFirstpromoterId.bind(settingsHelpers), dependents: ['firstpromoter', 'firstpromoter_id']}));
|
||||
fields.push(new CalculatedField({key: 'donations_enabled', type: 'boolean', group: 'donations', fn: settingsHelpers.areDonationsEnabled.bind(settingsHelpers), dependents: ['stripe_secret_key', 'stripe_publishable_key', 'stripe_connect_secret_key', 'stripe_connect_publishable_key']}));
|
||||
|
||||
// E-mail addresses
|
||||
fields.push(new CalculatedField({key: 'default_email_address', type: 'string', group: 'email', fn: settingsHelpers.getDefaultEmailAddress.bind(settingsHelpers), dependents: ['labs']}));
|
||||
fields.push(new CalculatedField({key: 'support_email_address', type: 'string', group: 'email', fn: settingsHelpers.getMembersSupportAddress.bind(settingsHelpers), dependents: ['labs', 'members_support_address']}));
|
||||
|
||||
return fields;
|
||||
},
|
||||
|
||||
|
@ -340,6 +340,14 @@ Object {
|
||||
"key": "donations_enabled",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"key": "default_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
Object {
|
||||
"key": "support_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -750,6 +758,14 @@ Object {
|
||||
"key": "donations_enabled",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"key": "default_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
Object {
|
||||
"key": "support_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -758,7 +774,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": "4367",
|
||||
"content-length": "4487",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1108,6 +1124,14 @@ Object {
|
||||
"key": "donations_enabled",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"key": "default_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
Object {
|
||||
"key": "support_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -1465,6 +1489,14 @@ Object {
|
||||
"key": "donations_enabled",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"key": "default_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
Object {
|
||||
"key": "support_email_address",
|
||||
"value": "support@example.com",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -1827,6 +1859,14 @@ Object {
|
||||
"key": "donations_enabled",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"key": "default_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
Object {
|
||||
"key": "support_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -2277,6 +2317,14 @@ Object {
|
||||
"key": "donations_enabled",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"key": "default_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
Object {
|
||||
"key": "support_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -2699,6 +2747,14 @@ Object {
|
||||
"key": "donations_enabled",
|
||||
"value": true,
|
||||
},
|
||||
Object {
|
||||
"key": "default_email_address",
|
||||
"value": "noreply@127.0.0.1",
|
||||
},
|
||||
Object {
|
||||
"key": "support_email_address",
|
||||
"value": "support@example.com",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
@ -9,7 +9,7 @@ const models = require('../../../core/server/models');
|
||||
const {mockLabsDisabled} = require('../../utils/e2e-framework-mock-manager');
|
||||
const {anyErrorId} = matchers;
|
||||
|
||||
const CURRENT_SETTINGS_COUNT = 84;
|
||||
const CURRENT_SETTINGS_COUNT = 86;
|
||||
|
||||
const settingsMatcher = {};
|
||||
|
||||
|
@ -151,7 +151,7 @@ export class EmailAddressService {
|
||||
// Self hoster or legacy Ghost Pro
|
||||
return {
|
||||
allowed: true,
|
||||
verificationEmailRequired: type === 'from' && !this.useNewEmailAddresses
|
||||
verificationEmailRequired: !this.useNewEmailAddresses // Self hosters don't need to verify email addresses
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user