mirror of
https://github.com/mjl-/mox.git
synced 2025-07-12 18:24:35 +03:00
Allow multiple localpart catch all separators, e.g. both "+" and "-", for addresses you+anything@example.com and you-anything@example.com
The original config option stays, and we still use it for the common case where we have a single separator. The "+" is configured by default. It is optional, just like the new option "LocalpartCatchallSeparators" (plural). When parsing the config file, we combine LocalpartCatchallSeparator and LocalpartCatchallSeparators into a single list LocalpartCatchallSeparatorsEffective, which we use throughout the code. For issue #301 by janc13
This commit is contained in:
@ -2527,9 +2527,19 @@ func (Admin) DomainClientSettingsDomainSave(ctx context.Context, domainName, cli
|
||||
|
||||
// DomainLocalpartConfigSave saves the localpart catchall and case-sensitive
|
||||
// settings for a domain.
|
||||
func (Admin) DomainLocalpartConfigSave(ctx context.Context, domainName, localpartCatchallSeparator string, localpartCaseSensitive bool) {
|
||||
func (Admin) DomainLocalpartConfigSave(ctx context.Context, domainName string, localpartCatchallSeparators []string, localpartCaseSensitive bool) {
|
||||
err := admin.DomainSave(ctx, domainName, func(domain *config.Domain) error {
|
||||
domain.LocalpartCatchallSeparator = localpartCatchallSeparator
|
||||
domain.LocalpartCatchallSeparatorsEffective = localpartCatchallSeparators
|
||||
// If there is a single separator, we prefer the non-list form, it's easier to
|
||||
// read/edit and should suffice for most setups.
|
||||
domain.LocalpartCatchallSeparator = ""
|
||||
domain.LocalpartCatchallSeparators = nil
|
||||
if len(localpartCatchallSeparators) == 1 {
|
||||
domain.LocalpartCatchallSeparator = localpartCatchallSeparators[0]
|
||||
} else {
|
||||
domain.LocalpartCatchallSeparators = localpartCatchallSeparators
|
||||
}
|
||||
|
||||
domain.LocalpartCaseSensitive = localpartCaseSensitive
|
||||
return nil
|
||||
})
|
||||
|
@ -298,7 +298,7 @@ var api;
|
||||
"AutoconfCheckResult": { "Name": "AutoconfCheckResult", "Docs": "", "Fields": [{ "Name": "ClientSettingsDomainIPs", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "IPs", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Errors", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Warnings", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Instructions", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"AutodiscoverCheckResult": { "Name": "AutodiscoverCheckResult", "Docs": "", "Fields": [{ "Name": "Records", "Docs": "", "Typewords": ["[]", "AutodiscoverSRV"] }, { "Name": "Errors", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Warnings", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "Instructions", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"AutodiscoverSRV": { "Name": "AutodiscoverSRV", "Docs": "", "Fields": [{ "Name": "Target", "Docs": "", "Typewords": ["string"] }, { "Name": "Port", "Docs": "", "Typewords": ["uint16"] }, { "Name": "Priority", "Docs": "", "Typewords": ["uint16"] }, { "Name": "Weight", "Docs": "", "Typewords": ["uint16"] }, { "Name": "IPs", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"ConfigDomain": { "Name": "ConfigDomain", "Docs": "", "Fields": [{ "Name": "Disabled", "Docs": "", "Typewords": ["bool"] }, { "Name": "Description", "Docs": "", "Typewords": ["string"] }, { "Name": "ClientSettingsDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }, { "Name": "DKIM", "Docs": "", "Typewords": ["DKIM"] }, { "Name": "DMARC", "Docs": "", "Typewords": ["nullable", "DMARC"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["nullable", "MTASTS"] }, { "Name": "TLSRPT", "Docs": "", "Typewords": ["nullable", "TLSRPT"] }, { "Name": "Routes", "Docs": "", "Typewords": ["[]", "Route"] }, { "Name": "Aliases", "Docs": "", "Typewords": ["{}", "Alias"] }, { "Name": "Domain", "Docs": "", "Typewords": ["Domain"] }] },
|
||||
"ConfigDomain": { "Name": "ConfigDomain", "Docs": "", "Fields": [{ "Name": "Disabled", "Docs": "", "Typewords": ["bool"] }, { "Name": "Description", "Docs": "", "Typewords": ["string"] }, { "Name": "ClientSettingsDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCatchallSeparator", "Docs": "", "Typewords": ["string"] }, { "Name": "LocalpartCatchallSeparators", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "LocalpartCaseSensitive", "Docs": "", "Typewords": ["bool"] }, { "Name": "DKIM", "Docs": "", "Typewords": ["DKIM"] }, { "Name": "DMARC", "Docs": "", "Typewords": ["nullable", "DMARC"] }, { "Name": "MTASTS", "Docs": "", "Typewords": ["nullable", "MTASTS"] }, { "Name": "TLSRPT", "Docs": "", "Typewords": ["nullable", "TLSRPT"] }, { "Name": "Routes", "Docs": "", "Typewords": ["[]", "Route"] }, { "Name": "Aliases", "Docs": "", "Typewords": ["{}", "Alias"] }, { "Name": "Domain", "Docs": "", "Typewords": ["Domain"] }, { "Name": "LocalpartCatchallSeparatorsEffective", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"DKIM": { "Name": "DKIM", "Docs": "", "Fields": [{ "Name": "Selectors", "Docs": "", "Typewords": ["{}", "Selector"] }, { "Name": "Sign", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||
"Selector": { "Name": "Selector", "Docs": "", "Fields": [{ "Name": "Hash", "Docs": "", "Typewords": ["string"] }, { "Name": "HashEffective", "Docs": "", "Typewords": ["string"] }, { "Name": "Canonicalization", "Docs": "", "Typewords": ["Canonicalization"] }, { "Name": "Headers", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "HeadersEffective", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "DontSealHeaders", "Docs": "", "Typewords": ["bool"] }, { "Name": "Expiration", "Docs": "", "Typewords": ["string"] }, { "Name": "PrivateKeyFile", "Docs": "", "Typewords": ["string"] }, { "Name": "Algorithm", "Docs": "", "Typewords": ["string"] }] },
|
||||
"Canonicalization": { "Name": "Canonicalization", "Docs": "", "Fields": [{ "Name": "HeaderRelaxed", "Docs": "", "Typewords": ["bool"] }, { "Name": "BodyRelaxed", "Docs": "", "Typewords": ["bool"] }] },
|
||||
@ -1220,11 +1220,11 @@ var api;
|
||||
}
|
||||
// DomainLocalpartConfigSave saves the localpart catchall and case-sensitive
|
||||
// settings for a domain.
|
||||
async DomainLocalpartConfigSave(domainName, localpartCatchallSeparator, localpartCaseSensitive) {
|
||||
async DomainLocalpartConfigSave(domainName, localpartCatchallSeparators, localpartCaseSensitive) {
|
||||
const fn = "DomainLocalpartConfigSave";
|
||||
const paramTypes = [["string"], ["string"], ["bool"]];
|
||||
const paramTypes = [["string"], ["[]", "string"], ["bool"]];
|
||||
const returnTypes = [];
|
||||
const params = [domainName, localpartCatchallSeparator, localpartCaseSensitive];
|
||||
const params = [domainName, localpartCatchallSeparators, localpartCaseSensitive];
|
||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||
}
|
||||
// DomainDMARCAddressSave saves the DMARC reporting address/processing
|
||||
@ -2372,7 +2372,6 @@ const domain = async (d) => {
|
||||
let clientSettingsDomainFieldset;
|
||||
let clientSettingsDomain;
|
||||
let localpartFieldset;
|
||||
let localpartCatchallSeparator;
|
||||
let localpartCaseSensitive;
|
||||
let dmarcFieldset;
|
||||
let dmarcLocalpart;
|
||||
@ -2469,11 +2468,39 @@ const domain = async (d) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
await check(clientSettingsDomainFieldset, client.DomainClientSettingsDomainSave(d, clientSettingsDomain.value));
|
||||
}, clientSettingsDomainFieldset = dom.fieldset(style({ display: 'flex', gap: '1em' }), dom.label(attr.title('Hostname for client settings instead of the mail server hostname. E.g. mail.<domain>. For future migration to another mail operator without requiring all clients to update their settings, it is convenient to have client settings that reference a subdomain of the hosted domain instead of the hostname of the server where the mail is currently hosted. If empty, the hostname of the mail server is used for client configurations. Unicode name.'), dom.div('Client settings domain'), clientSettingsDomain = dom.input(attr.value(domainConfig.ClientSettingsDomain), style({ width: '30em' }))), dom.div(dom.span('\u00a0'), dom.div(dom.submitbutton('Save'))))), dom.form(style({ marginTop: '1ex' }), async function submit(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
await check(localpartFieldset, client.DomainLocalpartConfigSave(d, localpartCatchallSeparator.value, localpartCaseSensitive.checked));
|
||||
}, localpartFieldset = dom.fieldset(style({ display: 'flex', gap: '1em' }), dom.label(attr.title('If set, upper/lower case is relevant for email delivery.'), dom.div('Localpart case sensitive'), localpartCaseSensitive = dom.input(attr.type('checkbox'), domainConfig.LocalpartCaseSensitive ? attr.checked('') : [])), dom.label(attr.title('If not empty, only the string before the separator is used to for email delivery decisions. For example, if set to \"+\", you+anything@example.com will be delivered to you@example.com.'), dom.div('Localpart catchall separator'), localpartCatchallSeparator = dom.input(attr.value(domainConfig.LocalpartCatchallSeparator))), dom.div(dom.span('\u00a0'), dom.div(dom.submitbutton('Save'))))), dom.br(), dom.h2('DMARC reporting address'), dom.form(style({ marginTop: '1ex' }), async function submit(e) {
|
||||
}, clientSettingsDomainFieldset = dom.fieldset(style({ display: 'flex', gap: '1em' }), dom.label(attr.title('Hostname for client settings instead of the mail server hostname. E.g. mail.<domain>. For future migration to another mail operator without requiring all clients to update their settings, it is convenient to have client settings that reference a subdomain of the hosted domain instead of the hostname of the server where the mail is currently hosted. If empty, the hostname of the mail server is used for client configurations. Unicode name.'), dom.div('Client settings domain'), clientSettingsDomain = dom.input(attr.value(domainConfig.ClientSettingsDomain), style({ width: '30em' }))), dom.div(dom.span('\u00a0'), dom.div(dom.submitbutton('Save'))))), (() => {
|
||||
let separatorViews = [];
|
||||
let separatorsBox;
|
||||
const addSeparatorView = (s) => {
|
||||
const separator = dom.input(attr.required(''), attr.value(s), style({ width: '2em' }));
|
||||
const v = {
|
||||
separator: separator,
|
||||
root: dom.div(separator, ' ', dom.clickbutton('Remove', function click() {
|
||||
separatorViews.splice(separatorViews.indexOf(v), 1);
|
||||
v.root.remove();
|
||||
if (separatorViews.length === 0) {
|
||||
separatorsBox.append(dom.div('(None)'));
|
||||
}
|
||||
})),
|
||||
};
|
||||
if (separatorViews.length === 0) {
|
||||
dom._kids(separatorsBox);
|
||||
}
|
||||
separatorViews.push(v);
|
||||
separatorsBox.appendChild(v.root);
|
||||
};
|
||||
const elem = dom.form(style({ marginTop: '1ex' }), async function submit(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
await check(localpartFieldset, client.DomainLocalpartConfigSave(d, separatorViews.map(v => v.separator.value), localpartCaseSensitive.checked));
|
||||
}, localpartFieldset = dom.fieldset(style({ display: 'flex', gap: '1em' }), dom.label(attr.title('If set, upper/lower case is relevant for email delivery.'), dom.div('Localpart case sensitive'), localpartCaseSensitive = dom.input(attr.type('checkbox'), domainConfig.LocalpartCaseSensitive ? attr.checked('') : [])), dom.div(dom.label(attr.title('If not empty, only the string before the separator is used for email delivery decisions. For example, if set to \"+\", you+anything@example.com will be delivered to you@example.com.'), 'Localpart catchall separators'), ' ', dom.clickbutton('Add', function click() {
|
||||
addSeparatorView('');
|
||||
}), separatorsBox = dom.div(style({ display: 'flex', flexDirection: 'column', gap: '.25em' }), dom.div('(None)'))), dom.div(dom.span('\u00a0'), dom.div(dom.submitbutton('Save')))));
|
||||
for (const sep of (domainConfig.LocalpartCatchallSeparatorsEffective || [])) {
|
||||
addSeparatorView(sep);
|
||||
}
|
||||
return elem;
|
||||
})(), dom.br(), dom.h2('DMARC reporting address'), dom.form(style({ marginTop: '1ex' }), async function submit(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (!dmarcLocalpart.value) {
|
||||
|
@ -1243,7 +1243,6 @@ const domain = async (d: string) => {
|
||||
let clientSettingsDomain: HTMLInputElement
|
||||
|
||||
let localpartFieldset: HTMLFieldSetElement
|
||||
let localpartCatchallSeparator: HTMLInputElement
|
||||
let localpartCaseSensitive: HTMLInputElement
|
||||
|
||||
let dmarcFieldset: HTMLFieldSetElement
|
||||
@ -1588,28 +1587,68 @@ const domain = async (d: string) => {
|
||||
dom.div(dom.span('\u00a0'), dom.div(dom.submitbutton('Save'))),
|
||||
),
|
||||
),
|
||||
dom.form(
|
||||
style({marginTop: '1ex'}),
|
||||
async function submit(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
await check(localpartFieldset, client.DomainLocalpartConfigSave(d, localpartCatchallSeparator.value, localpartCaseSensitive.checked))
|
||||
},
|
||||
localpartFieldset=dom.fieldset(
|
||||
style({display: 'flex', gap: '1em'}),
|
||||
dom.label(
|
||||
attr.title('If set, upper/lower case is relevant for email delivery.'),
|
||||
dom.div('Localpart case sensitive'),
|
||||
localpartCaseSensitive=dom.input(attr.type('checkbox'), domainConfig.LocalpartCaseSensitive ? attr.checked('') : []),
|
||||
(() => {
|
||||
interface SeparatorView {
|
||||
root: HTMLElement
|
||||
separator: HTMLInputElement
|
||||
}
|
||||
let separatorViews: SeparatorView[] = []
|
||||
let separatorsBox: HTMLDivElement
|
||||
|
||||
const addSeparatorView = (s: string) => {
|
||||
const separator = dom.input(attr.required(''), attr.value(s), style({width: '2em'}))
|
||||
const v = {
|
||||
separator: separator,
|
||||
root: dom.div(
|
||||
separator, ' ',
|
||||
dom.clickbutton('Remove', function click() {
|
||||
separatorViews.splice(separatorViews.indexOf(v), 1)
|
||||
v.root.remove()
|
||||
if (separatorViews.length === 0) {
|
||||
separatorsBox.append(dom.div('(None)'))
|
||||
}
|
||||
}),
|
||||
),
|
||||
}
|
||||
if (separatorViews.length === 0) {
|
||||
dom._kids(separatorsBox)
|
||||
}
|
||||
separatorViews.push(v)
|
||||
separatorsBox.appendChild(v.root)
|
||||
}
|
||||
|
||||
const elem = dom.form(
|
||||
style({marginTop: '1ex'}),
|
||||
async function submit(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
await check(localpartFieldset, client.DomainLocalpartConfigSave(d, separatorViews.map(v => v.separator.value), localpartCaseSensitive.checked))
|
||||
},
|
||||
localpartFieldset=dom.fieldset(
|
||||
style({display: 'flex', gap: '1em'}),
|
||||
dom.label(
|
||||
attr.title('If set, upper/lower case is relevant for email delivery.'),
|
||||
dom.div('Localpart case sensitive'),
|
||||
localpartCaseSensitive=dom.input(attr.type('checkbox'), domainConfig.LocalpartCaseSensitive ? attr.checked('') : []),
|
||||
),
|
||||
dom.div(
|
||||
dom.label(
|
||||
attr.title('If not empty, only the string before the separator is used for email delivery decisions. For example, if set to \"+\", you+anything@example.com will be delivered to you@example.com.'),
|
||||
'Localpart catchall separators',
|
||||
), ' ',
|
||||
dom.clickbutton('Add', function click() {
|
||||
addSeparatorView('')
|
||||
}),
|
||||
separatorsBox=dom.div(style({display: 'flex', flexDirection: 'column', gap: '.25em'}), dom.div('(None)')),
|
||||
),
|
||||
dom.div(dom.span('\u00a0'), dom.div(dom.submitbutton('Save'))),
|
||||
),
|
||||
dom.label(
|
||||
attr.title('If not empty, only the string before the separator is used to for email delivery decisions. For example, if set to \"+\", you+anything@example.com will be delivered to you@example.com.'),
|
||||
dom.div('Localpart catchall separator'),
|
||||
localpartCatchallSeparator=dom.input(attr.value(domainConfig.LocalpartCatchallSeparator)),
|
||||
),
|
||||
dom.div(dom.span('\u00a0'), dom.div(dom.submitbutton('Save'))),
|
||||
),
|
||||
),
|
||||
)
|
||||
for (const sep of (domainConfig.LocalpartCatchallSeparatorsEffective || [])) {
|
||||
addSeparatorView(sep)
|
||||
}
|
||||
return elem
|
||||
})(),
|
||||
dom.br(),
|
||||
|
||||
dom.h2('DMARC reporting address'),
|
||||
|
@ -277,9 +277,9 @@ func TestAdmin(t *testing.T) {
|
||||
tneedErrorCode(t, "user:error", func() { api.DomainClientSettingsDomainSave(ctxbg, "bogus.example", "unknown.example") })
|
||||
api.DomainClientSettingsDomainSave(ctxbg, "mox.example", "") // Restore.
|
||||
|
||||
api.DomainLocalpartConfigSave(ctxbg, "mox.example", "-", true)
|
||||
tneedErrorCode(t, "user:error", func() { api.DomainLocalpartConfigSave(ctxbg, "bogus.example", "", false) })
|
||||
api.DomainLocalpartConfigSave(ctxbg, "mox.example", "", false) // Restore.
|
||||
api.DomainLocalpartConfigSave(ctxbg, "mox.example", []string{"-"}, true)
|
||||
tneedErrorCode(t, "user:error", func() { api.DomainLocalpartConfigSave(ctxbg, "bogus.example", nil, false) })
|
||||
api.DomainLocalpartConfigSave(ctxbg, "mox.example", nil, false) // Restore.
|
||||
|
||||
api.DomainDMARCAddressSave(ctxbg, "mox.example", "dmarc-reports", "", "mjl", "DMARC")
|
||||
tneedErrorCode(t, "user:error", func() { api.DomainDMARCAddressSave(ctxbg, "bogus.example", "dmarc-reports", "", "mjl", "DMARC") })
|
||||
|
@ -1710,8 +1710,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "localpartCatchallSeparator",
|
||||
"Name": "localpartCatchallSeparators",
|
||||
"Typewords": [
|
||||
"[]",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
@ -3441,6 +3442,14 @@
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LocalpartCatchallSeparators",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"[]",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LocalpartCaseSensitive",
|
||||
"Docs": "",
|
||||
@ -3501,6 +3510,14 @@
|
||||
"Typewords": [
|
||||
"Domain"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LocalpartCatchallSeparatorsEffective",
|
||||
"Docs": "Either LocalpartCatchallSeparators, the value of LocalpartCatchallSeparator, or empty.",
|
||||
"Typewords": [
|
||||
"[]",
|
||||
"string"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -270,6 +270,7 @@ export interface ConfigDomain {
|
||||
Description: string
|
||||
ClientSettingsDomain: string
|
||||
LocalpartCatchallSeparator: string
|
||||
LocalpartCatchallSeparators?: string[] | null
|
||||
LocalpartCaseSensitive: boolean
|
||||
DKIM: DKIM
|
||||
DMARC?: DMARC | null
|
||||
@ -278,6 +279,7 @@ export interface ConfigDomain {
|
||||
Routes?: Route[] | null
|
||||
Aliases?: { [key: string]: Alias }
|
||||
Domain: Domain
|
||||
LocalpartCatchallSeparatorsEffective?: string[] | null // Either LocalpartCatchallSeparators, the value of LocalpartCatchallSeparator, or empty.
|
||||
}
|
||||
|
||||
export interface DKIM {
|
||||
@ -1184,7 +1186,7 @@ export const types: TypenameMap = {
|
||||
"AutoconfCheckResult": {"Name":"AutoconfCheckResult","Docs":"","Fields":[{"Name":"ClientSettingsDomainIPs","Docs":"","Typewords":["[]","string"]},{"Name":"IPs","Docs":"","Typewords":["[]","string"]},{"Name":"Errors","Docs":"","Typewords":["[]","string"]},{"Name":"Warnings","Docs":"","Typewords":["[]","string"]},{"Name":"Instructions","Docs":"","Typewords":["[]","string"]}]},
|
||||
"AutodiscoverCheckResult": {"Name":"AutodiscoverCheckResult","Docs":"","Fields":[{"Name":"Records","Docs":"","Typewords":["[]","AutodiscoverSRV"]},{"Name":"Errors","Docs":"","Typewords":["[]","string"]},{"Name":"Warnings","Docs":"","Typewords":["[]","string"]},{"Name":"Instructions","Docs":"","Typewords":["[]","string"]}]},
|
||||
"AutodiscoverSRV": {"Name":"AutodiscoverSRV","Docs":"","Fields":[{"Name":"Target","Docs":"","Typewords":["string"]},{"Name":"Port","Docs":"","Typewords":["uint16"]},{"Name":"Priority","Docs":"","Typewords":["uint16"]},{"Name":"Weight","Docs":"","Typewords":["uint16"]},{"Name":"IPs","Docs":"","Typewords":["[]","string"]}]},
|
||||
"ConfigDomain": {"Name":"ConfigDomain","Docs":"","Fields":[{"Name":"Disabled","Docs":"","Typewords":["bool"]},{"Name":"Description","Docs":"","Typewords":["string"]},{"Name":"ClientSettingsDomain","Docs":"","Typewords":["string"]},{"Name":"LocalpartCatchallSeparator","Docs":"","Typewords":["string"]},{"Name":"LocalpartCaseSensitive","Docs":"","Typewords":["bool"]},{"Name":"DKIM","Docs":"","Typewords":["DKIM"]},{"Name":"DMARC","Docs":"","Typewords":["nullable","DMARC"]},{"Name":"MTASTS","Docs":"","Typewords":["nullable","MTASTS"]},{"Name":"TLSRPT","Docs":"","Typewords":["nullable","TLSRPT"]},{"Name":"Routes","Docs":"","Typewords":["[]","Route"]},{"Name":"Aliases","Docs":"","Typewords":["{}","Alias"]},{"Name":"Domain","Docs":"","Typewords":["Domain"]}]},
|
||||
"ConfigDomain": {"Name":"ConfigDomain","Docs":"","Fields":[{"Name":"Disabled","Docs":"","Typewords":["bool"]},{"Name":"Description","Docs":"","Typewords":["string"]},{"Name":"ClientSettingsDomain","Docs":"","Typewords":["string"]},{"Name":"LocalpartCatchallSeparator","Docs":"","Typewords":["string"]},{"Name":"LocalpartCatchallSeparators","Docs":"","Typewords":["[]","string"]},{"Name":"LocalpartCaseSensitive","Docs":"","Typewords":["bool"]},{"Name":"DKIM","Docs":"","Typewords":["DKIM"]},{"Name":"DMARC","Docs":"","Typewords":["nullable","DMARC"]},{"Name":"MTASTS","Docs":"","Typewords":["nullable","MTASTS"]},{"Name":"TLSRPT","Docs":"","Typewords":["nullable","TLSRPT"]},{"Name":"Routes","Docs":"","Typewords":["[]","Route"]},{"Name":"Aliases","Docs":"","Typewords":["{}","Alias"]},{"Name":"Domain","Docs":"","Typewords":["Domain"]},{"Name":"LocalpartCatchallSeparatorsEffective","Docs":"","Typewords":["[]","string"]}]},
|
||||
"DKIM": {"Name":"DKIM","Docs":"","Fields":[{"Name":"Selectors","Docs":"","Typewords":["{}","Selector"]},{"Name":"Sign","Docs":"","Typewords":["[]","string"]}]},
|
||||
"Selector": {"Name":"Selector","Docs":"","Fields":[{"Name":"Hash","Docs":"","Typewords":["string"]},{"Name":"HashEffective","Docs":"","Typewords":["string"]},{"Name":"Canonicalization","Docs":"","Typewords":["Canonicalization"]},{"Name":"Headers","Docs":"","Typewords":["[]","string"]},{"Name":"HeadersEffective","Docs":"","Typewords":["[]","string"]},{"Name":"DontSealHeaders","Docs":"","Typewords":["bool"]},{"Name":"Expiration","Docs":"","Typewords":["string"]},{"Name":"PrivateKeyFile","Docs":"","Typewords":["string"]},{"Name":"Algorithm","Docs":"","Typewords":["string"]}]},
|
||||
"Canonicalization": {"Name":"Canonicalization","Docs":"","Fields":[{"Name":"HeaderRelaxed","Docs":"","Typewords":["bool"]},{"Name":"BodyRelaxed","Docs":"","Typewords":["bool"]}]},
|
||||
@ -2194,11 +2196,11 @@ export class Client {
|
||||
|
||||
// DomainLocalpartConfigSave saves the localpart catchall and case-sensitive
|
||||
// settings for a domain.
|
||||
async DomainLocalpartConfigSave(domainName: string, localpartCatchallSeparator: string, localpartCaseSensitive: boolean): Promise<void> {
|
||||
async DomainLocalpartConfigSave(domainName: string, localpartCatchallSeparators: string[] | null, localpartCaseSensitive: boolean): Promise<void> {
|
||||
const fn: string = "DomainLocalpartConfigSave"
|
||||
const paramTypes: string[][] = [["string"],["string"],["bool"]]
|
||||
const paramTypes: string[][] = [["string"],["[]","string"],["bool"]]
|
||||
const returnTypes: string[][] = []
|
||||
const params: any[] = [domainName, localpartCatchallSeparator, localpartCaseSensitive]
|
||||
const params: any[] = [domainName, localpartCatchallSeparators, localpartCaseSensitive]
|
||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as void
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user