mirror of
https://github.com/mjl-/mox.git
synced 2024-12-27 08:53:48 +03:00
webadmin: make routes configurable: globally, per domain, per account
this simplifies some of the code that makes modifications to the config file. a few protected functions can make changes to the dynamic config, which webadmin can use. instead of having separate functions in mox-/admin.go for each type of change. this also exports the parsed full dynamic config to webadmin, so we need fewer functions for specific config fields too.
This commit is contained in:
parent
baf4df55a6
commit
a69887bfab
19 changed files with 1165 additions and 189 deletions
2
Makefile
2
Makefile
|
@ -7,7 +7,7 @@ build0:
|
||||||
CGO_ENABLED=0 go build
|
CGO_ENABLED=0 go build
|
||||||
CGO_ENABLED=0 go vet ./...
|
CGO_ENABLED=0 go vet ./...
|
||||||
./gendoc.sh
|
./gendoc.sh
|
||||||
(cd webadmin && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Admin) >webadmin/api.json
|
(cd webadmin && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none -rename 'config Domain ConfigDomain' Admin) >webadmin/api.json
|
||||||
(cd webaccount && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Account) >webaccount/api.json
|
(cd webaccount && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Account) >webaccount/api.json
|
||||||
(cd webmail && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Webmail) >webmail/api.json
|
(cd webmail && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Webmail) >webmail/api.json
|
||||||
./gents.sh webadmin/api.json webadmin/api.ts
|
./gents.sh webadmin/api.json webadmin/api.ts
|
||||||
|
|
|
@ -320,13 +320,15 @@ type TLSRPT struct {
|
||||||
DNSDomain dns.Domain `sconf:"-"` // Effective domain, always set based on Domain field or Domain where this is configured.
|
DNSDomain dns.Domain `sconf:"-"` // Effective domain, always set based on Domain field or Domain where this is configured.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Canonicalization struct {
|
||||||
|
HeaderRelaxed bool `sconf-doc:"If set, some modifications to the headers (mostly whitespace) are allowed."`
|
||||||
|
BodyRelaxed bool `sconf-doc:"If set, some whitespace modifications to the message body are allowed."`
|
||||||
|
}
|
||||||
|
|
||||||
type Selector struct {
|
type Selector struct {
|
||||||
Hash string `sconf:"optional" sconf-doc:"sha256 (default) or (older, not recommended) sha1"`
|
Hash string `sconf:"optional" sconf-doc:"sha256 (default) or (older, not recommended) sha1"`
|
||||||
HashEffective string `sconf:"-"`
|
HashEffective string `sconf:"-"`
|
||||||
Canonicalization struct {
|
Canonicalization Canonicalization `sconf:"optional"`
|
||||||
HeaderRelaxed bool `sconf-doc:"If set, some modifications to the headers (mostly whitespace) are allowed."`
|
|
||||||
BodyRelaxed bool `sconf-doc:"If set, some whitespace modifications to the message body are allowed."`
|
|
||||||
} `sconf:"optional"`
|
|
||||||
Headers []string `sconf:"optional" sconf-doc:"Headers to sign with DKIM. If empty, a reasonable default set of headers is selected."`
|
Headers []string `sconf:"optional" sconf-doc:"Headers to sign with DKIM. If empty, a reasonable default set of headers is selected."`
|
||||||
HeadersEffective []string `sconf:"-"` // Used when signing. Based on Headers from config, or the reasonable default.
|
HeadersEffective []string `sconf:"-"` // Used when signing. Based on Headers from config, or the reasonable default.
|
||||||
DontSealHeaders bool `sconf:"optional" sconf-doc:"If set, don't prevent duplicate headers from being added. Not recommended."`
|
DontSealHeaders bool `sconf:"optional" sconf-doc:"If set, don't prevent duplicate headers from being added. Not recommended."`
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -8,7 +8,7 @@ require (
|
||||||
github.com/mjl-/bstore v0.0.5
|
github.com/mjl-/bstore v0.0.5
|
||||||
github.com/mjl-/sconf v0.0.6
|
github.com/mjl-/sconf v0.0.6
|
||||||
github.com/mjl-/sherpa v0.6.7
|
github.com/mjl-/sherpa v0.6.7
|
||||||
github.com/mjl-/sherpadoc v0.0.13
|
github.com/mjl-/sherpadoc v0.0.14
|
||||||
github.com/mjl-/sherpaprom v0.0.2
|
github.com/mjl-/sherpaprom v0.0.2
|
||||||
github.com/mjl-/sherpats v0.0.6
|
github.com/mjl-/sherpats v0.0.6
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.18.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -35,8 +35,8 @@ github.com/mjl-/sconf v0.0.6/go.mod h1:uF8OdWtLT8La3i4ln176i1pB0ps9pXGCaABEU55Zk
|
||||||
github.com/mjl-/sherpa v0.6.7 h1:C5F8XQdV5nCuS4fvB+ye/ziUQrajEhOoj/t2w5T14BY=
|
github.com/mjl-/sherpa v0.6.7 h1:C5F8XQdV5nCuS4fvB+ye/ziUQrajEhOoj/t2w5T14BY=
|
||||||
github.com/mjl-/sherpa v0.6.7/go.mod h1:dSpAOdgpwdqQZ72O4n3EHo/tR68eKyan8tYYraUMPNc=
|
github.com/mjl-/sherpa v0.6.7/go.mod h1:dSpAOdgpwdqQZ72O4n3EHo/tR68eKyan8tYYraUMPNc=
|
||||||
github.com/mjl-/sherpadoc v0.0.0-20190505200843-c0a7f43f5f1d/go.mod h1:5khTKxoKKNXcB8bkVUO6GlzC7PFtMmkHq578lPbmnok=
|
github.com/mjl-/sherpadoc v0.0.0-20190505200843-c0a7f43f5f1d/go.mod h1:5khTKxoKKNXcB8bkVUO6GlzC7PFtMmkHq578lPbmnok=
|
||||||
github.com/mjl-/sherpadoc v0.0.13 h1:Rem75lUlFsgX6TPTdtBxskY/Ze/yivaRkFw1H1MUmFw=
|
github.com/mjl-/sherpadoc v0.0.14 h1:Xrdg8RhAmTDQXlEU+qDSlige4zfhMHr+VKBJNpPeWe4=
|
||||||
github.com/mjl-/sherpadoc v0.0.13/go.mod h1:vh5zcsk3j/Tvm725EY+unTZb3EZcZcpiEQzrODSa6+I=
|
github.com/mjl-/sherpadoc v0.0.14/go.mod h1:vh5zcsk3j/Tvm725EY+unTZb3EZcZcpiEQzrODSa6+I=
|
||||||
github.com/mjl-/sherpaprom v0.0.2 h1:1dlbkScsNafM5jURI44uiWrZMSwfZtcOFEEq7vx2C1Y=
|
github.com/mjl-/sherpaprom v0.0.2 h1:1dlbkScsNafM5jURI44uiWrZMSwfZtcOFEEq7vx2C1Y=
|
||||||
github.com/mjl-/sherpaprom v0.0.2/go.mod h1:cl5nMNOvqhzMiQJ2FzccQ9ReivjHXe53JhOVkPfSvw4=
|
github.com/mjl-/sherpaprom v0.0.2/go.mod h1:cl5nMNOvqhzMiQJ2FzccQ9ReivjHXe53JhOVkPfSvw4=
|
||||||
github.com/mjl-/sherpats v0.0.6 h1:2lSoJbb+jkjLOdlvoMxItq0QQrrnkH+rnm3PMRfpbmA=
|
github.com/mjl-/sherpats v0.0.6 h1:2lSoJbb+jkjLOdlvoMxItq0QQrrnkH+rnm3PMRfpbmA=
|
||||||
|
|
|
@ -47,7 +47,9 @@ func recvid(r *http.Request) string {
|
||||||
// If no handler matched, false is returned.
|
// If no handler matched, false is returned.
|
||||||
// WebHandle sets w.Name to that of the matching handler.
|
// WebHandle sets w.Name to that of the matching handler.
|
||||||
func WebHandle(w *loggingWriter, r *http.Request, host dns.Domain) (handled bool) {
|
func WebHandle(w *loggingWriter, r *http.Request, host dns.Domain) (handled bool) {
|
||||||
redirects, handlers := mox.Conf.WebServer()
|
conf := mox.Conf.DynamicConfig()
|
||||||
|
redirects := conf.WebDNSDomainRedirects
|
||||||
|
handlers := conf.WebHandlers
|
||||||
|
|
||||||
for from, to := range redirects {
|
for from, to := range redirects {
|
||||||
if host != from {
|
if host != from {
|
||||||
|
|
|
@ -430,28 +430,68 @@ func DomainRemove(ctx context.Context, domain dns.Domain) (rerr error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func WebserverConfigSet(ctx context.Context, domainRedirects map[string]string, webhandlers []config.WebHandler) (rerr error) {
|
// DomainSave calls xmodify with a shallow copy of the domain config. xmodify
|
||||||
|
// can modify the config, but must clone all referencing data it changes.
|
||||||
|
// xmodify may employ panic-based error handling. After xmodify returns, the
|
||||||
|
// modified config is verified, saved and takes effect.
|
||||||
|
func DomainSave(ctx context.Context, domainName string, xmodify func(config *config.Domain)) (rerr error) {
|
||||||
log := pkglog.WithContext(ctx)
|
log := pkglog.WithContext(ctx)
|
||||||
defer func() {
|
defer func() {
|
||||||
if rerr != nil {
|
if rerr != nil {
|
||||||
log.Errorx("saving webserver config", rerr)
|
log.Errorx("saving domain config", rerr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
Conf.dynamicMutex.Lock()
|
Conf.dynamicMutex.Lock()
|
||||||
defer Conf.dynamicMutex.Unlock()
|
defer Conf.dynamicMutex.Unlock()
|
||||||
|
|
||||||
// Compose new config without modifying existing data structures. If we fail, we
|
nc := Conf.Dynamic // Shallow copy.
|
||||||
// leave no trace.
|
dom, ok := nc.Domains[domainName] // dom is a shallow copy.
|
||||||
nc := Conf.Dynamic
|
if !ok {
|
||||||
nc.WebDomainRedirects = domainRedirects
|
return fmt.Errorf("domain not present")
|
||||||
nc.WebHandlers = webhandlers
|
|
||||||
|
|
||||||
if err := writeDynamic(ctx, log, nc); err != nil {
|
|
||||||
return fmt.Errorf("writing domains.conf: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("webserver config saved")
|
xmodify(&dom)
|
||||||
|
|
||||||
|
// Compose new config without modifying existing data structures. If we fail, we
|
||||||
|
// leave no trace.
|
||||||
|
nc.Domains = map[string]config.Domain{}
|
||||||
|
for name, d := range Conf.Dynamic.Domains {
|
||||||
|
nc.Domains[name] = d
|
||||||
|
}
|
||||||
|
nc.Domains[domainName] = dom
|
||||||
|
|
||||||
|
if err := writeDynamic(ctx, log, nc); err != nil {
|
||||||
|
return fmt.Errorf("writing domains.conf: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("domain saved")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigSave calls xmodify with a shallow copy of the dynamic config. xmodify
|
||||||
|
// can modify the config, but must clone all referencing data it changes.
|
||||||
|
// xmodify may employ panic-based error handling. After xmodify returns, the
|
||||||
|
// modified config is verified, saved and takes effect.
|
||||||
|
func ConfigSave(ctx context.Context, xmodify func(config *config.Dynamic)) (rerr error) {
|
||||||
|
log := pkglog.WithContext(ctx)
|
||||||
|
defer func() {
|
||||||
|
if rerr != nil {
|
||||||
|
log.Errorx("saving config", rerr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
Conf.dynamicMutex.Lock()
|
||||||
|
defer Conf.dynamicMutex.Unlock()
|
||||||
|
|
||||||
|
nc := Conf.Dynamic // Shallow copy.
|
||||||
|
xmodify(&nc)
|
||||||
|
|
||||||
|
if err := writeDynamic(ctx, log, nc); err != nil {
|
||||||
|
return fmt.Errorf("writing domains.conf: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("config saved")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,7 +814,7 @@ func AccountAdd(ctx context.Context, account, address string) (rerr error) {
|
||||||
nc.Accounts[account] = MakeAccountConfig(addr)
|
nc.Accounts[account] = MakeAccountConfig(addr)
|
||||||
|
|
||||||
if err := writeDynamic(ctx, log, nc); err != nil {
|
if err := writeDynamic(ctx, log, nc); err != nil {
|
||||||
return fmt.Errorf("writing domains.conf: %v", err)
|
return fmt.Errorf("writing domains.conf: %w", err)
|
||||||
}
|
}
|
||||||
log.Info("account added", slog.String("account", account), slog.Any("address", addr))
|
log.Info("account added", slog.String("account", account), slog.Any("address", addr))
|
||||||
return nil
|
return nil
|
||||||
|
@ -808,7 +848,7 @@ func AccountRemove(ctx context.Context, account string) (rerr error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writeDynamic(ctx, log, nc); err != nil {
|
if err := writeDynamic(ctx, log, nc); err != nil {
|
||||||
return fmt.Errorf("writing domains.conf: %v", err)
|
return fmt.Errorf("writing domains.conf: %w", err)
|
||||||
}
|
}
|
||||||
log.Info("account removed", slog.String("account", account))
|
log.Info("account removed", slog.String("account", account))
|
||||||
return nil
|
return nil
|
||||||
|
@ -892,7 +932,7 @@ func AddressAdd(ctx context.Context, address, account string) (rerr error) {
|
||||||
nc.Accounts[account] = a
|
nc.Accounts[account] = a
|
||||||
|
|
||||||
if err := writeDynamic(ctx, log, nc); err != nil {
|
if err := writeDynamic(ctx, log, nc); err != nil {
|
||||||
return fmt.Errorf("writing domains.conf: %v", err)
|
return fmt.Errorf("writing domains.conf: %w", err)
|
||||||
}
|
}
|
||||||
log.Info("address added", slog.String("address", address), slog.String("account", account))
|
log.Info("address added", slog.String("address", address), slog.String("account", account))
|
||||||
return nil
|
return nil
|
||||||
|
@ -989,7 +1029,7 @@ func AddressRemove(ctx context.Context, address string) (rerr error) {
|
||||||
nc.Accounts[ad.Account] = na
|
nc.Accounts[ad.Account] = na
|
||||||
|
|
||||||
if err := writeDynamic(ctx, log, nc); err != nil {
|
if err := writeDynamic(ctx, log, nc); err != nil {
|
||||||
return fmt.Errorf("writing domains.conf: %v", err)
|
return fmt.Errorf("writing domains.conf: %w", err)
|
||||||
}
|
}
|
||||||
log.Info("address removed", slog.String("address", address), slog.String("account", ad.Account))
|
log.Info("address removed", slog.String("address", address), slog.String("account", ad.Account))
|
||||||
return nil
|
return nil
|
||||||
|
@ -1035,35 +1075,6 @@ func AccountSave(ctx context.Context, account string, xmodify func(acc *config.A
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonitorDNSBLsSave(ctx context.Context, zones []dns.Domain) (rerr error) {
|
|
||||||
log := pkglog.WithContext(ctx)
|
|
||||||
defer func() {
|
|
||||||
if rerr != nil {
|
|
||||||
log.Errorx("saving monitor dnsbl zones", rerr)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
Conf.dynamicMutex.Lock()
|
|
||||||
defer Conf.dynamicMutex.Unlock()
|
|
||||||
|
|
||||||
c := Conf.Dynamic
|
|
||||||
|
|
||||||
// Compose new config without modifying existing data structures. If we fail, we
|
|
||||||
// leave no trace.
|
|
||||||
nc := c
|
|
||||||
nc.MonitorDNSBLs = make([]string, len(zones))
|
|
||||||
nc.MonitorDNSBLZones = nil
|
|
||||||
for i, z := range zones {
|
|
||||||
nc.MonitorDNSBLs[i] = z.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := writeDynamic(ctx, log, nc); err != nil {
|
|
||||||
return fmt.Errorf("writing domains.conf: %v", err)
|
|
||||||
}
|
|
||||||
log.Info("monitor dnsbl zones saved")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type TLSMode uint8
|
type TLSMode uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -163,6 +163,14 @@ func (c *Config) loadDynamic() []error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DynamicConfig returns a shallow copy of the dynamic config. Must not be modified.
|
||||||
|
func (c *Config) DynamicConfig() (config config.Dynamic) {
|
||||||
|
c.withDynamicLock(func() {
|
||||||
|
config = c.Dynamic // Shallow copy.
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) Domains() (l []string) {
|
func (c *Config) Domains() (l []string) {
|
||||||
c.withDynamicLock(func() {
|
c.withDynamicLock(func() {
|
||||||
for name := range c.Dynamic.Domains {
|
for name := range c.Dynamic.Domains {
|
||||||
|
@ -224,14 +232,6 @@ func (c *Config) AccountDestination(addr string) (accDests AccountDestination, o
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WebServer() (r map[dns.Domain]dns.Domain, l []config.WebHandler) {
|
|
||||||
c.withDynamicLock(func() {
|
|
||||||
r = c.Dynamic.WebDNSDomainRedirects
|
|
||||||
l = c.Dynamic.WebHandlers
|
|
||||||
})
|
|
||||||
return r, l
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Routes(accountName string, domain dns.Domain) (accountRoutes, domainRoutes, globalRoutes []config.Route) {
|
func (c *Config) Routes(accountName string, domain dns.Domain) (accountRoutes, domainRoutes, globalRoutes []config.Route) {
|
||||||
c.withDynamicLock(func() {
|
c.withDynamicLock(func() {
|
||||||
acc := c.Dynamic.Accounts[accountName]
|
acc := c.Dynamic.Accounts[accountName]
|
||||||
|
@ -245,13 +245,6 @@ func (c *Config) Routes(accountName string, domain dns.Domain) (accountRoutes, d
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) MonitorDNSBLs() (zones []dns.Domain) {
|
|
||||||
c.withDynamicLock(func() {
|
|
||||||
zones = c.Dynamic.MonitorDNSBLZones
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) allowACMEHosts(log mlog.Log, checkACMEHosts bool) {
|
func (c *Config) allowACMEHosts(log mlog.Log, checkACMEHosts bool) {
|
||||||
for _, l := range c.Static.Listeners {
|
for _, l := range c.Static.Listeners {
|
||||||
if l.TLS == nil || l.TLS.ACME == "" {
|
if l.TLS == nil || l.TLS.ACME == "" {
|
||||||
|
|
|
@ -86,7 +86,8 @@ func monitorDNSBL(log mlog.Log) {
|
||||||
|
|
||||||
// Gather zones.
|
// Gather zones.
|
||||||
zones := append([]dns.Domain{}, publicListener.SMTP.DNSBLZones...)
|
zones := append([]dns.Domain{}, publicListener.SMTP.DNSBLZones...)
|
||||||
for _, zone := range mox.Conf.MonitorDNSBLs() {
|
conf := mox.Conf.DynamicConfig()
|
||||||
|
for _, zone := range conf.MonitorDNSBLZones {
|
||||||
if !slices.Contains(zones, zone) {
|
if !slices.Contains(zones, zone) {
|
||||||
zones = append(zones, zone)
|
zones = append(zones, zone)
|
||||||
}
|
}
|
||||||
|
|
5
testdata/webadmin/mox.conf
vendored
5
testdata/webadmin/mox.conf
vendored
|
@ -10,3 +10,8 @@ Listeners:
|
||||||
Postmaster:
|
Postmaster:
|
||||||
Account: mjl
|
Account: mjl
|
||||||
Mailbox: postmaster
|
Mailbox: postmaster
|
||||||
|
|
||||||
|
Transports:
|
||||||
|
direct:
|
||||||
|
Direct:
|
||||||
|
DisableIPv6: true
|
||||||
|
|
4
vendor/github.com/mjl-/sherpadoc/README.txt
generated
vendored
4
vendor/github.com/mjl-/sherpadoc/README.txt
generated
vendored
|
@ -17,8 +17,8 @@ MIT-licensed, see LICENSE.
|
||||||
- major cleanup required. too much parsing is done that can probably be handled by the go/* packages.
|
- major cleanup required. too much parsing is done that can probably be handled by the go/* packages.
|
||||||
- check that all cases of embedding work (seems like we will include duplicates: when a struct has fields that override an embedded struct, we generate duplicate fields).
|
- check that all cases of embedding work (seems like we will include duplicates: when a struct has fields that override an embedded struct, we generate duplicate fields).
|
||||||
- check that all cross-package referencing (ast.SelectorExpr) works
|
- check that all cross-package referencing (ast.SelectorExpr) works
|
||||||
- better cli syntax for replacements, and always replace based on fully qualified names. currently you need to specify both the fully qualified and unqualified type paths.
|
- better cli syntax for replacements and renames, and always replace based on fully qualified names. currently you need to specify both the fully qualified and unqualified type paths.
|
||||||
- see if order of items in output depends on a map somewhere, i've seen diffs for generated jsons where a type was only moved, not modified.
|
- see if order of items in output depends on a map somewhere, i've seen diffs for generated jsons where a type was only moved, not modified. perhaps the type was discovered earlier/later because of other type changes. we may want to sort sections,methods,types in the output.
|
||||||
- better error messages and error handling, stricter parsing
|
- better error messages and error handling, stricter parsing
|
||||||
- support type aliases
|
- support type aliases
|
||||||
- support plain iota enums? currently only simple literals are supported for enums.
|
- support plain iota enums? currently only simple literals are supported for enums.
|
||||||
|
|
30
vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/main.go
generated
vendored
30
vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/main.go
generated
vendored
|
@ -56,6 +56,7 @@ import (
|
||||||
var (
|
var (
|
||||||
packagePath = flag.String("package-path", ".", "of source code to parse")
|
packagePath = flag.String("package-path", ".", "of source code to parse")
|
||||||
replace = flag.String("replace", "", "comma-separated list of type replacements, e.g. \"somepkg.SomeType string\"")
|
replace = flag.String("replace", "", "comma-separated list of type replacements, e.g. \"somepkg.SomeType string\"")
|
||||||
|
rename = flag.String("rename", "", "comma-separated list of type renames as used with a package selector, e.g. \"somepkg SomeName OtherName\"")
|
||||||
title = flag.String("title", "", "title of the API, default is the name of the type of the main API")
|
title = flag.String("title", "", "title of the API, default is the name of the type of the main API")
|
||||||
adjustFunctionNames = flag.String("adjust-function-names", "", `by default, the first character of function names is turned into lower case; with "lowerWord" the first string of upper case characters is lower cased, with "none" the name is left as is`)
|
adjustFunctionNames = flag.String("adjust-function-names", "", `by default, the first character of function names is turned into lower case; with "lowerWord" the first string of upper case characters is lower cased, with "none" the name is left as is`)
|
||||||
)
|
)
|
||||||
|
@ -140,6 +141,13 @@ func check(err error, action string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type renameSrc struct {
|
||||||
|
Pkg string // Package selector, not full path at the moment.
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
var renames = map[renameSrc]string{}
|
||||||
|
|
||||||
func usage() {
|
func usage() {
|
||||||
log.Println("usage: sherpadoc [flags] section")
|
log.Println("usage: sherpadoc [flags] section")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
|
@ -155,6 +163,28 @@ func main() {
|
||||||
usage()
|
usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *rename != "" {
|
||||||
|
to := map[string]bool{} // Track target names, for detecting duplicates.
|
||||||
|
for _, elem := range strings.Split(*rename, ",") {
|
||||||
|
l := strings.Split(elem, " ")
|
||||||
|
if len(l) != 3 {
|
||||||
|
log.Printf("invalid rename %q", elem)
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
src := renameSrc{l[0], l[1]}
|
||||||
|
if _, ok := renames[src]; ok {
|
||||||
|
log.Printf("duplicate rename %q", elem)
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
if to[l[2]] {
|
||||||
|
log.Printf("duplicate rename type %q", l[2])
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
to[l[2]] = true
|
||||||
|
renames[src] = l[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If vendor exists, we load packages from it.
|
// If vendor exists, we load packages from it.
|
||||||
for dir, _ := os.Getwd(); dir != "" && dir != "/"; dir = filepath.Dir(dir) {
|
for dir, _ := os.Getwd(); dir != "" && dir != "/"; dir = filepath.Dir(dir) {
|
||||||
p := filepath.Join(dir, "go.mod")
|
p := filepath.Join(dir, "go.mod")
|
||||||
|
|
26
vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/parse.go
generated
vendored
26
vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/parse.go
generated
vendored
|
@ -181,15 +181,21 @@ func parseSection(t *doc.Type, pp *parsedPackage) *section {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure type "t" (used in a field or argument) defined in package pp is parsed
|
// Ensure type "t" (used in a field or argument) defined in package pp is parsed
|
||||||
// and added to the section.
|
// and added to the section. The returned string is the name as used in the
|
||||||
func ensureNamedType(t *doc.Type, sec *section, pp *parsedPackage) {
|
// sherpadoc, it may have been renamed.
|
||||||
typePath := pp.Path + "." + t.Name
|
func ensureNamedType(t *doc.Type, sec *section, pp *parsedPackage) (name string) {
|
||||||
|
if s, ok := renames[renameSrc{pp.Pkg.Name, t.Name}]; ok {
|
||||||
|
name = s
|
||||||
|
} else {
|
||||||
|
name = t.Name
|
||||||
|
}
|
||||||
|
typePath := pp.Path + "." + name
|
||||||
if _, have := sec.Typeset[typePath]; have {
|
if _, have := sec.Typeset[typePath]; have {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tt := &namedType{
|
tt := &namedType{
|
||||||
Name: t.Name,
|
Name: name,
|
||||||
Text: strings.TrimSpace(t.Doc),
|
Text: strings.TrimSpace(t.Doc),
|
||||||
}
|
}
|
||||||
// add it early, so self-referencing types can't cause a loop
|
// add it early, so self-referencing types can't cause a loop
|
||||||
|
@ -360,6 +366,7 @@ func ensureNamedType(t *doc.Type, sec *section, pp *parsedPackage) {
|
||||||
default:
|
default:
|
||||||
logFatalLinef(pp, t.Decl.TokPos, "unsupported field/param/return type %T", ts.Type)
|
logFatalLinef(pp, t.Decl.TokPos, "unsupported field/param/return type %T", ts.Type)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasOmitEmpty(tag *ast.BasicLit) bool {
|
func hasOmitEmpty(tag *ast.BasicLit) bool {
|
||||||
|
@ -407,8 +414,8 @@ func gatherFieldType(typeName string, f *field, e ast.Expr, fieldTag *ast.BasicL
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
tt := pp.lookupType(t.Name)
|
tt := pp.lookupType(t.Name)
|
||||||
if tt != nil {
|
if tt != nil {
|
||||||
ensureNamedType(tt, sec, pp)
|
name := ensureNamedType(tt, sec, pp)
|
||||||
return []string{t.Name}
|
return []string{name}
|
||||||
}
|
}
|
||||||
commaString := isCommaString(fieldTag)
|
commaString := isCommaString(fieldTag)
|
||||||
name := t.Name
|
name := t.Name
|
||||||
|
@ -465,8 +472,8 @@ func parseArgType(e ast.Expr, sec *section, pp *parsedPackage) typewords {
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
tt := pp.lookupType(t.Name)
|
tt := pp.lookupType(t.Name)
|
||||||
if tt != nil {
|
if tt != nil {
|
||||||
ensureNamedType(tt, sec, pp)
|
name := ensureNamedType(tt, sec, pp)
|
||||||
return []string{t.Name}
|
return []string{name}
|
||||||
}
|
}
|
||||||
name := t.Name
|
name := t.Name
|
||||||
switch name {
|
switch name {
|
||||||
|
@ -560,8 +567,7 @@ func parseSelector(t *ast.SelectorExpr, srcTypeName string, sec *section, pp *pa
|
||||||
if tt == nil {
|
if tt == nil {
|
||||||
logFatalLinef(pp, t.Pos(), "could not find type %q in package %q", typeName, importPath)
|
logFatalLinef(pp, t.Pos(), "could not find type %q in package %q", typeName, importPath)
|
||||||
}
|
}
|
||||||
ensureNamedType(tt, sec, opp)
|
return ensureNamedType(tt, sec, opp)
|
||||||
return typeName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type replacement struct {
|
type replacement struct {
|
||||||
|
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -25,7 +25,7 @@ github.com/mjl-/sconf
|
||||||
# github.com/mjl-/sherpa v0.6.7
|
# github.com/mjl-/sherpa v0.6.7
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/mjl-/sherpa
|
github.com/mjl-/sherpa
|
||||||
# github.com/mjl-/sherpadoc v0.0.13
|
# github.com/mjl-/sherpadoc v0.0.14
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
github.com/mjl-/sherpadoc
|
github.com/mjl-/sherpadoc
|
||||||
github.com/mjl-/sherpadoc/cmd/sherpadoc
|
github.com/mjl-/sherpadoc/cmd/sherpadoc
|
||||||
|
|
|
@ -194,6 +194,11 @@ func xcheckf(ctx context.Context, err error, format string, args ...any) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// If caller tried saving a config that is invalid, cause a user error.
|
||||||
|
if errors.Is(err, mox.ErrConfig) {
|
||||||
|
xcheckuserf(ctx, err, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
msg := fmt.Sprintf(format, args...)
|
msg := fmt.Sprintf(format, args...)
|
||||||
errmsg := fmt.Sprintf("%s: %s", msg, err)
|
errmsg := fmt.Sprintf("%s: %s", msg, err)
|
||||||
pkglog.WithContext(ctx).Errorx(msg, err)
|
pkglog.WithContext(ctx).Errorx(msg, err)
|
||||||
|
@ -1518,6 +1523,17 @@ func (Admin) ParseDomain(ctx context.Context, domain string) dns.Domain {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DomainConfig returns the configuration for a domain.
|
||||||
|
func (Admin) DomainConfig(ctx context.Context, domain string) config.Domain {
|
||||||
|
d, err := dns.ParseDomain(domain)
|
||||||
|
xcheckuserf(ctx, err, "parse domain")
|
||||||
|
conf, ok := mox.Conf.Domain(d)
|
||||||
|
if !ok {
|
||||||
|
xcheckuserf(ctx, errors.New("no such domain"), "looking up domain")
|
||||||
|
}
|
||||||
|
return conf
|
||||||
|
}
|
||||||
|
|
||||||
// DomainLocalparts returns the encoded localparts and accounts configured in domain.
|
// DomainLocalparts returns the encoded localparts and accounts configured in domain.
|
||||||
func (Admin) DomainLocalparts(ctx context.Context, domain string) (localpartAccounts map[string]string) {
|
func (Admin) DomainLocalparts(ctx context.Context, domain string) (localpartAccounts map[string]string) {
|
||||||
d, err := dns.ParseDomain(domain)
|
d, err := dns.ParseDomain(domain)
|
||||||
|
@ -1797,7 +1813,8 @@ func dnsblsStatus(ctx context.Context, log mlog.Log, resolver dns.Resolver) (res
|
||||||
// todo: check health before using dnsbl?
|
// todo: check health before using dnsbl?
|
||||||
using = mox.Conf.Static.Listeners["public"].SMTP.DNSBLZones
|
using = mox.Conf.Static.Listeners["public"].SMTP.DNSBLZones
|
||||||
zones := append([]dns.Domain{}, using...)
|
zones := append([]dns.Domain{}, using...)
|
||||||
for _, zone := range mox.Conf.MonitorDNSBLs() {
|
conf := mox.Conf.DynamicConfig()
|
||||||
|
for _, zone := range conf.MonitorDNSBLZones {
|
||||||
if !slices.Contains(zones, zone) {
|
if !slices.Contains(zones, zone) {
|
||||||
zones = append(zones, zone)
|
zones = append(zones, zone)
|
||||||
monitoring = append(monitoring, zone)
|
monitoring = append(monitoring, zone)
|
||||||
|
@ -1844,7 +1861,14 @@ func (Admin) MonitorDNSBLsSave(ctx context.Context, text string) {
|
||||||
}
|
}
|
||||||
zones = append(zones, d)
|
zones = append(zones, d)
|
||||||
}
|
}
|
||||||
err := mox.MonitorDNSBLsSave(ctx, zones)
|
|
||||||
|
err := mox.ConfigSave(ctx, func(conf *config.Dynamic) {
|
||||||
|
conf.MonitorDNSBLs = make([]string, len(zones))
|
||||||
|
conf.MonitorDNSBLZones = nil
|
||||||
|
for i, z := range zones {
|
||||||
|
conf.MonitorDNSBLs[i] = z.Name()
|
||||||
|
}
|
||||||
|
})
|
||||||
xcheckf(ctx, err, "saving monitoring dnsbl zones")
|
xcheckf(ctx, err, "saving monitoring dnsbl zones")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2172,7 +2196,10 @@ func (Admin) WebserverConfig(ctx context.Context) (conf WebserverConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func webserverConfig() WebserverConfig {
|
func webserverConfig() WebserverConfig {
|
||||||
r, l := mox.Conf.WebServer()
|
conf := mox.Conf.DynamicConfig()
|
||||||
|
r := conf.WebDNSDomainRedirects
|
||||||
|
l := conf.WebHandlers
|
||||||
|
|
||||||
x := make([][2]dns.Domain, 0, len(r))
|
x := make([][2]dns.Domain, 0, len(r))
|
||||||
xs := make([][2]string, 0, len(r))
|
xs := make([][2]string, 0, len(r))
|
||||||
for k, v := range r {
|
for k, v := range r {
|
||||||
|
@ -2218,7 +2245,10 @@ func (Admin) WebserverConfigSave(ctx context.Context, oldConf, newConf Webserver
|
||||||
domainRedirects[x[0]] = x[1]
|
domainRedirects[x[0]] = x[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
err := mox.WebserverConfigSet(ctx, domainRedirects, newConf.WebHandlers)
|
err := mox.ConfigSave(ctx, func(conf *config.Dynamic) {
|
||||||
|
conf.WebDomainRedirects = domainRedirects
|
||||||
|
conf.WebHandlers = newConf.WebHandlers
|
||||||
|
})
|
||||||
xcheckf(ctx, err, "saving webserver config")
|
xcheckf(ctx, err, "saving webserver config")
|
||||||
|
|
||||||
savedConf = webserverConfig()
|
savedConf = webserverConfig()
|
||||||
|
@ -2384,3 +2414,32 @@ func (Admin) LookupCid(ctx context.Context, recvID string) (cid string) {
|
||||||
xcheckf(ctx, err, "received id to cid")
|
xcheckf(ctx, err, "received id to cid")
|
||||||
return fmt.Sprintf("%x", v)
|
return fmt.Sprintf("%x", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config returns the dynamic config.
|
||||||
|
func (Admin) Config(ctx context.Context) config.Dynamic {
|
||||||
|
return mox.Conf.DynamicConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountRoutesSave saves routes for an account.
|
||||||
|
func (Admin) AccountRoutesSave(ctx context.Context, accountName string, routes []config.Route) {
|
||||||
|
err := mox.AccountSave(ctx, accountName, func(acc *config.Account) {
|
||||||
|
acc.Routes = routes
|
||||||
|
})
|
||||||
|
xcheckf(ctx, err, "saving account routes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainRoutesSave saves routes for a domain.
|
||||||
|
func (Admin) DomainRoutesSave(ctx context.Context, domainName string, routes []config.Route) {
|
||||||
|
err := mox.DomainSave(ctx, domainName, func(domain *config.Domain) {
|
||||||
|
domain.Routes = routes
|
||||||
|
})
|
||||||
|
xcheckf(ctx, err, "saving domain routes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoutesSave saves global routes.
|
||||||
|
func (Admin) RoutesSave(ctx context.Context, routes []config.Route) {
|
||||||
|
err := mox.ConfigSave(ctx, func(config *config.Dynamic) {
|
||||||
|
config.Routes = routes
|
||||||
|
})
|
||||||
|
xcheckf(ctx, err, "saving global routes")
|
||||||
|
}
|
||||||
|
|
|
@ -337,7 +337,7 @@ var api;
|
||||||
SPFResult["SPFTemperror"] = "temperror";
|
SPFResult["SPFTemperror"] = "temperror";
|
||||||
SPFResult["SPFPermerror"] = "permerror";
|
SPFResult["SPFPermerror"] = "permerror";
|
||||||
})(SPFResult = api.SPFResult || (api.SPFResult = {}));
|
})(SPFResult = api.SPFResult || (api.SPFResult = {}));
|
||||||
api.structTypes = { "Account": true, "AuthResults": true, "AutoconfCheckResult": true, "AutodiscoverCheckResult": true, "AutodiscoverSRV": true, "AutomaticJunkFlags": true, "CheckResult": true, "ClientConfigs": true, "ClientConfigsEntry": true, "DANECheckResult": true, "DKIMAuthResult": true, "DKIMCheckResult": true, "DKIMRecord": true, "DMARCCheckResult": true, "DMARCRecord": true, "DMARCSummary": true, "DNSSECResult": true, "DateRange": true, "Destination": true, "Directive": true, "Domain": true, "DomainFeedback": true, "Evaluation": true, "EvaluationStat": true, "Extension": true, "FailureDetails": true, "Filter": true, "HoldRule": true, "Hook": true, "HookFilter": true, "HookResult": true, "HookRetired": true, "HookRetiredFilter": true, "HookRetiredSort": true, "HookSort": true, "IPDomain": true, "IPRevCheckResult": true, "Identifiers": true, "IncomingWebhook": true, "JunkFilter": true, "MTASTSCheckResult": true, "MTASTSRecord": true, "MX": true, "MXCheckResult": true, "Modifier": true, "Msg": true, "MsgResult": true, "MsgRetired": true, "OutgoingWebhook": true, "Pair": true, "Policy": true, "PolicyEvaluated": true, "PolicyOverrideReason": true, "PolicyPublished": true, "PolicyRecord": true, "Record": true, "Report": true, "ReportMetadata": true, "ReportRecord": true, "Result": true, "ResultPolicy": true, "RetiredFilter": true, "RetiredSort": true, "Reverse": true, "Route": true, "Row": true, "Ruleset": true, "SMTPAuth": true, "SPFAuthResult": true, "SPFCheckResult": true, "SPFRecord": true, "SRV": true, "SRVConfCheckResult": true, "STSMX": true, "Sort": true, "SubjectPass": true, "Summary": true, "SuppressAddress": true, "TLSCheckResult": true, "TLSRPTCheckResult": true, "TLSRPTDateRange": true, "TLSRPTRecord": true, "TLSRPTSummary": true, "TLSRPTSuppressAddress": true, "TLSReportRecord": true, "TLSResult": true, "Transport": true, "TransportDirect": true, "TransportSMTP": true, "TransportSocks": true, "URI": true, "WebForward": true, "WebHandler": true, "WebRedirect": true, "WebStatic": true, "WebserverConfig": true };
|
api.structTypes = { "Account": true, "AuthResults": true, "AutoconfCheckResult": true, "AutodiscoverCheckResult": true, "AutodiscoverSRV": true, "AutomaticJunkFlags": true, "Canonicalization": true, "CheckResult": true, "ClientConfigs": true, "ClientConfigsEntry": true, "ConfigDomain": true, "DANECheckResult": true, "DKIM": true, "DKIMAuthResult": true, "DKIMCheckResult": true, "DKIMRecord": true, "DMARC": true, "DMARCCheckResult": true, "DMARCRecord": true, "DMARCSummary": true, "DNSSECResult": true, "DateRange": true, "Destination": true, "Directive": true, "Domain": true, "DomainFeedback": true, "Dynamic": true, "Evaluation": true, "EvaluationStat": true, "Extension": true, "FailureDetails": true, "Filter": true, "HoldRule": true, "Hook": true, "HookFilter": true, "HookResult": true, "HookRetired": true, "HookRetiredFilter": true, "HookRetiredSort": true, "HookSort": true, "IPDomain": true, "IPRevCheckResult": true, "Identifiers": true, "IncomingWebhook": true, "JunkFilter": true, "MTASTS": true, "MTASTSCheckResult": true, "MTASTSRecord": true, "MX": true, "MXCheckResult": true, "Modifier": true, "Msg": true, "MsgResult": true, "MsgRetired": true, "OutgoingWebhook": true, "Pair": true, "Policy": true, "PolicyEvaluated": true, "PolicyOverrideReason": true, "PolicyPublished": true, "PolicyRecord": true, "Record": true, "Report": true, "ReportMetadata": true, "ReportRecord": true, "Result": true, "ResultPolicy": true, "RetiredFilter": true, "RetiredSort": true, "Reverse": true, "Route": true, "Row": true, "Ruleset": true, "SMTPAuth": true, "SPFAuthResult": true, "SPFCheckResult": true, "SPFRecord": true, "SRV": true, "SRVConfCheckResult": true, "STSMX": true, "Selector": true, "Sort": true, "SubjectPass": true, "Summary": true, "SuppressAddress": true, "TLSCheckResult": true, "TLSRPT": true, "TLSRPTCheckResult": true, "TLSRPTDateRange": true, "TLSRPTRecord": true, "TLSRPTSummary": true, "TLSRPTSuppressAddress": true, "TLSReportRecord": true, "TLSResult": true, "Transport": true, "TransportDirect": true, "TransportSMTP": true, "TransportSocks": true, "URI": true, "WebForward": true, "WebHandler": true, "WebRedirect": true, "WebStatic": true, "WebserverConfig": true };
|
||||||
api.stringsTypes = { "Align": true, "Alignment": true, "CSRFToken": true, "DKIMResult": true, "DMARCPolicy": true, "DMARCResult": true, "Disposition": true, "IP": true, "Localpart": true, "Mode": true, "PolicyOverride": true, "PolicyType": true, "RUA": true, "ResultType": true, "SPFDomainScope": true, "SPFResult": true };
|
api.stringsTypes = { "Align": true, "Alignment": true, "CSRFToken": true, "DKIMResult": true, "DMARCPolicy": true, "DMARCResult": true, "Disposition": true, "IP": true, "Localpart": true, "Mode": true, "PolicyOverride": true, "PolicyType": true, "RUA": true, "ResultType": true, "SPFDomainScope": true, "SPFResult": true };
|
||||||
api.intsTypes = {};
|
api.intsTypes = {};
|
||||||
api.types = {
|
api.types = {
|
||||||
|
@ -372,6 +372,14 @@ 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"] }] },
|
"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"] }] },
|
"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"] }] },
|
"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": "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"] }] },
|
||||||
|
"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"] }] },
|
||||||
|
"Canonicalization": { "Name": "Canonicalization", "Docs": "", "Fields": [{ "Name": "HeaderRelaxed", "Docs": "", "Typewords": ["bool"] }, { "Name": "BodyRelaxed", "Docs": "", "Typewords": ["bool"] }] },
|
||||||
|
"DMARC": { "Name": "DMARC", "Docs": "", "Fields": [{ "Name": "Localpart", "Docs": "", "Typewords": ["string"] }, { "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "Account", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "ParsedLocalpart", "Docs": "", "Typewords": ["Localpart"] }, { "Name": "DNSDomain", "Docs": "", "Typewords": ["Domain"] }] },
|
||||||
|
"MTASTS": { "Name": "MTASTS", "Docs": "", "Fields": [{ "Name": "PolicyID", "Docs": "", "Typewords": ["string"] }, { "Name": "Mode", "Docs": "", "Typewords": ["Mode"] }, { "Name": "MaxAge", "Docs": "", "Typewords": ["int64"] }, { "Name": "MX", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||||
|
"TLSRPT": { "Name": "TLSRPT", "Docs": "", "Fields": [{ "Name": "Localpart", "Docs": "", "Typewords": ["string"] }, { "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "Account", "Docs": "", "Typewords": ["string"] }, { "Name": "Mailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "ParsedLocalpart", "Docs": "", "Typewords": ["Localpart"] }, { "Name": "DNSDomain", "Docs": "", "Typewords": ["Domain"] }] },
|
||||||
|
"Route": { "Name": "Route", "Docs": "", "Fields": [{ "Name": "FromDomain", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "ToDomain", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "MinimumAttempts", "Docs": "", "Typewords": ["int32"] }, { "Name": "Transport", "Docs": "", "Typewords": ["string"] }, { "Name": "FromDomainASCII", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "ToDomainASCII", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||||
"Account": { "Name": "Account", "Docs": "", "Fields": [{ "Name": "OutgoingWebhook", "Docs": "", "Typewords": ["nullable", "OutgoingWebhook"] }, { "Name": "IncomingWebhook", "Docs": "", "Typewords": ["nullable", "IncomingWebhook"] }, { "Name": "FromIDLoginAddresses", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "KeepRetiredMessagePeriod", "Docs": "", "Typewords": ["int64"] }, { "Name": "KeepRetiredWebhookPeriod", "Docs": "", "Typewords": ["int64"] }, { "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "Description", "Docs": "", "Typewords": ["string"] }, { "Name": "FullName", "Docs": "", "Typewords": ["string"] }, { "Name": "Destinations", "Docs": "", "Typewords": ["{}", "Destination"] }, { "Name": "SubjectPass", "Docs": "", "Typewords": ["SubjectPass"] }, { "Name": "QuotaMessageSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "KeepRejects", "Docs": "", "Typewords": ["bool"] }, { "Name": "AutomaticJunkFlags", "Docs": "", "Typewords": ["AutomaticJunkFlags"] }, { "Name": "JunkFilter", "Docs": "", "Typewords": ["nullable", "JunkFilter"] }, { "Name": "MaxOutgoingMessagesPerDay", "Docs": "", "Typewords": ["int32"] }, { "Name": "MaxFirstTimeRecipientsPerDay", "Docs": "", "Typewords": ["int32"] }, { "Name": "NoFirstTimeSenderDelay", "Docs": "", "Typewords": ["bool"] }, { "Name": "Routes", "Docs": "", "Typewords": ["[]", "Route"] }, { "Name": "DNSDomain", "Docs": "", "Typewords": ["Domain"] }] },
|
"Account": { "Name": "Account", "Docs": "", "Fields": [{ "Name": "OutgoingWebhook", "Docs": "", "Typewords": ["nullable", "OutgoingWebhook"] }, { "Name": "IncomingWebhook", "Docs": "", "Typewords": ["nullable", "IncomingWebhook"] }, { "Name": "FromIDLoginAddresses", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "KeepRetiredMessagePeriod", "Docs": "", "Typewords": ["int64"] }, { "Name": "KeepRetiredWebhookPeriod", "Docs": "", "Typewords": ["int64"] }, { "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "Description", "Docs": "", "Typewords": ["string"] }, { "Name": "FullName", "Docs": "", "Typewords": ["string"] }, { "Name": "Destinations", "Docs": "", "Typewords": ["{}", "Destination"] }, { "Name": "SubjectPass", "Docs": "", "Typewords": ["SubjectPass"] }, { "Name": "QuotaMessageSize", "Docs": "", "Typewords": ["int64"] }, { "Name": "RejectsMailbox", "Docs": "", "Typewords": ["string"] }, { "Name": "KeepRejects", "Docs": "", "Typewords": ["bool"] }, { "Name": "AutomaticJunkFlags", "Docs": "", "Typewords": ["AutomaticJunkFlags"] }, { "Name": "JunkFilter", "Docs": "", "Typewords": ["nullable", "JunkFilter"] }, { "Name": "MaxOutgoingMessagesPerDay", "Docs": "", "Typewords": ["int32"] }, { "Name": "MaxFirstTimeRecipientsPerDay", "Docs": "", "Typewords": ["int32"] }, { "Name": "NoFirstTimeSenderDelay", "Docs": "", "Typewords": ["bool"] }, { "Name": "Routes", "Docs": "", "Typewords": ["[]", "Route"] }, { "Name": "DNSDomain", "Docs": "", "Typewords": ["Domain"] }] },
|
||||||
"OutgoingWebhook": { "Name": "OutgoingWebhook", "Docs": "", "Fields": [{ "Name": "URL", "Docs": "", "Typewords": ["string"] }, { "Name": "Authorization", "Docs": "", "Typewords": ["string"] }, { "Name": "Events", "Docs": "", "Typewords": ["[]", "string"] }] },
|
"OutgoingWebhook": { "Name": "OutgoingWebhook", "Docs": "", "Fields": [{ "Name": "URL", "Docs": "", "Typewords": ["string"] }, { "Name": "Authorization", "Docs": "", "Typewords": ["string"] }, { "Name": "Events", "Docs": "", "Typewords": ["[]", "string"] }] },
|
||||||
"IncomingWebhook": { "Name": "IncomingWebhook", "Docs": "", "Fields": [{ "Name": "URL", "Docs": "", "Typewords": ["string"] }, { "Name": "Authorization", "Docs": "", "Typewords": ["string"] }] },
|
"IncomingWebhook": { "Name": "IncomingWebhook", "Docs": "", "Fields": [{ "Name": "URL", "Docs": "", "Typewords": ["string"] }, { "Name": "Authorization", "Docs": "", "Typewords": ["string"] }] },
|
||||||
|
@ -380,7 +388,6 @@ var api;
|
||||||
"SubjectPass": { "Name": "SubjectPass", "Docs": "", "Fields": [{ "Name": "Period", "Docs": "", "Typewords": ["int64"] }] },
|
"SubjectPass": { "Name": "SubjectPass", "Docs": "", "Fields": [{ "Name": "Period", "Docs": "", "Typewords": ["int64"] }] },
|
||||||
"AutomaticJunkFlags": { "Name": "AutomaticJunkFlags", "Docs": "", "Fields": [{ "Name": "Enabled", "Docs": "", "Typewords": ["bool"] }, { "Name": "JunkMailboxRegexp", "Docs": "", "Typewords": ["string"] }, { "Name": "NeutralMailboxRegexp", "Docs": "", "Typewords": ["string"] }, { "Name": "NotJunkMailboxRegexp", "Docs": "", "Typewords": ["string"] }] },
|
"AutomaticJunkFlags": { "Name": "AutomaticJunkFlags", "Docs": "", "Fields": [{ "Name": "Enabled", "Docs": "", "Typewords": ["bool"] }, { "Name": "JunkMailboxRegexp", "Docs": "", "Typewords": ["string"] }, { "Name": "NeutralMailboxRegexp", "Docs": "", "Typewords": ["string"] }, { "Name": "NotJunkMailboxRegexp", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"JunkFilter": { "Name": "JunkFilter", "Docs": "", "Fields": [{ "Name": "Threshold", "Docs": "", "Typewords": ["float64"] }, { "Name": "Onegrams", "Docs": "", "Typewords": ["bool"] }, { "Name": "Twograms", "Docs": "", "Typewords": ["bool"] }, { "Name": "Threegrams", "Docs": "", "Typewords": ["bool"] }, { "Name": "MaxPower", "Docs": "", "Typewords": ["float64"] }, { "Name": "TopWords", "Docs": "", "Typewords": ["int32"] }, { "Name": "IgnoreWords", "Docs": "", "Typewords": ["float64"] }, { "Name": "RareWords", "Docs": "", "Typewords": ["int32"] }] },
|
"JunkFilter": { "Name": "JunkFilter", "Docs": "", "Fields": [{ "Name": "Threshold", "Docs": "", "Typewords": ["float64"] }, { "Name": "Onegrams", "Docs": "", "Typewords": ["bool"] }, { "Name": "Twograms", "Docs": "", "Typewords": ["bool"] }, { "Name": "Threegrams", "Docs": "", "Typewords": ["bool"] }, { "Name": "MaxPower", "Docs": "", "Typewords": ["float64"] }, { "Name": "TopWords", "Docs": "", "Typewords": ["int32"] }, { "Name": "IgnoreWords", "Docs": "", "Typewords": ["float64"] }, { "Name": "RareWords", "Docs": "", "Typewords": ["int32"] }] },
|
||||||
"Route": { "Name": "Route", "Docs": "", "Fields": [{ "Name": "FromDomain", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "ToDomain", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "MinimumAttempts", "Docs": "", "Typewords": ["int32"] }, { "Name": "Transport", "Docs": "", "Typewords": ["string"] }, { "Name": "FromDomainASCII", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "ToDomainASCII", "Docs": "", "Typewords": ["[]", "string"] }] },
|
|
||||||
"PolicyRecord": { "Name": "PolicyRecord", "Docs": "", "Fields": [{ "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "Inserted", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "ValidEnd", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "LastUpdate", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "LastUse", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Backoff", "Docs": "", "Typewords": ["bool"] }, { "Name": "RecordID", "Docs": "", "Typewords": ["string"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }, { "Name": "Mode", "Docs": "", "Typewords": ["Mode"] }, { "Name": "MX", "Docs": "", "Typewords": ["[]", "STSMX"] }, { "Name": "MaxAgeSeconds", "Docs": "", "Typewords": ["int32"] }, { "Name": "Extensions", "Docs": "", "Typewords": ["[]", "Pair"] }, { "Name": "PolicyText", "Docs": "", "Typewords": ["string"] }] },
|
"PolicyRecord": { "Name": "PolicyRecord", "Docs": "", "Fields": [{ "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "Inserted", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "ValidEnd", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "LastUpdate", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "LastUse", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Backoff", "Docs": "", "Typewords": ["bool"] }, { "Name": "RecordID", "Docs": "", "Typewords": ["string"] }, { "Name": "Version", "Docs": "", "Typewords": ["string"] }, { "Name": "Mode", "Docs": "", "Typewords": ["Mode"] }, { "Name": "MX", "Docs": "", "Typewords": ["[]", "STSMX"] }, { "Name": "MaxAgeSeconds", "Docs": "", "Typewords": ["int32"] }, { "Name": "Extensions", "Docs": "", "Typewords": ["[]", "Pair"] }, { "Name": "PolicyText", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"TLSReportRecord": { "Name": "TLSReportRecord", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "FromDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "MailFrom", "Docs": "", "Typewords": ["string"] }, { "Name": "HostReport", "Docs": "", "Typewords": ["bool"] }, { "Name": "Report", "Docs": "", "Typewords": ["Report"] }] },
|
"TLSReportRecord": { "Name": "TLSReportRecord", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Domain", "Docs": "", "Typewords": ["string"] }, { "Name": "FromDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "MailFrom", "Docs": "", "Typewords": ["string"] }, { "Name": "HostReport", "Docs": "", "Typewords": ["bool"] }, { "Name": "Report", "Docs": "", "Typewords": ["Report"] }] },
|
||||||
"Report": { "Name": "Report", "Docs": "", "Fields": [{ "Name": "OrganizationName", "Docs": "", "Typewords": ["string"] }, { "Name": "DateRange", "Docs": "", "Typewords": ["TLSRPTDateRange"] }, { "Name": "ContactInfo", "Docs": "", "Typewords": ["string"] }, { "Name": "ReportID", "Docs": "", "Typewords": ["string"] }, { "Name": "Policies", "Docs": "", "Typewords": ["[]", "Result"] }] },
|
"Report": { "Name": "Report", "Docs": "", "Fields": [{ "Name": "OrganizationName", "Docs": "", "Typewords": ["string"] }, { "Name": "DateRange", "Docs": "", "Typewords": ["TLSRPTDateRange"] }, { "Name": "ContactInfo", "Docs": "", "Typewords": ["string"] }, { "Name": "ReportID", "Docs": "", "Typewords": ["string"] }, { "Name": "Policies", "Docs": "", "Typewords": ["[]", "Result"] }] },
|
||||||
|
@ -437,11 +444,13 @@ var api;
|
||||||
"SuppressAddress": { "Name": "SuppressAddress", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Inserted", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "ReportingAddress", "Docs": "", "Typewords": ["string"] }, { "Name": "Until", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Comment", "Docs": "", "Typewords": ["string"] }] },
|
"SuppressAddress": { "Name": "SuppressAddress", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Inserted", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "ReportingAddress", "Docs": "", "Typewords": ["string"] }, { "Name": "Until", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Comment", "Docs": "", "Typewords": ["string"] }] },
|
||||||
"TLSResult": { "Name": "TLSResult", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "PolicyDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "DayUTC", "Docs": "", "Typewords": ["string"] }, { "Name": "RecipientDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "Created", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Updated", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "IsHost", "Docs": "", "Typewords": ["bool"] }, { "Name": "SendReport", "Docs": "", "Typewords": ["bool"] }, { "Name": "SentToRecipientDomain", "Docs": "", "Typewords": ["bool"] }, { "Name": "RecipientDomainReportingAddresses", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "SentToPolicyDomain", "Docs": "", "Typewords": ["bool"] }, { "Name": "Results", "Docs": "", "Typewords": ["[]", "Result"] }] },
|
"TLSResult": { "Name": "TLSResult", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "PolicyDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "DayUTC", "Docs": "", "Typewords": ["string"] }, { "Name": "RecipientDomain", "Docs": "", "Typewords": ["string"] }, { "Name": "Created", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Updated", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "IsHost", "Docs": "", "Typewords": ["bool"] }, { "Name": "SendReport", "Docs": "", "Typewords": ["bool"] }, { "Name": "SentToRecipientDomain", "Docs": "", "Typewords": ["bool"] }, { "Name": "RecipientDomainReportingAddresses", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "SentToPolicyDomain", "Docs": "", "Typewords": ["bool"] }, { "Name": "Results", "Docs": "", "Typewords": ["[]", "Result"] }] },
|
||||||
"TLSRPTSuppressAddress": { "Name": "TLSRPTSuppressAddress", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Inserted", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "ReportingAddress", "Docs": "", "Typewords": ["string"] }, { "Name": "Until", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Comment", "Docs": "", "Typewords": ["string"] }] },
|
"TLSRPTSuppressAddress": { "Name": "TLSRPTSuppressAddress", "Docs": "", "Fields": [{ "Name": "ID", "Docs": "", "Typewords": ["int64"] }, { "Name": "Inserted", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "ReportingAddress", "Docs": "", "Typewords": ["string"] }, { "Name": "Until", "Docs": "", "Typewords": ["timestamp"] }, { "Name": "Comment", "Docs": "", "Typewords": ["string"] }] },
|
||||||
|
"Dynamic": { "Name": "Dynamic", "Docs": "", "Fields": [{ "Name": "Domains", "Docs": "", "Typewords": ["{}", "ConfigDomain"] }, { "Name": "Accounts", "Docs": "", "Typewords": ["{}", "Account"] }, { "Name": "WebDomainRedirects", "Docs": "", "Typewords": ["{}", "string"] }, { "Name": "WebHandlers", "Docs": "", "Typewords": ["[]", "WebHandler"] }, { "Name": "Routes", "Docs": "", "Typewords": ["[]", "Route"] }, { "Name": "MonitorDNSBLs", "Docs": "", "Typewords": ["[]", "string"] }, { "Name": "MonitorDNSBLZones", "Docs": "", "Typewords": ["[]", "Domain"] }] },
|
||||||
"CSRFToken": { "Name": "CSRFToken", "Docs": "", "Values": null },
|
"CSRFToken": { "Name": "CSRFToken", "Docs": "", "Values": null },
|
||||||
"DMARCPolicy": { "Name": "DMARCPolicy", "Docs": "", "Values": [{ "Name": "PolicyEmpty", "Value": "", "Docs": "" }, { "Name": "PolicyNone", "Value": "none", "Docs": "" }, { "Name": "PolicyQuarantine", "Value": "quarantine", "Docs": "" }, { "Name": "PolicyReject", "Value": "reject", "Docs": "" }] },
|
"DMARCPolicy": { "Name": "DMARCPolicy", "Docs": "", "Values": [{ "Name": "PolicyEmpty", "Value": "", "Docs": "" }, { "Name": "PolicyNone", "Value": "none", "Docs": "" }, { "Name": "PolicyQuarantine", "Value": "quarantine", "Docs": "" }, { "Name": "PolicyReject", "Value": "reject", "Docs": "" }] },
|
||||||
"Align": { "Name": "Align", "Docs": "", "Values": [{ "Name": "AlignStrict", "Value": "s", "Docs": "" }, { "Name": "AlignRelaxed", "Value": "r", "Docs": "" }] },
|
"Align": { "Name": "Align", "Docs": "", "Values": [{ "Name": "AlignStrict", "Value": "s", "Docs": "" }, { "Name": "AlignRelaxed", "Value": "r", "Docs": "" }] },
|
||||||
"RUA": { "Name": "RUA", "Docs": "", "Values": null },
|
"RUA": { "Name": "RUA", "Docs": "", "Values": null },
|
||||||
"Mode": { "Name": "Mode", "Docs": "", "Values": [{ "Name": "ModeEnforce", "Value": "enforce", "Docs": "" }, { "Name": "ModeTesting", "Value": "testing", "Docs": "" }, { "Name": "ModeNone", "Value": "none", "Docs": "" }] },
|
"Mode": { "Name": "Mode", "Docs": "", "Values": [{ "Name": "ModeEnforce", "Value": "enforce", "Docs": "" }, { "Name": "ModeTesting", "Value": "testing", "Docs": "" }, { "Name": "ModeNone", "Value": "none", "Docs": "" }] },
|
||||||
|
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
||||||
"PolicyType": { "Name": "PolicyType", "Docs": "", "Values": [{ "Name": "TLSA", "Value": "tlsa", "Docs": "" }, { "Name": "STS", "Value": "sts", "Docs": "" }, { "Name": "NoPolicyFound", "Value": "no-policy-found", "Docs": "" }] },
|
"PolicyType": { "Name": "PolicyType", "Docs": "", "Values": [{ "Name": "TLSA", "Value": "tlsa", "Docs": "" }, { "Name": "STS", "Value": "sts", "Docs": "" }, { "Name": "NoPolicyFound", "Value": "no-policy-found", "Docs": "" }] },
|
||||||
"ResultType": { "Name": "ResultType", "Docs": "", "Values": [{ "Name": "ResultSTARTTLSNotSupported", "Value": "starttls-not-supported", "Docs": "" }, { "Name": "ResultCertificateHostMismatch", "Value": "certificate-host-mismatch", "Docs": "" }, { "Name": "ResultCertificateExpired", "Value": "certificate-expired", "Docs": "" }, { "Name": "ResultTLSAInvalid", "Value": "tlsa-invalid", "Docs": "" }, { "Name": "ResultDNSSECInvalid", "Value": "dnssec-invalid", "Docs": "" }, { "Name": "ResultDANERequired", "Value": "dane-required", "Docs": "" }, { "Name": "ResultCertificateNotTrusted", "Value": "certificate-not-trusted", "Docs": "" }, { "Name": "ResultSTSPolicyInvalid", "Value": "sts-policy-invalid", "Docs": "" }, { "Name": "ResultSTSWebPKIInvalid", "Value": "sts-webpki-invalid", "Docs": "" }, { "Name": "ResultValidationFailure", "Value": "validation-failure", "Docs": "" }, { "Name": "ResultSTSPolicyFetch", "Value": "sts-policy-fetch-error", "Docs": "" }] },
|
"ResultType": { "Name": "ResultType", "Docs": "", "Values": [{ "Name": "ResultSTARTTLSNotSupported", "Value": "starttls-not-supported", "Docs": "" }, { "Name": "ResultCertificateHostMismatch", "Value": "certificate-host-mismatch", "Docs": "" }, { "Name": "ResultCertificateExpired", "Value": "certificate-expired", "Docs": "" }, { "Name": "ResultTLSAInvalid", "Value": "tlsa-invalid", "Docs": "" }, { "Name": "ResultDNSSECInvalid", "Value": "dnssec-invalid", "Docs": "" }, { "Name": "ResultDANERequired", "Value": "dane-required", "Docs": "" }, { "Name": "ResultCertificateNotTrusted", "Value": "certificate-not-trusted", "Docs": "" }, { "Name": "ResultSTSPolicyInvalid", "Value": "sts-policy-invalid", "Docs": "" }, { "Name": "ResultSTSWebPKIInvalid", "Value": "sts-webpki-invalid", "Docs": "" }, { "Name": "ResultValidationFailure", "Value": "validation-failure", "Docs": "" }, { "Name": "ResultSTSPolicyFetch", "Value": "sts-policy-fetch-error", "Docs": "" }] },
|
||||||
"Alignment": { "Name": "Alignment", "Docs": "", "Values": [{ "Name": "AlignmentAbsent", "Value": "", "Docs": "" }, { "Name": "AlignmentRelaxed", "Value": "r", "Docs": "" }, { "Name": "AlignmentStrict", "Value": "s", "Docs": "" }] },
|
"Alignment": { "Name": "Alignment", "Docs": "", "Values": [{ "Name": "AlignmentAbsent", "Value": "", "Docs": "" }, { "Name": "AlignmentRelaxed", "Value": "r", "Docs": "" }, { "Name": "AlignmentStrict", "Value": "s", "Docs": "" }] },
|
||||||
|
@ -451,7 +460,6 @@ var api;
|
||||||
"DKIMResult": { "Name": "DKIMResult", "Docs": "", "Values": [{ "Name": "DKIMAbsent", "Value": "", "Docs": "" }, { "Name": "DKIMNone", "Value": "none", "Docs": "" }, { "Name": "DKIMPass", "Value": "pass", "Docs": "" }, { "Name": "DKIMFail", "Value": "fail", "Docs": "" }, { "Name": "DKIMPolicy", "Value": "policy", "Docs": "" }, { "Name": "DKIMNeutral", "Value": "neutral", "Docs": "" }, { "Name": "DKIMTemperror", "Value": "temperror", "Docs": "" }, { "Name": "DKIMPermerror", "Value": "permerror", "Docs": "" }] },
|
"DKIMResult": { "Name": "DKIMResult", "Docs": "", "Values": [{ "Name": "DKIMAbsent", "Value": "", "Docs": "" }, { "Name": "DKIMNone", "Value": "none", "Docs": "" }, { "Name": "DKIMPass", "Value": "pass", "Docs": "" }, { "Name": "DKIMFail", "Value": "fail", "Docs": "" }, { "Name": "DKIMPolicy", "Value": "policy", "Docs": "" }, { "Name": "DKIMNeutral", "Value": "neutral", "Docs": "" }, { "Name": "DKIMTemperror", "Value": "temperror", "Docs": "" }, { "Name": "DKIMPermerror", "Value": "permerror", "Docs": "" }] },
|
||||||
"SPFDomainScope": { "Name": "SPFDomainScope", "Docs": "", "Values": [{ "Name": "SPFDomainScopeAbsent", "Value": "", "Docs": "" }, { "Name": "SPFDomainScopeHelo", "Value": "helo", "Docs": "" }, { "Name": "SPFDomainScopeMailFrom", "Value": "mfrom", "Docs": "" }] },
|
"SPFDomainScope": { "Name": "SPFDomainScope", "Docs": "", "Values": [{ "Name": "SPFDomainScopeAbsent", "Value": "", "Docs": "" }, { "Name": "SPFDomainScopeHelo", "Value": "helo", "Docs": "" }, { "Name": "SPFDomainScopeMailFrom", "Value": "mfrom", "Docs": "" }] },
|
||||||
"SPFResult": { "Name": "SPFResult", "Docs": "", "Values": [{ "Name": "SPFAbsent", "Value": "", "Docs": "" }, { "Name": "SPFNone", "Value": "none", "Docs": "" }, { "Name": "SPFNeutral", "Value": "neutral", "Docs": "" }, { "Name": "SPFPass", "Value": "pass", "Docs": "" }, { "Name": "SPFFail", "Value": "fail", "Docs": "" }, { "Name": "SPFSoftfail", "Value": "softfail", "Docs": "" }, { "Name": "SPFTemperror", "Value": "temperror", "Docs": "" }, { "Name": "SPFPermerror", "Value": "permerror", "Docs": "" }] },
|
"SPFResult": { "Name": "SPFResult", "Docs": "", "Values": [{ "Name": "SPFAbsent", "Value": "", "Docs": "" }, { "Name": "SPFNone", "Value": "none", "Docs": "" }, { "Name": "SPFNeutral", "Value": "neutral", "Docs": "" }, { "Name": "SPFPass", "Value": "pass", "Docs": "" }, { "Name": "SPFFail", "Value": "fail", "Docs": "" }, { "Name": "SPFSoftfail", "Value": "softfail", "Docs": "" }, { "Name": "SPFTemperror", "Value": "temperror", "Docs": "" }, { "Name": "SPFPermerror", "Value": "permerror", "Docs": "" }] },
|
||||||
"Localpart": { "Name": "Localpart", "Docs": "", "Values": null },
|
|
||||||
"IP": { "Name": "IP", "Docs": "", "Values": [] },
|
"IP": { "Name": "IP", "Docs": "", "Values": [] },
|
||||||
};
|
};
|
||||||
api.parser = {
|
api.parser = {
|
||||||
|
@ -486,6 +494,14 @@ var api;
|
||||||
AutoconfCheckResult: (v) => api.parse("AutoconfCheckResult", v),
|
AutoconfCheckResult: (v) => api.parse("AutoconfCheckResult", v),
|
||||||
AutodiscoverCheckResult: (v) => api.parse("AutodiscoverCheckResult", v),
|
AutodiscoverCheckResult: (v) => api.parse("AutodiscoverCheckResult", v),
|
||||||
AutodiscoverSRV: (v) => api.parse("AutodiscoverSRV", v),
|
AutodiscoverSRV: (v) => api.parse("AutodiscoverSRV", v),
|
||||||
|
ConfigDomain: (v) => api.parse("ConfigDomain", v),
|
||||||
|
DKIM: (v) => api.parse("DKIM", v),
|
||||||
|
Selector: (v) => api.parse("Selector", v),
|
||||||
|
Canonicalization: (v) => api.parse("Canonicalization", v),
|
||||||
|
DMARC: (v) => api.parse("DMARC", v),
|
||||||
|
MTASTS: (v) => api.parse("MTASTS", v),
|
||||||
|
TLSRPT: (v) => api.parse("TLSRPT", v),
|
||||||
|
Route: (v) => api.parse("Route", v),
|
||||||
Account: (v) => api.parse("Account", v),
|
Account: (v) => api.parse("Account", v),
|
||||||
OutgoingWebhook: (v) => api.parse("OutgoingWebhook", v),
|
OutgoingWebhook: (v) => api.parse("OutgoingWebhook", v),
|
||||||
IncomingWebhook: (v) => api.parse("IncomingWebhook", v),
|
IncomingWebhook: (v) => api.parse("IncomingWebhook", v),
|
||||||
|
@ -494,7 +510,6 @@ var api;
|
||||||
SubjectPass: (v) => api.parse("SubjectPass", v),
|
SubjectPass: (v) => api.parse("SubjectPass", v),
|
||||||
AutomaticJunkFlags: (v) => api.parse("AutomaticJunkFlags", v),
|
AutomaticJunkFlags: (v) => api.parse("AutomaticJunkFlags", v),
|
||||||
JunkFilter: (v) => api.parse("JunkFilter", v),
|
JunkFilter: (v) => api.parse("JunkFilter", v),
|
||||||
Route: (v) => api.parse("Route", v),
|
|
||||||
PolicyRecord: (v) => api.parse("PolicyRecord", v),
|
PolicyRecord: (v) => api.parse("PolicyRecord", v),
|
||||||
TLSReportRecord: (v) => api.parse("TLSReportRecord", v),
|
TLSReportRecord: (v) => api.parse("TLSReportRecord", v),
|
||||||
Report: (v) => api.parse("Report", v),
|
Report: (v) => api.parse("Report", v),
|
||||||
|
@ -551,11 +566,13 @@ var api;
|
||||||
SuppressAddress: (v) => api.parse("SuppressAddress", v),
|
SuppressAddress: (v) => api.parse("SuppressAddress", v),
|
||||||
TLSResult: (v) => api.parse("TLSResult", v),
|
TLSResult: (v) => api.parse("TLSResult", v),
|
||||||
TLSRPTSuppressAddress: (v) => api.parse("TLSRPTSuppressAddress", v),
|
TLSRPTSuppressAddress: (v) => api.parse("TLSRPTSuppressAddress", v),
|
||||||
|
Dynamic: (v) => api.parse("Dynamic", v),
|
||||||
CSRFToken: (v) => api.parse("CSRFToken", v),
|
CSRFToken: (v) => api.parse("CSRFToken", v),
|
||||||
DMARCPolicy: (v) => api.parse("DMARCPolicy", v),
|
DMARCPolicy: (v) => api.parse("DMARCPolicy", v),
|
||||||
Align: (v) => api.parse("Align", v),
|
Align: (v) => api.parse("Align", v),
|
||||||
RUA: (v) => api.parse("RUA", v),
|
RUA: (v) => api.parse("RUA", v),
|
||||||
Mode: (v) => api.parse("Mode", v),
|
Mode: (v) => api.parse("Mode", v),
|
||||||
|
Localpart: (v) => api.parse("Localpart", v),
|
||||||
PolicyType: (v) => api.parse("PolicyType", v),
|
PolicyType: (v) => api.parse("PolicyType", v),
|
||||||
ResultType: (v) => api.parse("ResultType", v),
|
ResultType: (v) => api.parse("ResultType", v),
|
||||||
Alignment: (v) => api.parse("Alignment", v),
|
Alignment: (v) => api.parse("Alignment", v),
|
||||||
|
@ -565,7 +582,6 @@ var api;
|
||||||
DKIMResult: (v) => api.parse("DKIMResult", v),
|
DKIMResult: (v) => api.parse("DKIMResult", v),
|
||||||
SPFDomainScope: (v) => api.parse("SPFDomainScope", v),
|
SPFDomainScope: (v) => api.parse("SPFDomainScope", v),
|
||||||
SPFResult: (v) => api.parse("SPFResult", v),
|
SPFResult: (v) => api.parse("SPFResult", v),
|
||||||
Localpart: (v) => api.parse("Localpart", v),
|
|
||||||
IP: (v) => api.parse("IP", v),
|
IP: (v) => api.parse("IP", v),
|
||||||
};
|
};
|
||||||
// Admin exports web API functions for the admin web interface. All its methods are
|
// Admin exports web API functions for the admin web interface. All its methods are
|
||||||
|
@ -652,6 +668,14 @@ var api;
|
||||||
const params = [domain];
|
const params = [domain];
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
}
|
}
|
||||||
|
// DomainConfig returns the configuration for a domain.
|
||||||
|
async DomainConfig(domain) {
|
||||||
|
const fn = "DomainConfig";
|
||||||
|
const paramTypes = [["string"]];
|
||||||
|
const returnTypes = [["ConfigDomain"]];
|
||||||
|
const params = [domain];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
// DomainLocalparts returns the encoded localparts and accounts configured in domain.
|
// DomainLocalparts returns the encoded localparts and accounts configured in domain.
|
||||||
async DomainLocalparts(domain) {
|
async DomainLocalparts(domain) {
|
||||||
const fn = "DomainLocalparts";
|
const fn = "DomainLocalparts";
|
||||||
|
@ -1214,6 +1238,38 @@ var api;
|
||||||
const params = [recvID];
|
const params = [recvID];
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
}
|
}
|
||||||
|
// Config returns the dynamic config.
|
||||||
|
async Config() {
|
||||||
|
const fn = "Config";
|
||||||
|
const paramTypes = [];
|
||||||
|
const returnTypes = [["Dynamic"]];
|
||||||
|
const params = [];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
|
// AccountRoutesSave saves routes for an account.
|
||||||
|
async AccountRoutesSave(accountName, routes) {
|
||||||
|
const fn = "AccountRoutesSave";
|
||||||
|
const paramTypes = [["string"], ["[]", "Route"]];
|
||||||
|
const returnTypes = [];
|
||||||
|
const params = [accountName, routes];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
|
// DomainRoutesSave saves routes for a domain.
|
||||||
|
async DomainRoutesSave(domainName, routes) {
|
||||||
|
const fn = "DomainRoutesSave";
|
||||||
|
const paramTypes = [["string"], ["[]", "Route"]];
|
||||||
|
const returnTypes = [];
|
||||||
|
const params = [domainName, routes];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
|
// RoutesSave saves global routes.
|
||||||
|
async RoutesSave(routes) {
|
||||||
|
const fn = "RoutesSave";
|
||||||
|
const paramTypes = [["[]", "Route"]];
|
||||||
|
const returnTypes = [];
|
||||||
|
const params = [routes];
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
api.Client = Client;
|
api.Client = Client;
|
||||||
api.defaultBaseURL = (function () {
|
api.defaultBaseURL = (function () {
|
||||||
|
@ -1855,7 +1911,14 @@ const index = async () => {
|
||||||
await check(recvIDFieldset, client.LookupCid(recvID.value));
|
await check(recvIDFieldset, client.LookupCid(recvID.value));
|
||||||
}, recvIDFieldset = dom.fieldset(dom.label('Received ID', attr.title('The ID in the Received header that was added during incoming delivery.')), ' ', recvID = dom.input(attr.required('')), ' ', dom.submitbutton('Lookup cid', attr.title('Logging about an incoming message includes an attribute "cid", a counter identifying the transaction related to delivery of the message. The ID in the received header is an encrypted cid, which this form decrypts, after which you can look it up in the logging.')), ' ', cidElem = dom.span()))),
|
}, recvIDFieldset = dom.fieldset(dom.label('Received ID', attr.title('The ID in the Received header that was added during incoming delivery.')), ' ', recvID = dom.input(attr.required('')), ' ', dom.submitbutton('Lookup cid', attr.title('Logging about an incoming message includes an attribute "cid", a counter identifying the transaction related to delivery of the message. The ID in the received header is an encrypted cid, which this form decrypts, after which you can look it up in the logging.')), ' ', cidElem = dom.span()))),
|
||||||
// todo: routing, globally, per domain and per account
|
// todo: routing, globally, per domain and per account
|
||||||
dom.br(), dom.h2('Configuration'), dom.div(dom.a('Webserver', attr.href('#webserver'))), dom.div(dom.a('Files', attr.href('#config'))), dom.div(dom.a('Log levels', attr.href('#loglevels'))), footer);
|
dom.br(), dom.h2('Configuration'), dom.div(dom.a('Routes', attr.href('#routes'))), dom.div(dom.a('Webserver', attr.href('#webserver'))), dom.div(dom.a('Files', attr.href('#config'))), dom.div(dom.a('Log levels', attr.href('#loglevels'))), footer);
|
||||||
|
};
|
||||||
|
const globalRoutes = async () => {
|
||||||
|
const [transports, config] = await Promise.all([
|
||||||
|
client.Transports(),
|
||||||
|
client.Config(),
|
||||||
|
]);
|
||||||
|
dom._kids(page, crumbs(crumblink('Mox Admin', '#'), 'Routes'), RoutesEditor('global', transports, config.Routes || [], async (routes) => await client.RoutesSave(routes)));
|
||||||
};
|
};
|
||||||
const config = async () => {
|
const config = async () => {
|
||||||
const [staticPath, dynamicPath, staticText, dynamicText] = await client.ConfigFiles();
|
const [staticPath, dynamicPath, staticText, dynamicText] = await client.ConfigFiles();
|
||||||
|
@ -1945,10 +2008,69 @@ const formatQuotaSize = (v) => {
|
||||||
}
|
}
|
||||||
return '' + v;
|
return '' + v;
|
||||||
};
|
};
|
||||||
|
const RoutesEditor = (kind, transports, routes, save) => {
|
||||||
|
const transportNames = Object.keys(transports || {});
|
||||||
|
transportNames.sort();
|
||||||
|
const hdr = dom.h2('Routes', attr.title('Messages submitted to the queue for outgoing delivery are delivered directly to the MX records of the recipient domain by default. However, other "transports" can be configured, such as SMTP submission/relay or connecting through a SOCKS proxy. Routes with matching rules and a transport can be configured for accounts, domains and globally. Routes are evaluated in that order, the first match is applied.'));
|
||||||
|
let routesElem;
|
||||||
|
const render = () => {
|
||||||
|
if (transportNames.length === 0) {
|
||||||
|
return [hdr, dom.p('No transports configured.', attr.title('To configure routes, first configure transports via the mox.conf config file.'))];
|
||||||
|
}
|
||||||
|
let routesFieldset;
|
||||||
|
let routeRows = [];
|
||||||
|
let elem = dom.form(async function submit(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
await check(routesFieldset, save(routeRows.map(rr => rr.gather())));
|
||||||
|
}, routesFieldset = dom.fieldset(dom.table(dom.thead(dom.tr(dom.th('From domain'), dom.th('To domain'), dom.th('Minimum attempts'), dom.th('Transport'), dom.th(dom.clickbutton('Add', function click() {
|
||||||
|
routes = routeRows.map(rr => rr.gather());
|
||||||
|
routes.push({ FromDomain: [], ToDomain: [], MinimumAttempts: 0, Transport: transportNames[0] });
|
||||||
|
render();
|
||||||
|
})))), dom.tbody((routes || []).length === 0 ? dom.tr(dom.td(attr.colspan('5'), 'No routes.')) : [], routeRows = (routes || []).map((r, index) => {
|
||||||
|
let fromDomain = dom.input(attr.value((r.FromDomain || []).join(',')));
|
||||||
|
let toDomain = dom.input(attr.value((r.ToDomain || []).join(',')));
|
||||||
|
let minimumAttempts = dom.input(attr.value('' + r.MinimumAttempts));
|
||||||
|
let transport = dom.select(attr.required(''), transportNames.map(s => dom.option(s, s === r.Transport ? attr.selected('') : [])));
|
||||||
|
const tr = dom.tr(dom.td(fromDomain), dom.td(toDomain), dom.td(minimumAttempts), dom.td(transport), dom.td(dom.clickbutton('Remove', function click() {
|
||||||
|
routeRows.splice(index, 1);
|
||||||
|
routes = routeRows.map(rr => rr.gather());
|
||||||
|
render();
|
||||||
|
})));
|
||||||
|
return {
|
||||||
|
root: tr,
|
||||||
|
gather: () => {
|
||||||
|
return {
|
||||||
|
FromDomain: fromDomain.value ? fromDomain.value.split(',') : [],
|
||||||
|
ToDomain: toDomain.value ? toDomain.value.split(',') : [],
|
||||||
|
MinimumAttempts: parseInt(minimumAttempts.value) || 0,
|
||||||
|
Transport: transport.value,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}))), dom.div(dom.submitbutton('Save'))));
|
||||||
|
if (!routesElem && (routes || []).length === 0) {
|
||||||
|
// Keep it short.
|
||||||
|
elem = dom.div('No ' + kind + ' routes configured. ', dom.clickbutton('Add', function click() {
|
||||||
|
routes = routeRows.map(rr => rr.gather());
|
||||||
|
routes.push({ FromDomain: [], ToDomain: [], MinimumAttempts: 0, Transport: transportNames[0] });
|
||||||
|
render();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
elem = dom.div(hdr, elem);
|
||||||
|
if (routesElem) {
|
||||||
|
routesElem.replaceWith(elem);
|
||||||
|
}
|
||||||
|
routesElem = elem;
|
||||||
|
return elem;
|
||||||
|
};
|
||||||
|
return render();
|
||||||
|
};
|
||||||
const account = async (name) => {
|
const account = async (name) => {
|
||||||
const [[config, diskUsage], domains] = await Promise.all([
|
const [[config, diskUsage], domains, transports] = await Promise.all([
|
||||||
client.Account(name),
|
client.Account(name),
|
||||||
client.Domains(),
|
client.Domains(),
|
||||||
|
client.Transports(),
|
||||||
]);
|
]);
|
||||||
// todo: show suppression list, and buttons to add/remove entries.
|
// todo: show suppression list, and buttons to add/remove entries.
|
||||||
let form;
|
let form;
|
||||||
|
@ -2044,7 +2166,7 @@ const account = async (name) => {
|
||||||
await check(fieldsetPassword, client.SetPassword(name, password.value));
|
await check(fieldsetPassword, client.SetPassword(name, password.value));
|
||||||
window.alert('Password has been changed.');
|
window.alert('Password has been changed.');
|
||||||
formPassword.reset();
|
formPassword.reset();
|
||||||
}), dom.br(), dom.h2('Danger'), dom.clickbutton('Remove account', async function click(e) {
|
}), dom.br(), RoutesEditor('account-specific', transports, config.Routes || [], async (routes) => await client.AccountRoutesSave(name, routes)), dom.br(), dom.h2('Danger'), dom.clickbutton('Remove account', async function click(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!window.confirm('Are you sure you want to remove this account?')) {
|
if (!window.confirm('Are you sure you want to remove this account?')) {
|
||||||
return;
|
return;
|
||||||
|
@ -2056,13 +2178,15 @@ const account = async (name) => {
|
||||||
const domain = async (d) => {
|
const domain = async (d) => {
|
||||||
const end = new Date();
|
const end = new Date();
|
||||||
const start = new Date(new Date().getTime() - 30 * 24 * 3600 * 1000);
|
const start = new Date(new Date().getTime() - 30 * 24 * 3600 * 1000);
|
||||||
const [dmarcSummaries, tlsrptSummaries, localpartAccounts, dnsdomain, clientConfigs, accounts] = await Promise.all([
|
const [dmarcSummaries, tlsrptSummaries, localpartAccounts, dnsdomain, clientConfigs, accounts, domainConfig, transports] = await Promise.all([
|
||||||
client.DMARCSummaries(start, end, d),
|
client.DMARCSummaries(start, end, d),
|
||||||
client.TLSRPTSummaries(start, end, d),
|
client.TLSRPTSummaries(start, end, d),
|
||||||
client.DomainLocalparts(d),
|
client.DomainLocalparts(d),
|
||||||
client.Domain(d),
|
client.ParseDomain(d),
|
||||||
client.ClientConfigsDomain(d),
|
client.ClientConfigsDomain(d),
|
||||||
client.Accounts(),
|
client.Accounts(),
|
||||||
|
client.DomainConfig(d),
|
||||||
|
client.Transports(),
|
||||||
]);
|
]);
|
||||||
let form;
|
let form;
|
||||||
let fieldset;
|
let fieldset;
|
||||||
|
@ -2081,7 +2205,7 @@ const domain = async (d) => {
|
||||||
await check(fieldset, client.AddressAdd(localpart.value + '@' + d, account.value));
|
await check(fieldset, client.AddressAdd(localpart.value + '@' + d, account.value));
|
||||||
form.reset();
|
form.reset();
|
||||||
window.location.reload(); // todo: only reload the addresses
|
window.location.reload(); // todo: only reload the addresses
|
||||||
}, fieldset = dom.fieldset(dom.label(style({ display: 'inline-block' }), dom.span('Localpart', attr.title('The localpart is the part before the "@"-sign of an address. An empty localpart is the catchall destination/address for the domain.')), dom.br(), localpart = dom.input()), '@', domainName(dnsdomain), ' ', dom.label(style({ display: 'inline-block' }), dom.span('Account', attr.title('Account to assign the address to.')), dom.br(), account = dom.select(attr.required(''), (accounts || []).map(a => dom.option(a)))), ' ', dom.submitbutton('Add address', attr.title('Address will be added and the config reloaded.')))), dom.br(), dom.h2('External checks'), dom.ul(dom.li(link('https://internet.nl/mail/' + dnsdomain.ASCII + '/', 'Check configuration at internet.nl'))), dom.br(), dom.h2('Danger'), dom.clickbutton('Remove domain', async function click(e) {
|
}, fieldset = dom.fieldset(dom.label(style({ display: 'inline-block' }), dom.span('Localpart', attr.title('The localpart is the part before the "@"-sign of an address. An empty localpart is the catchall destination/address for the domain.')), dom.br(), localpart = dom.input()), '@', domainName(dnsdomain), ' ', dom.label(style({ display: 'inline-block' }), dom.span('Account', attr.title('Account to assign the address to.')), dom.br(), account = dom.select(attr.required(''), (accounts || []).map(a => dom.option(a)))), ' ', dom.submitbutton('Add address', attr.title('Address will be added and the config reloaded.')))), dom.br(), RoutesEditor('domain-specific', transports, domainConfig.Routes || [], async (routes) => await client.DomainRoutesSave(d, routes)), dom.br(), dom.h2('External checks'), dom.ul(dom.li(link('https://internet.nl/mail/' + dnsdomain.ASCII + '/', 'Check configuration at internet.nl'))), dom.br(), dom.h2('Danger'), dom.clickbutton('Remove domain', async function click(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!window.confirm('Are you sure you want to remove this domain?')) {
|
if (!window.confirm('Are you sure you want to remove this domain?')) {
|
||||||
return;
|
return;
|
||||||
|
@ -2093,14 +2217,14 @@ const domain = async (d) => {
|
||||||
const domainDNSRecords = async (d) => {
|
const domainDNSRecords = async (d) => {
|
||||||
const [records, dnsdomain] = await Promise.all([
|
const [records, dnsdomain] = await Promise.all([
|
||||||
client.DomainRecords(d),
|
client.DomainRecords(d),
|
||||||
client.Domain(d),
|
client.ParseDomain(d),
|
||||||
]);
|
]);
|
||||||
dom._kids(page, crumbs(crumblink('Mox Admin', '#'), crumblink('Domain ' + domainString(dnsdomain), '#domains/' + d), 'DNS Records'), dom.h1('Required DNS records'), dom.pre('pre', dom._class('literal'), (records || []).join('\n')), dom.br());
|
dom._kids(page, crumbs(crumblink('Mox Admin', '#'), crumblink('Domain ' + domainString(dnsdomain), '#domains/' + d), 'DNS Records'), dom.h1('Required DNS records'), dom.pre('pre', dom._class('literal'), (records || []).join('\n')), dom.br());
|
||||||
};
|
};
|
||||||
const domainDNSCheck = async (d) => {
|
const domainDNSCheck = async (d) => {
|
||||||
const [checks, dnsdomain] = await Promise.all([
|
const [checks, dnsdomain] = await Promise.all([
|
||||||
client.CheckDomain(d),
|
client.CheckDomain(d),
|
||||||
client.Domain(d),
|
client.ParseDomain(d),
|
||||||
]);
|
]);
|
||||||
const resultSection = (title, r, details) => {
|
const resultSection = (title, r, details) => {
|
||||||
let success = [];
|
let success = [];
|
||||||
|
@ -3590,6 +3714,9 @@ const init = async () => {
|
||||||
else if (h === 'dnsbl') {
|
else if (h === 'dnsbl') {
|
||||||
await dnsbl();
|
await dnsbl();
|
||||||
}
|
}
|
||||||
|
else if (h === 'routes') {
|
||||||
|
await globalRoutes();
|
||||||
|
}
|
||||||
else if (h === 'webserver') {
|
else if (h === 'webserver') {
|
||||||
await webserver();
|
await webserver();
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,6 +421,7 @@ const index = async () => {
|
||||||
// todo: routing, globally, per domain and per account
|
// todo: routing, globally, per domain and per account
|
||||||
dom.br(),
|
dom.br(),
|
||||||
dom.h2('Configuration'),
|
dom.h2('Configuration'),
|
||||||
|
dom.div(dom.a('Routes', attr.href('#routes'))),
|
||||||
dom.div(dom.a('Webserver', attr.href('#webserver'))),
|
dom.div(dom.a('Webserver', attr.href('#webserver'))),
|
||||||
dom.div(dom.a('Files', attr.href('#config'))),
|
dom.div(dom.a('Files', attr.href('#config'))),
|
||||||
dom.div(dom.a('Log levels', attr.href('#loglevels'))),
|
dom.div(dom.a('Log levels', attr.href('#loglevels'))),
|
||||||
|
@ -428,6 +429,21 @@ const index = async () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const globalRoutes = async () => {
|
||||||
|
const [transports, config] = await Promise.all([
|
||||||
|
client.Transports(),
|
||||||
|
client.Config(),
|
||||||
|
])
|
||||||
|
|
||||||
|
dom._kids(page,
|
||||||
|
crumbs(
|
||||||
|
crumblink('Mox Admin', '#'),
|
||||||
|
'Routes',
|
||||||
|
),
|
||||||
|
RoutesEditor('global', transports, config.Routes || [], async (routes: api.Route[]) => await client.RoutesSave(routes)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const config = async () => {
|
const config = async () => {
|
||||||
const [staticPath, dynamicPath, staticText, dynamicText] = await client.ConfigFiles()
|
const [staticPath, dynamicPath, staticText, dynamicText] = await client.ConfigFiles()
|
||||||
|
|
||||||
|
@ -635,10 +651,112 @@ const formatQuotaSize = (v: number) => {
|
||||||
return ''+v
|
return ''+v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RoutesEditor = (kind: string, transports: { [key: string]: api.Transport }, routes: api.Route[], save: (routes: api.Route[]) => Promise<void>) => {
|
||||||
|
const transportNames = Object.keys(transports || {})
|
||||||
|
transportNames.sort()
|
||||||
|
|
||||||
|
const hdr = dom.h2('Routes', attr.title('Messages submitted to the queue for outgoing delivery are delivered directly to the MX records of the recipient domain by default. However, other "transports" can be configured, such as SMTP submission/relay or connecting through a SOCKS proxy. Routes with matching rules and a transport can be configured for accounts, domains and globally. Routes are evaluated in that order, the first match is applied.'))
|
||||||
|
|
||||||
|
let routesElem: HTMLElement
|
||||||
|
const render = () => {
|
||||||
|
if (transportNames.length === 0) {
|
||||||
|
return [hdr, dom.p('No transports configured.', attr.title('To configure routes, first configure transports via the mox.conf config file.'))]
|
||||||
|
}
|
||||||
|
|
||||||
|
let routesFieldset: HTMLFieldSetElement
|
||||||
|
interface RouteRow {
|
||||||
|
root: HTMLElement
|
||||||
|
gather: () => api.Route
|
||||||
|
}
|
||||||
|
let routeRows: RouteRow[] = []
|
||||||
|
|
||||||
|
let elem: HTMLElement = dom.form(
|
||||||
|
async function submit(e: SubmitEvent) {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
await check(routesFieldset, save(routeRows.map(rr => rr.gather())))
|
||||||
|
},
|
||||||
|
routesFieldset=dom.fieldset(
|
||||||
|
dom.table(
|
||||||
|
dom.thead(
|
||||||
|
dom.tr(
|
||||||
|
dom.th('From domain'),
|
||||||
|
dom.th('To domain'),
|
||||||
|
dom.th('Minimum attempts'),
|
||||||
|
dom.th('Transport'),
|
||||||
|
dom.th(
|
||||||
|
dom.clickbutton('Add', function click() {
|
||||||
|
routes = routeRows.map(rr => rr.gather())
|
||||||
|
routes.push({FromDomain: [], ToDomain: [], MinimumAttempts: 0, Transport: transportNames[0]})
|
||||||
|
render()
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dom.tbody(
|
||||||
|
(routes || []).length === 0 ? dom.tr(dom.td(attr.colspan('5'), 'No routes.')) : [],
|
||||||
|
routeRows=(routes || []).map((r, index) => {
|
||||||
|
let fromDomain = dom.input(attr.value((r.FromDomain || []).join(',')))
|
||||||
|
let toDomain = dom.input(attr.value((r.ToDomain || []).join(',')))
|
||||||
|
let minimumAttempts = dom.input(attr.value(''+r.MinimumAttempts))
|
||||||
|
let transport = dom.select(attr.required(''), transportNames.map(s => dom.option(s, s === r.Transport ? attr.selected('') : [])))
|
||||||
|
|
||||||
|
const tr = dom.tr(
|
||||||
|
dom.td(fromDomain),
|
||||||
|
dom.td(toDomain),
|
||||||
|
dom.td(minimumAttempts),
|
||||||
|
dom.td(transport),
|
||||||
|
dom.td(
|
||||||
|
dom.clickbutton('Remove', function click() {
|
||||||
|
routeRows.splice(index, 1)
|
||||||
|
routes = routeRows.map(rr => rr.gather())
|
||||||
|
render()
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
root: tr,
|
||||||
|
gather: (): api.Route => {
|
||||||
|
return {
|
||||||
|
FromDomain: fromDomain.value ? fromDomain.value.split(',') : [],
|
||||||
|
ToDomain: toDomain.value ? toDomain.value.split(',') : [],
|
||||||
|
MinimumAttempts: parseInt(minimumAttempts.value) || 0,
|
||||||
|
Transport: transport.value,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dom.div(dom.submitbutton('Save')),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if (!routesElem && (routes || []).length === 0) {
|
||||||
|
// Keep it short.
|
||||||
|
elem = dom.div(
|
||||||
|
'No '+kind+' routes configured. ',
|
||||||
|
dom.clickbutton('Add', function click() {
|
||||||
|
routes = routeRows.map(rr => rr.gather())
|
||||||
|
routes.push({FromDomain: [], ToDomain: [], MinimumAttempts: 0, Transport: transportNames[0]})
|
||||||
|
render()
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
elem = dom.div(hdr, elem)
|
||||||
|
if (routesElem) {
|
||||||
|
routesElem.replaceWith(elem)
|
||||||
|
}
|
||||||
|
routesElem = elem
|
||||||
|
return elem
|
||||||
|
}
|
||||||
|
return render()
|
||||||
|
}
|
||||||
|
|
||||||
const account = async (name: string) => {
|
const account = async (name: string) => {
|
||||||
const [[config, diskUsage], domains] = await Promise.all([
|
const [[config, diskUsage], domains, transports] = await Promise.all([
|
||||||
client.Account(name),
|
client.Account(name),
|
||||||
client.Domains(),
|
client.Domains(),
|
||||||
|
client.Transports(),
|
||||||
])
|
])
|
||||||
|
|
||||||
// todo: show suppression list, and buttons to add/remove entries.
|
// todo: show suppression list, and buttons to add/remove entries.
|
||||||
|
@ -839,6 +957,9 @@ const account = async (name: string) => {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
dom.br(),
|
dom.br(),
|
||||||
|
RoutesEditor('account-specific', transports, config.Routes || [], async (routes: api.Route[]) => await client.AccountRoutesSave(name, routes)),
|
||||||
|
dom.br(),
|
||||||
|
|
||||||
dom.h2('Danger'),
|
dom.h2('Danger'),
|
||||||
dom.clickbutton('Remove account', async function click(e: MouseEvent) {
|
dom.clickbutton('Remove account', async function click(e: MouseEvent) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -854,13 +975,15 @@ const account = async (name: string) => {
|
||||||
const domain = async (d: string) => {
|
const domain = async (d: string) => {
|
||||||
const end = new Date()
|
const end = new Date()
|
||||||
const start = new Date(new Date().getTime() - 30*24*3600*1000)
|
const start = new Date(new Date().getTime() - 30*24*3600*1000)
|
||||||
const [dmarcSummaries, tlsrptSummaries, localpartAccounts, dnsdomain, clientConfigs, accounts] = await Promise.all([
|
const [dmarcSummaries, tlsrptSummaries, localpartAccounts, dnsdomain, clientConfigs, accounts, domainConfig, transports] = await Promise.all([
|
||||||
client.DMARCSummaries(start, end, d),
|
client.DMARCSummaries(start, end, d),
|
||||||
client.TLSRPTSummaries(start, end, d),
|
client.TLSRPTSummaries(start, end, d),
|
||||||
client.DomainLocalparts(d),
|
client.DomainLocalparts(d),
|
||||||
client.Domain(d),
|
client.ParseDomain(d),
|
||||||
client.ClientConfigsDomain(d),
|
client.ClientConfigsDomain(d),
|
||||||
client.Accounts(),
|
client.Accounts(),
|
||||||
|
client.DomainConfig(d),
|
||||||
|
client.Transports(),
|
||||||
])
|
])
|
||||||
|
|
||||||
let form: HTMLFormElement
|
let form: HTMLFormElement
|
||||||
|
@ -961,6 +1084,8 @@ const domain = async (d: string) => {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dom.br(),
|
dom.br(),
|
||||||
|
RoutesEditor('domain-specific', transports, domainConfig.Routes || [], async (routes: api.Route[]) => await client.DomainRoutesSave(d, routes)),
|
||||||
|
dom.br(),
|
||||||
dom.h2('External checks'),
|
dom.h2('External checks'),
|
||||||
dom.ul(
|
dom.ul(
|
||||||
dom.li(link('https://internet.nl/mail/'+dnsdomain.ASCII+'/', 'Check configuration at internet.nl')),
|
dom.li(link('https://internet.nl/mail/'+dnsdomain.ASCII+'/', 'Check configuration at internet.nl')),
|
||||||
|
@ -981,7 +1106,7 @@ const domain = async (d: string) => {
|
||||||
const domainDNSRecords = async (d: string) => {
|
const domainDNSRecords = async (d: string) => {
|
||||||
const [records, dnsdomain] = await Promise.all([
|
const [records, dnsdomain] = await Promise.all([
|
||||||
client.DomainRecords(d),
|
client.DomainRecords(d),
|
||||||
client.Domain(d),
|
client.ParseDomain(d),
|
||||||
])
|
])
|
||||||
|
|
||||||
dom._kids(page,
|
dom._kids(page,
|
||||||
|
@ -999,7 +1124,7 @@ const domainDNSRecords = async (d: string) => {
|
||||||
const domainDNSCheck = async (d: string) => {
|
const domainDNSCheck = async (d: string) => {
|
||||||
const [checks, dnsdomain] = await Promise.all([
|
const [checks, dnsdomain] = await Promise.all([
|
||||||
client.CheckDomain(d),
|
client.CheckDomain(d),
|
||||||
client.Domain(d),
|
client.ParseDomain(d),
|
||||||
])
|
])
|
||||||
|
|
||||||
interface Result {
|
interface Result {
|
||||||
|
@ -4184,6 +4309,8 @@ const init = async () => {
|
||||||
await mtasts()
|
await mtasts()
|
||||||
} else if (h === 'dnsbl') {
|
} else if (h === 'dnsbl') {
|
||||||
await dnsbl()
|
await dnsbl()
|
||||||
|
} else if (h === 'routes') {
|
||||||
|
await globalRoutes()
|
||||||
} else if (h === 'webserver') {
|
} else if (h === 'webserver') {
|
||||||
await webserver()
|
await webserver()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -209,10 +209,18 @@ func TestAdminAuth(t *testing.T) {
|
||||||
|
|
||||||
api.Logout(ctx)
|
api.Logout(ctx)
|
||||||
tneedErrorCode(t, "server:error", func() { api.Logout(ctx) })
|
tneedErrorCode(t, "server:error", func() { api.Logout(ctx) })
|
||||||
|
}
|
||||||
|
|
||||||
err = queue.Init()
|
func TestAdmin(t *testing.T) {
|
||||||
|
os.RemoveAll("../testdata/webadmin/data")
|
||||||
|
mox.ConfigStaticPath = filepath.FromSlash("../testdata/webadmin/mox.conf")
|
||||||
|
mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf")
|
||||||
|
mox.MustLoadConfig(true, false)
|
||||||
|
err := queue.Init()
|
||||||
tcheck(t, err, "queue init")
|
tcheck(t, err, "queue init")
|
||||||
|
|
||||||
|
api := Admin{}
|
||||||
|
|
||||||
mrl := api.RetiredList(ctxbg, queue.RetiredFilter{}, queue.RetiredSort{})
|
mrl := api.RetiredList(ctxbg, queue.RetiredFilter{}, queue.RetiredSort{})
|
||||||
tcompare(t, len(mrl), 0)
|
tcompare(t, len(mrl), 0)
|
||||||
|
|
||||||
|
@ -233,6 +241,22 @@ func TestAdminAuth(t *testing.T) {
|
||||||
|
|
||||||
n = api.HookCancel(ctxbg, queue.HookFilter{})
|
n = api.HookCancel(ctxbg, queue.HookFilter{})
|
||||||
tcompare(t, n, 0)
|
tcompare(t, n, 0)
|
||||||
|
|
||||||
|
api.Config(ctxbg)
|
||||||
|
api.DomainConfig(ctxbg, "mox.example")
|
||||||
|
tneedErrorCode(t, "user:error", func() { api.DomainConfig(ctxbg, "bogus.example") })
|
||||||
|
|
||||||
|
api.AccountRoutesSave(ctxbg, "mjl", []config.Route{{Transport: "direct"}})
|
||||||
|
tneedErrorCode(t, "user:error", func() { api.AccountRoutesSave(ctxbg, "mjl", []config.Route{{Transport: "bogus"}}) })
|
||||||
|
api.AccountRoutesSave(ctxbg, "mjl", nil)
|
||||||
|
|
||||||
|
api.DomainRoutesSave(ctxbg, "mox.example", []config.Route{{Transport: "direct"}})
|
||||||
|
tneedErrorCode(t, "user:error", func() { api.DomainRoutesSave(ctxbg, "mox.example", []config.Route{{Transport: "bogus"}}) })
|
||||||
|
api.DomainRoutesSave(ctxbg, "mox.example", nil)
|
||||||
|
|
||||||
|
api.RoutesSave(ctxbg, []config.Route{{Transport: "direct"}})
|
||||||
|
tneedErrorCode(t, "user:error", func() { api.RoutesSave(ctxbg, []config.Route{{Transport: "bogus"}}) })
|
||||||
|
api.RoutesSave(ctxbg, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckDomain(t *testing.T) {
|
func TestCheckDomain(t *testing.T) {
|
||||||
|
|
|
@ -121,6 +121,26 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "DomainConfig",
|
||||||
|
"Docs": "DomainConfig returns the configuration for a domain.",
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "domain",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Returns": [
|
||||||
|
{
|
||||||
|
"Name": "r0",
|
||||||
|
"Typewords": [
|
||||||
|
"ConfigDomain"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "DomainLocalparts",
|
"Name": "DomainLocalparts",
|
||||||
"Docs": "DomainLocalparts returns the encoded localparts and accounts configured in domain.",
|
"Docs": "DomainLocalparts returns the encoded localparts and accounts configured in domain.",
|
||||||
|
@ -1528,6 +1548,73 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Config",
|
||||||
|
"Docs": "Config returns the dynamic config.",
|
||||||
|
"Params": [],
|
||||||
|
"Returns": [
|
||||||
|
{
|
||||||
|
"Name": "r0",
|
||||||
|
"Typewords": [
|
||||||
|
"Dynamic"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "AccountRoutesSave",
|
||||||
|
"Docs": "AccountRoutesSave saves routes for an account.",
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "accountName",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "routes",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"Route"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Returns": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DomainRoutesSave",
|
||||||
|
"Docs": "DomainRoutesSave saves routes for a domain.",
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "domainName",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "routes",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"Route"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Returns": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "RoutesSave",
|
||||||
|
"Docs": "RoutesSave saves global routes.",
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "routes",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"Route"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Returns": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Sections": [],
|
"Sections": [],
|
||||||
|
@ -2794,6 +2881,368 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "ConfigDomain",
|
||||||
|
"Docs": "",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"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": "DKIM",
|
||||||
|
"Docs": "",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "Selectors",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"{}",
|
||||||
|
"Selector"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Sign",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": "Used when signing. Based on Headers from config, or the reasonable default.",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DontSealHeaders",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"bool"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Expiration",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "PrivateKeyFile",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Canonicalization",
|
||||||
|
"Docs": "",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "HeaderRelaxed",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"bool"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "BodyRelaxed",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"bool"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DMARC",
|
||||||
|
"Docs": "",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "Localpart",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Domain",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Account",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Mailbox",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ParsedLocalpart",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"Localpart"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DNSDomain",
|
||||||
|
"Docs": "Effective domain, always set based on Domain field or Domain where this is configured.",
|
||||||
|
"Typewords": [
|
||||||
|
"Domain"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "MTASTS",
|
||||||
|
"Docs": "",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "PolicyID",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Mode",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"Mode"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "MaxAge",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"int64"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "MX",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "TLSRPT",
|
||||||
|
"Docs": "",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "Localpart",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Domain",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Account",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Mailbox",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ParsedLocalpart",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"Localpart"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DNSDomain",
|
||||||
|
"Docs": "Effective domain, always set based on Domain field or Domain where this is configured.",
|
||||||
|
"Typewords": [
|
||||||
|
"Domain"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Route",
|
||||||
|
"Docs": "",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "FromDomain",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ToDomain",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "MinimumAttempts",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"int32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Transport",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "FromDomainASCII",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ToDomainASCII",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "Account",
|
"Name": "Account",
|
||||||
"Docs": "",
|
"Docs": "",
|
||||||
|
@ -3201,58 +3650,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Name": "Route",
|
|
||||||
"Docs": "",
|
|
||||||
"Fields": [
|
|
||||||
{
|
|
||||||
"Name": "FromDomain",
|
|
||||||
"Docs": "",
|
|
||||||
"Typewords": [
|
|
||||||
"[]",
|
|
||||||
"string"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "ToDomain",
|
|
||||||
"Docs": "",
|
|
||||||
"Typewords": [
|
|
||||||
"[]",
|
|
||||||
"string"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "MinimumAttempts",
|
|
||||||
"Docs": "",
|
|
||||||
"Typewords": [
|
|
||||||
"int32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Transport",
|
|
||||||
"Docs": "",
|
|
||||||
"Typewords": [
|
|
||||||
"string"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "FromDomainASCII",
|
|
||||||
"Docs": "",
|
|
||||||
"Typewords": [
|
|
||||||
"[]",
|
|
||||||
"string"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "ToDomainASCII",
|
|
||||||
"Docs": "",
|
|
||||||
"Typewords": [
|
|
||||||
"[]",
|
|
||||||
"string"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Name": "PolicyRecord",
|
"Name": "PolicyRecord",
|
||||||
"Docs": "PolicyRecord is a cached policy or absence of a policy.",
|
"Docs": "PolicyRecord is a cached policy or absence of a policy.",
|
||||||
|
@ -6153,6 +6550,68 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Dynamic",
|
||||||
|
"Docs": "Dynamic is the parsed form of domains.conf, and is automatically reloaded when changed.",
|
||||||
|
"Fields": [
|
||||||
|
{
|
||||||
|
"Name": "Domains",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"{}",
|
||||||
|
"ConfigDomain"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Accounts",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"{}",
|
||||||
|
"Account"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "WebDomainRedirects",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"{}",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "WebHandlers",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"WebHandler"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Routes",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"Route"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "MonitorDNSBLs",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "MonitorDNSBLZones",
|
||||||
|
"Docs": "",
|
||||||
|
"Typewords": [
|
||||||
|
"[]",
|
||||||
|
"Domain"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Ints": [],
|
"Ints": [],
|
||||||
|
@ -6230,6 +6689,11 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Name": "Localpart",
|
||||||
|
"Docs": "Localpart is a decoded local part of an email address, before the \"@\".\nFor quoted strings, values do not hold the double quote or escaping backslashes.\nAn empty string can be a valid localpart.\nLocalparts are in Unicode NFC.",
|
||||||
|
"Values": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Name": "PolicyType",
|
"Name": "PolicyType",
|
||||||
"Docs": "PolicyType indicates the policy success/failure results are for.",
|
"Docs": "PolicyType indicates the policy success/failure results are for.",
|
||||||
|
@ -6534,11 +6998,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Name": "Localpart",
|
|
||||||
"Docs": "Localpart is a decoded local part of an email address, before the \"@\".\nFor quoted strings, values do not hold the double quote or escaping backslashes.\nAn empty string can be a valid localpart.\nLocalparts are in Unicode NFC.",
|
|
||||||
"Values": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Name": "IP",
|
"Name": "IP",
|
||||||
"Docs": "An IP is a single IP address, a slice of bytes.\nFunctions in this package accept either 4-byte (IPv4)\nor 16-byte (IPv6) slices as input.\n\nNote that in this documentation, referring to an\nIP address as an IPv4 address or an IPv6 address\nis a semantic property of the address, not just the\nlength of the byte slice: a 16-byte slice can still\nbe an IPv4 address.",
|
"Docs": "An IP is a single IP address, a slice of bytes.\nFunctions in this package accept either 4-byte (IPv4)\nor 16-byte (IPv6) slices as input.\n\nNote that in this documentation, referring to an\nIP address as an IPv4 address or an IPv6 address\nis a semantic property of the address, not just the\nlength of the byte slice: a 16-byte slice can still\nbe an IPv4 address.",
|
||||||
|
|
170
webadmin/api.ts
170
webadmin/api.ts
|
@ -266,6 +266,73 @@ export interface AutodiscoverSRV {
|
||||||
IPs?: string[] | null
|
IPs?: string[] | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConfigDomain {
|
||||||
|
Description: string
|
||||||
|
ClientSettingsDomain: string
|
||||||
|
LocalpartCatchallSeparator: string
|
||||||
|
LocalpartCaseSensitive: boolean
|
||||||
|
DKIM: DKIM
|
||||||
|
DMARC?: DMARC | null
|
||||||
|
MTASTS?: MTASTS | null
|
||||||
|
TLSRPT?: TLSRPT | null
|
||||||
|
Routes?: Route[] | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DKIM {
|
||||||
|
Selectors?: { [key: string]: Selector }
|
||||||
|
Sign?: string[] | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Selector {
|
||||||
|
Hash: string
|
||||||
|
HashEffective: string
|
||||||
|
Canonicalization: Canonicalization
|
||||||
|
Headers?: string[] | null
|
||||||
|
HeadersEffective?: string[] | null // Used when signing. Based on Headers from config, or the reasonable default.
|
||||||
|
DontSealHeaders: boolean
|
||||||
|
Expiration: string
|
||||||
|
PrivateKeyFile: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Canonicalization {
|
||||||
|
HeaderRelaxed: boolean
|
||||||
|
BodyRelaxed: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DMARC {
|
||||||
|
Localpart: string
|
||||||
|
Domain: string
|
||||||
|
Account: string
|
||||||
|
Mailbox: string
|
||||||
|
ParsedLocalpart: Localpart
|
||||||
|
DNSDomain: Domain // Effective domain, always set based on Domain field or Domain where this is configured.
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MTASTS {
|
||||||
|
PolicyID: string
|
||||||
|
Mode: Mode
|
||||||
|
MaxAge: number
|
||||||
|
MX?: string[] | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TLSRPT {
|
||||||
|
Localpart: string
|
||||||
|
Domain: string
|
||||||
|
Account: string
|
||||||
|
Mailbox: string
|
||||||
|
ParsedLocalpart: Localpart
|
||||||
|
DNSDomain: Domain // Effective domain, always set based on Domain field or Domain where this is configured.
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Route {
|
||||||
|
FromDomain?: string[] | null
|
||||||
|
ToDomain?: string[] | null
|
||||||
|
MinimumAttempts: number
|
||||||
|
Transport: string
|
||||||
|
FromDomainASCII?: string[] | null
|
||||||
|
ToDomainASCII?: string[] | null
|
||||||
|
}
|
||||||
|
|
||||||
export interface Account {
|
export interface Account {
|
||||||
OutgoingWebhook?: OutgoingWebhook | null
|
OutgoingWebhook?: OutgoingWebhook | null
|
||||||
IncomingWebhook?: IncomingWebhook | null
|
IncomingWebhook?: IncomingWebhook | null
|
||||||
|
@ -340,15 +407,6 @@ export interface JunkFilter {
|
||||||
RareWords: number
|
RareWords: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Route {
|
|
||||||
FromDomain?: string[] | null
|
|
||||||
ToDomain?: string[] | null
|
|
||||||
MinimumAttempts: number
|
|
||||||
Transport: string
|
|
||||||
FromDomainASCII?: string[] | null
|
|
||||||
ToDomainASCII?: string[] | null
|
|
||||||
}
|
|
||||||
|
|
||||||
// PolicyRecord is a cached policy or absence of a policy.
|
// PolicyRecord is a cached policy or absence of a policy.
|
||||||
export interface PolicyRecord {
|
export interface PolicyRecord {
|
||||||
Domain: string // Domain name, with unicode characters.
|
Domain: string // Domain name, with unicode characters.
|
||||||
|
@ -946,6 +1004,17 @@ export interface TLSRPTSuppressAddress {
|
||||||
Comment: string
|
Comment: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dynamic is the parsed form of domains.conf, and is automatically reloaded when changed.
|
||||||
|
export interface Dynamic {
|
||||||
|
Domains?: { [key: string]: ConfigDomain }
|
||||||
|
Accounts?: { [key: string]: Account }
|
||||||
|
WebDomainRedirects?: { [key: string]: string }
|
||||||
|
WebHandlers?: WebHandler[] | null
|
||||||
|
Routes?: Route[] | null
|
||||||
|
MonitorDNSBLs?: string[] | null
|
||||||
|
MonitorDNSBLZones?: Domain[] | null
|
||||||
|
}
|
||||||
|
|
||||||
export type CSRFToken = string
|
export type CSRFToken = string
|
||||||
|
|
||||||
// Policy as used in DMARC DNS record for "p=" or "sp=".
|
// Policy as used in DMARC DNS record for "p=" or "sp=".
|
||||||
|
@ -973,6 +1042,12 @@ export enum Mode {
|
||||||
ModeNone = "none", // In case MTA-STS is not or no longer implemented.
|
ModeNone = "none", // In case MTA-STS is not or no longer implemented.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Localpart is a decoded local part of an email address, before the "@".
|
||||||
|
// For quoted strings, values do not hold the double quote or escaping backslashes.
|
||||||
|
// An empty string can be a valid localpart.
|
||||||
|
// Localparts are in Unicode NFC.
|
||||||
|
export type Localpart = string
|
||||||
|
|
||||||
// PolicyType indicates the policy success/failure results are for.
|
// PolicyType indicates the policy success/failure results are for.
|
||||||
export enum PolicyType {
|
export enum PolicyType {
|
||||||
TLSA = "tlsa", // For DANE, against a mail host (not recipient domain).
|
TLSA = "tlsa", // For DANE, against a mail host (not recipient domain).
|
||||||
|
@ -1060,12 +1135,6 @@ export enum SPFResult {
|
||||||
SPFPermerror = "permerror",
|
SPFPermerror = "permerror",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Localpart is a decoded local part of an email address, before the "@".
|
|
||||||
// For quoted strings, values do not hold the double quote or escaping backslashes.
|
|
||||||
// An empty string can be a valid localpart.
|
|
||||||
// Localparts are in Unicode NFC.
|
|
||||||
export type Localpart = string
|
|
||||||
|
|
||||||
// An IP is a single IP address, a slice of bytes.
|
// An IP is a single IP address, a slice of bytes.
|
||||||
// Functions in this package accept either 4-byte (IPv4)
|
// Functions in this package accept either 4-byte (IPv4)
|
||||||
// or 16-byte (IPv6) slices as input.
|
// or 16-byte (IPv6) slices as input.
|
||||||
|
@ -1077,7 +1146,7 @@ export type Localpart = string
|
||||||
// be an IPv4 address.
|
// be an IPv4 address.
|
||||||
export type IP = string
|
export type IP = string
|
||||||
|
|
||||||
export const structTypes: {[typename: string]: boolean} = {"Account":true,"AuthResults":true,"AutoconfCheckResult":true,"AutodiscoverCheckResult":true,"AutodiscoverSRV":true,"AutomaticJunkFlags":true,"CheckResult":true,"ClientConfigs":true,"ClientConfigsEntry":true,"DANECheckResult":true,"DKIMAuthResult":true,"DKIMCheckResult":true,"DKIMRecord":true,"DMARCCheckResult":true,"DMARCRecord":true,"DMARCSummary":true,"DNSSECResult":true,"DateRange":true,"Destination":true,"Directive":true,"Domain":true,"DomainFeedback":true,"Evaluation":true,"EvaluationStat":true,"Extension":true,"FailureDetails":true,"Filter":true,"HoldRule":true,"Hook":true,"HookFilter":true,"HookResult":true,"HookRetired":true,"HookRetiredFilter":true,"HookRetiredSort":true,"HookSort":true,"IPDomain":true,"IPRevCheckResult":true,"Identifiers":true,"IncomingWebhook":true,"JunkFilter":true,"MTASTSCheckResult":true,"MTASTSRecord":true,"MX":true,"MXCheckResult":true,"Modifier":true,"Msg":true,"MsgResult":true,"MsgRetired":true,"OutgoingWebhook":true,"Pair":true,"Policy":true,"PolicyEvaluated":true,"PolicyOverrideReason":true,"PolicyPublished":true,"PolicyRecord":true,"Record":true,"Report":true,"ReportMetadata":true,"ReportRecord":true,"Result":true,"ResultPolicy":true,"RetiredFilter":true,"RetiredSort":true,"Reverse":true,"Route":true,"Row":true,"Ruleset":true,"SMTPAuth":true,"SPFAuthResult":true,"SPFCheckResult":true,"SPFRecord":true,"SRV":true,"SRVConfCheckResult":true,"STSMX":true,"Sort":true,"SubjectPass":true,"Summary":true,"SuppressAddress":true,"TLSCheckResult":true,"TLSRPTCheckResult":true,"TLSRPTDateRange":true,"TLSRPTRecord":true,"TLSRPTSummary":true,"TLSRPTSuppressAddress":true,"TLSReportRecord":true,"TLSResult":true,"Transport":true,"TransportDirect":true,"TransportSMTP":true,"TransportSocks":true,"URI":true,"WebForward":true,"WebHandler":true,"WebRedirect":true,"WebStatic":true,"WebserverConfig":true}
|
export const structTypes: {[typename: string]: boolean} = {"Account":true,"AuthResults":true,"AutoconfCheckResult":true,"AutodiscoverCheckResult":true,"AutodiscoverSRV":true,"AutomaticJunkFlags":true,"Canonicalization":true,"CheckResult":true,"ClientConfigs":true,"ClientConfigsEntry":true,"ConfigDomain":true,"DANECheckResult":true,"DKIM":true,"DKIMAuthResult":true,"DKIMCheckResult":true,"DKIMRecord":true,"DMARC":true,"DMARCCheckResult":true,"DMARCRecord":true,"DMARCSummary":true,"DNSSECResult":true,"DateRange":true,"Destination":true,"Directive":true,"Domain":true,"DomainFeedback":true,"Dynamic":true,"Evaluation":true,"EvaluationStat":true,"Extension":true,"FailureDetails":true,"Filter":true,"HoldRule":true,"Hook":true,"HookFilter":true,"HookResult":true,"HookRetired":true,"HookRetiredFilter":true,"HookRetiredSort":true,"HookSort":true,"IPDomain":true,"IPRevCheckResult":true,"Identifiers":true,"IncomingWebhook":true,"JunkFilter":true,"MTASTS":true,"MTASTSCheckResult":true,"MTASTSRecord":true,"MX":true,"MXCheckResult":true,"Modifier":true,"Msg":true,"MsgResult":true,"MsgRetired":true,"OutgoingWebhook":true,"Pair":true,"Policy":true,"PolicyEvaluated":true,"PolicyOverrideReason":true,"PolicyPublished":true,"PolicyRecord":true,"Record":true,"Report":true,"ReportMetadata":true,"ReportRecord":true,"Result":true,"ResultPolicy":true,"RetiredFilter":true,"RetiredSort":true,"Reverse":true,"Route":true,"Row":true,"Ruleset":true,"SMTPAuth":true,"SPFAuthResult":true,"SPFCheckResult":true,"SPFRecord":true,"SRV":true,"SRVConfCheckResult":true,"STSMX":true,"Selector":true,"Sort":true,"SubjectPass":true,"Summary":true,"SuppressAddress":true,"TLSCheckResult":true,"TLSRPT":true,"TLSRPTCheckResult":true,"TLSRPTDateRange":true,"TLSRPTRecord":true,"TLSRPTSummary":true,"TLSRPTSuppressAddress":true,"TLSReportRecord":true,"TLSResult":true,"Transport":true,"TransportDirect":true,"TransportSMTP":true,"TransportSocks":true,"URI":true,"WebForward":true,"WebHandler":true,"WebRedirect":true,"WebStatic":true,"WebserverConfig":true}
|
||||||
export const stringsTypes: {[typename: string]: boolean} = {"Align":true,"Alignment":true,"CSRFToken":true,"DKIMResult":true,"DMARCPolicy":true,"DMARCResult":true,"Disposition":true,"IP":true,"Localpart":true,"Mode":true,"PolicyOverride":true,"PolicyType":true,"RUA":true,"ResultType":true,"SPFDomainScope":true,"SPFResult":true}
|
export const stringsTypes: {[typename: string]: boolean} = {"Align":true,"Alignment":true,"CSRFToken":true,"DKIMResult":true,"DMARCPolicy":true,"DMARCResult":true,"Disposition":true,"IP":true,"Localpart":true,"Mode":true,"PolicyOverride":true,"PolicyType":true,"RUA":true,"ResultType":true,"SPFDomainScope":true,"SPFResult":true}
|
||||||
export const intsTypes: {[typename: string]: boolean} = {}
|
export const intsTypes: {[typename: string]: boolean} = {}
|
||||||
export const types: TypenameMap = {
|
export const types: TypenameMap = {
|
||||||
|
@ -1112,6 +1181,14 @@ 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"]}]},
|
"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"]}]},
|
"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"]}]},
|
"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":"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"]}]},
|
||||||
|
"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"]}]},
|
||||||
|
"Canonicalization": {"Name":"Canonicalization","Docs":"","Fields":[{"Name":"HeaderRelaxed","Docs":"","Typewords":["bool"]},{"Name":"BodyRelaxed","Docs":"","Typewords":["bool"]}]},
|
||||||
|
"DMARC": {"Name":"DMARC","Docs":"","Fields":[{"Name":"Localpart","Docs":"","Typewords":["string"]},{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"Account","Docs":"","Typewords":["string"]},{"Name":"Mailbox","Docs":"","Typewords":["string"]},{"Name":"ParsedLocalpart","Docs":"","Typewords":["Localpart"]},{"Name":"DNSDomain","Docs":"","Typewords":["Domain"]}]},
|
||||||
|
"MTASTS": {"Name":"MTASTS","Docs":"","Fields":[{"Name":"PolicyID","Docs":"","Typewords":["string"]},{"Name":"Mode","Docs":"","Typewords":["Mode"]},{"Name":"MaxAge","Docs":"","Typewords":["int64"]},{"Name":"MX","Docs":"","Typewords":["[]","string"]}]},
|
||||||
|
"TLSRPT": {"Name":"TLSRPT","Docs":"","Fields":[{"Name":"Localpart","Docs":"","Typewords":["string"]},{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"Account","Docs":"","Typewords":["string"]},{"Name":"Mailbox","Docs":"","Typewords":["string"]},{"Name":"ParsedLocalpart","Docs":"","Typewords":["Localpart"]},{"Name":"DNSDomain","Docs":"","Typewords":["Domain"]}]},
|
||||||
|
"Route": {"Name":"Route","Docs":"","Fields":[{"Name":"FromDomain","Docs":"","Typewords":["[]","string"]},{"Name":"ToDomain","Docs":"","Typewords":["[]","string"]},{"Name":"MinimumAttempts","Docs":"","Typewords":["int32"]},{"Name":"Transport","Docs":"","Typewords":["string"]},{"Name":"FromDomainASCII","Docs":"","Typewords":["[]","string"]},{"Name":"ToDomainASCII","Docs":"","Typewords":["[]","string"]}]},
|
||||||
"Account": {"Name":"Account","Docs":"","Fields":[{"Name":"OutgoingWebhook","Docs":"","Typewords":["nullable","OutgoingWebhook"]},{"Name":"IncomingWebhook","Docs":"","Typewords":["nullable","IncomingWebhook"]},{"Name":"FromIDLoginAddresses","Docs":"","Typewords":["[]","string"]},{"Name":"KeepRetiredMessagePeriod","Docs":"","Typewords":["int64"]},{"Name":"KeepRetiredWebhookPeriod","Docs":"","Typewords":["int64"]},{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"Description","Docs":"","Typewords":["string"]},{"Name":"FullName","Docs":"","Typewords":["string"]},{"Name":"Destinations","Docs":"","Typewords":["{}","Destination"]},{"Name":"SubjectPass","Docs":"","Typewords":["SubjectPass"]},{"Name":"QuotaMessageSize","Docs":"","Typewords":["int64"]},{"Name":"RejectsMailbox","Docs":"","Typewords":["string"]},{"Name":"KeepRejects","Docs":"","Typewords":["bool"]},{"Name":"AutomaticJunkFlags","Docs":"","Typewords":["AutomaticJunkFlags"]},{"Name":"JunkFilter","Docs":"","Typewords":["nullable","JunkFilter"]},{"Name":"MaxOutgoingMessagesPerDay","Docs":"","Typewords":["int32"]},{"Name":"MaxFirstTimeRecipientsPerDay","Docs":"","Typewords":["int32"]},{"Name":"NoFirstTimeSenderDelay","Docs":"","Typewords":["bool"]},{"Name":"Routes","Docs":"","Typewords":["[]","Route"]},{"Name":"DNSDomain","Docs":"","Typewords":["Domain"]}]},
|
"Account": {"Name":"Account","Docs":"","Fields":[{"Name":"OutgoingWebhook","Docs":"","Typewords":["nullable","OutgoingWebhook"]},{"Name":"IncomingWebhook","Docs":"","Typewords":["nullable","IncomingWebhook"]},{"Name":"FromIDLoginAddresses","Docs":"","Typewords":["[]","string"]},{"Name":"KeepRetiredMessagePeriod","Docs":"","Typewords":["int64"]},{"Name":"KeepRetiredWebhookPeriod","Docs":"","Typewords":["int64"]},{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"Description","Docs":"","Typewords":["string"]},{"Name":"FullName","Docs":"","Typewords":["string"]},{"Name":"Destinations","Docs":"","Typewords":["{}","Destination"]},{"Name":"SubjectPass","Docs":"","Typewords":["SubjectPass"]},{"Name":"QuotaMessageSize","Docs":"","Typewords":["int64"]},{"Name":"RejectsMailbox","Docs":"","Typewords":["string"]},{"Name":"KeepRejects","Docs":"","Typewords":["bool"]},{"Name":"AutomaticJunkFlags","Docs":"","Typewords":["AutomaticJunkFlags"]},{"Name":"JunkFilter","Docs":"","Typewords":["nullable","JunkFilter"]},{"Name":"MaxOutgoingMessagesPerDay","Docs":"","Typewords":["int32"]},{"Name":"MaxFirstTimeRecipientsPerDay","Docs":"","Typewords":["int32"]},{"Name":"NoFirstTimeSenderDelay","Docs":"","Typewords":["bool"]},{"Name":"Routes","Docs":"","Typewords":["[]","Route"]},{"Name":"DNSDomain","Docs":"","Typewords":["Domain"]}]},
|
||||||
"OutgoingWebhook": {"Name":"OutgoingWebhook","Docs":"","Fields":[{"Name":"URL","Docs":"","Typewords":["string"]},{"Name":"Authorization","Docs":"","Typewords":["string"]},{"Name":"Events","Docs":"","Typewords":["[]","string"]}]},
|
"OutgoingWebhook": {"Name":"OutgoingWebhook","Docs":"","Fields":[{"Name":"URL","Docs":"","Typewords":["string"]},{"Name":"Authorization","Docs":"","Typewords":["string"]},{"Name":"Events","Docs":"","Typewords":["[]","string"]}]},
|
||||||
"IncomingWebhook": {"Name":"IncomingWebhook","Docs":"","Fields":[{"Name":"URL","Docs":"","Typewords":["string"]},{"Name":"Authorization","Docs":"","Typewords":["string"]}]},
|
"IncomingWebhook": {"Name":"IncomingWebhook","Docs":"","Fields":[{"Name":"URL","Docs":"","Typewords":["string"]},{"Name":"Authorization","Docs":"","Typewords":["string"]}]},
|
||||||
|
@ -1120,7 +1197,6 @@ export const types: TypenameMap = {
|
||||||
"SubjectPass": {"Name":"SubjectPass","Docs":"","Fields":[{"Name":"Period","Docs":"","Typewords":["int64"]}]},
|
"SubjectPass": {"Name":"SubjectPass","Docs":"","Fields":[{"Name":"Period","Docs":"","Typewords":["int64"]}]},
|
||||||
"AutomaticJunkFlags": {"Name":"AutomaticJunkFlags","Docs":"","Fields":[{"Name":"Enabled","Docs":"","Typewords":["bool"]},{"Name":"JunkMailboxRegexp","Docs":"","Typewords":["string"]},{"Name":"NeutralMailboxRegexp","Docs":"","Typewords":["string"]},{"Name":"NotJunkMailboxRegexp","Docs":"","Typewords":["string"]}]},
|
"AutomaticJunkFlags": {"Name":"AutomaticJunkFlags","Docs":"","Fields":[{"Name":"Enabled","Docs":"","Typewords":["bool"]},{"Name":"JunkMailboxRegexp","Docs":"","Typewords":["string"]},{"Name":"NeutralMailboxRegexp","Docs":"","Typewords":["string"]},{"Name":"NotJunkMailboxRegexp","Docs":"","Typewords":["string"]}]},
|
||||||
"JunkFilter": {"Name":"JunkFilter","Docs":"","Fields":[{"Name":"Threshold","Docs":"","Typewords":["float64"]},{"Name":"Onegrams","Docs":"","Typewords":["bool"]},{"Name":"Twograms","Docs":"","Typewords":["bool"]},{"Name":"Threegrams","Docs":"","Typewords":["bool"]},{"Name":"MaxPower","Docs":"","Typewords":["float64"]},{"Name":"TopWords","Docs":"","Typewords":["int32"]},{"Name":"IgnoreWords","Docs":"","Typewords":["float64"]},{"Name":"RareWords","Docs":"","Typewords":["int32"]}]},
|
"JunkFilter": {"Name":"JunkFilter","Docs":"","Fields":[{"Name":"Threshold","Docs":"","Typewords":["float64"]},{"Name":"Onegrams","Docs":"","Typewords":["bool"]},{"Name":"Twograms","Docs":"","Typewords":["bool"]},{"Name":"Threegrams","Docs":"","Typewords":["bool"]},{"Name":"MaxPower","Docs":"","Typewords":["float64"]},{"Name":"TopWords","Docs":"","Typewords":["int32"]},{"Name":"IgnoreWords","Docs":"","Typewords":["float64"]},{"Name":"RareWords","Docs":"","Typewords":["int32"]}]},
|
||||||
"Route": {"Name":"Route","Docs":"","Fields":[{"Name":"FromDomain","Docs":"","Typewords":["[]","string"]},{"Name":"ToDomain","Docs":"","Typewords":["[]","string"]},{"Name":"MinimumAttempts","Docs":"","Typewords":["int32"]},{"Name":"Transport","Docs":"","Typewords":["string"]},{"Name":"FromDomainASCII","Docs":"","Typewords":["[]","string"]},{"Name":"ToDomainASCII","Docs":"","Typewords":["[]","string"]}]},
|
|
||||||
"PolicyRecord": {"Name":"PolicyRecord","Docs":"","Fields":[{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"Inserted","Docs":"","Typewords":["timestamp"]},{"Name":"ValidEnd","Docs":"","Typewords":["timestamp"]},{"Name":"LastUpdate","Docs":"","Typewords":["timestamp"]},{"Name":"LastUse","Docs":"","Typewords":["timestamp"]},{"Name":"Backoff","Docs":"","Typewords":["bool"]},{"Name":"RecordID","Docs":"","Typewords":["string"]},{"Name":"Version","Docs":"","Typewords":["string"]},{"Name":"Mode","Docs":"","Typewords":["Mode"]},{"Name":"MX","Docs":"","Typewords":["[]","STSMX"]},{"Name":"MaxAgeSeconds","Docs":"","Typewords":["int32"]},{"Name":"Extensions","Docs":"","Typewords":["[]","Pair"]},{"Name":"PolicyText","Docs":"","Typewords":["string"]}]},
|
"PolicyRecord": {"Name":"PolicyRecord","Docs":"","Fields":[{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"Inserted","Docs":"","Typewords":["timestamp"]},{"Name":"ValidEnd","Docs":"","Typewords":["timestamp"]},{"Name":"LastUpdate","Docs":"","Typewords":["timestamp"]},{"Name":"LastUse","Docs":"","Typewords":["timestamp"]},{"Name":"Backoff","Docs":"","Typewords":["bool"]},{"Name":"RecordID","Docs":"","Typewords":["string"]},{"Name":"Version","Docs":"","Typewords":["string"]},{"Name":"Mode","Docs":"","Typewords":["Mode"]},{"Name":"MX","Docs":"","Typewords":["[]","STSMX"]},{"Name":"MaxAgeSeconds","Docs":"","Typewords":["int32"]},{"Name":"Extensions","Docs":"","Typewords":["[]","Pair"]},{"Name":"PolicyText","Docs":"","Typewords":["string"]}]},
|
||||||
"TLSReportRecord": {"Name":"TLSReportRecord","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"FromDomain","Docs":"","Typewords":["string"]},{"Name":"MailFrom","Docs":"","Typewords":["string"]},{"Name":"HostReport","Docs":"","Typewords":["bool"]},{"Name":"Report","Docs":"","Typewords":["Report"]}]},
|
"TLSReportRecord": {"Name":"TLSReportRecord","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Domain","Docs":"","Typewords":["string"]},{"Name":"FromDomain","Docs":"","Typewords":["string"]},{"Name":"MailFrom","Docs":"","Typewords":["string"]},{"Name":"HostReport","Docs":"","Typewords":["bool"]},{"Name":"Report","Docs":"","Typewords":["Report"]}]},
|
||||||
"Report": {"Name":"Report","Docs":"","Fields":[{"Name":"OrganizationName","Docs":"","Typewords":["string"]},{"Name":"DateRange","Docs":"","Typewords":["TLSRPTDateRange"]},{"Name":"ContactInfo","Docs":"","Typewords":["string"]},{"Name":"ReportID","Docs":"","Typewords":["string"]},{"Name":"Policies","Docs":"","Typewords":["[]","Result"]}]},
|
"Report": {"Name":"Report","Docs":"","Fields":[{"Name":"OrganizationName","Docs":"","Typewords":["string"]},{"Name":"DateRange","Docs":"","Typewords":["TLSRPTDateRange"]},{"Name":"ContactInfo","Docs":"","Typewords":["string"]},{"Name":"ReportID","Docs":"","Typewords":["string"]},{"Name":"Policies","Docs":"","Typewords":["[]","Result"]}]},
|
||||||
|
@ -1177,11 +1253,13 @@ export const types: TypenameMap = {
|
||||||
"SuppressAddress": {"Name":"SuppressAddress","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Inserted","Docs":"","Typewords":["timestamp"]},{"Name":"ReportingAddress","Docs":"","Typewords":["string"]},{"Name":"Until","Docs":"","Typewords":["timestamp"]},{"Name":"Comment","Docs":"","Typewords":["string"]}]},
|
"SuppressAddress": {"Name":"SuppressAddress","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Inserted","Docs":"","Typewords":["timestamp"]},{"Name":"ReportingAddress","Docs":"","Typewords":["string"]},{"Name":"Until","Docs":"","Typewords":["timestamp"]},{"Name":"Comment","Docs":"","Typewords":["string"]}]},
|
||||||
"TLSResult": {"Name":"TLSResult","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"PolicyDomain","Docs":"","Typewords":["string"]},{"Name":"DayUTC","Docs":"","Typewords":["string"]},{"Name":"RecipientDomain","Docs":"","Typewords":["string"]},{"Name":"Created","Docs":"","Typewords":["timestamp"]},{"Name":"Updated","Docs":"","Typewords":["timestamp"]},{"Name":"IsHost","Docs":"","Typewords":["bool"]},{"Name":"SendReport","Docs":"","Typewords":["bool"]},{"Name":"SentToRecipientDomain","Docs":"","Typewords":["bool"]},{"Name":"RecipientDomainReportingAddresses","Docs":"","Typewords":["[]","string"]},{"Name":"SentToPolicyDomain","Docs":"","Typewords":["bool"]},{"Name":"Results","Docs":"","Typewords":["[]","Result"]}]},
|
"TLSResult": {"Name":"TLSResult","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"PolicyDomain","Docs":"","Typewords":["string"]},{"Name":"DayUTC","Docs":"","Typewords":["string"]},{"Name":"RecipientDomain","Docs":"","Typewords":["string"]},{"Name":"Created","Docs":"","Typewords":["timestamp"]},{"Name":"Updated","Docs":"","Typewords":["timestamp"]},{"Name":"IsHost","Docs":"","Typewords":["bool"]},{"Name":"SendReport","Docs":"","Typewords":["bool"]},{"Name":"SentToRecipientDomain","Docs":"","Typewords":["bool"]},{"Name":"RecipientDomainReportingAddresses","Docs":"","Typewords":["[]","string"]},{"Name":"SentToPolicyDomain","Docs":"","Typewords":["bool"]},{"Name":"Results","Docs":"","Typewords":["[]","Result"]}]},
|
||||||
"TLSRPTSuppressAddress": {"Name":"TLSRPTSuppressAddress","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Inserted","Docs":"","Typewords":["timestamp"]},{"Name":"ReportingAddress","Docs":"","Typewords":["string"]},{"Name":"Until","Docs":"","Typewords":["timestamp"]},{"Name":"Comment","Docs":"","Typewords":["string"]}]},
|
"TLSRPTSuppressAddress": {"Name":"TLSRPTSuppressAddress","Docs":"","Fields":[{"Name":"ID","Docs":"","Typewords":["int64"]},{"Name":"Inserted","Docs":"","Typewords":["timestamp"]},{"Name":"ReportingAddress","Docs":"","Typewords":["string"]},{"Name":"Until","Docs":"","Typewords":["timestamp"]},{"Name":"Comment","Docs":"","Typewords":["string"]}]},
|
||||||
|
"Dynamic": {"Name":"Dynamic","Docs":"","Fields":[{"Name":"Domains","Docs":"","Typewords":["{}","ConfigDomain"]},{"Name":"Accounts","Docs":"","Typewords":["{}","Account"]},{"Name":"WebDomainRedirects","Docs":"","Typewords":["{}","string"]},{"Name":"WebHandlers","Docs":"","Typewords":["[]","WebHandler"]},{"Name":"Routes","Docs":"","Typewords":["[]","Route"]},{"Name":"MonitorDNSBLs","Docs":"","Typewords":["[]","string"]},{"Name":"MonitorDNSBLZones","Docs":"","Typewords":["[]","Domain"]}]},
|
||||||
"CSRFToken": {"Name":"CSRFToken","Docs":"","Values":null},
|
"CSRFToken": {"Name":"CSRFToken","Docs":"","Values":null},
|
||||||
"DMARCPolicy": {"Name":"DMARCPolicy","Docs":"","Values":[{"Name":"PolicyEmpty","Value":"","Docs":""},{"Name":"PolicyNone","Value":"none","Docs":""},{"Name":"PolicyQuarantine","Value":"quarantine","Docs":""},{"Name":"PolicyReject","Value":"reject","Docs":""}]},
|
"DMARCPolicy": {"Name":"DMARCPolicy","Docs":"","Values":[{"Name":"PolicyEmpty","Value":"","Docs":""},{"Name":"PolicyNone","Value":"none","Docs":""},{"Name":"PolicyQuarantine","Value":"quarantine","Docs":""},{"Name":"PolicyReject","Value":"reject","Docs":""}]},
|
||||||
"Align": {"Name":"Align","Docs":"","Values":[{"Name":"AlignStrict","Value":"s","Docs":""},{"Name":"AlignRelaxed","Value":"r","Docs":""}]},
|
"Align": {"Name":"Align","Docs":"","Values":[{"Name":"AlignStrict","Value":"s","Docs":""},{"Name":"AlignRelaxed","Value":"r","Docs":""}]},
|
||||||
"RUA": {"Name":"RUA","Docs":"","Values":null},
|
"RUA": {"Name":"RUA","Docs":"","Values":null},
|
||||||
"Mode": {"Name":"Mode","Docs":"","Values":[{"Name":"ModeEnforce","Value":"enforce","Docs":""},{"Name":"ModeTesting","Value":"testing","Docs":""},{"Name":"ModeNone","Value":"none","Docs":""}]},
|
"Mode": {"Name":"Mode","Docs":"","Values":[{"Name":"ModeEnforce","Value":"enforce","Docs":""},{"Name":"ModeTesting","Value":"testing","Docs":""},{"Name":"ModeNone","Value":"none","Docs":""}]},
|
||||||
|
"Localpart": {"Name":"Localpart","Docs":"","Values":null},
|
||||||
"PolicyType": {"Name":"PolicyType","Docs":"","Values":[{"Name":"TLSA","Value":"tlsa","Docs":""},{"Name":"STS","Value":"sts","Docs":""},{"Name":"NoPolicyFound","Value":"no-policy-found","Docs":""}]},
|
"PolicyType": {"Name":"PolicyType","Docs":"","Values":[{"Name":"TLSA","Value":"tlsa","Docs":""},{"Name":"STS","Value":"sts","Docs":""},{"Name":"NoPolicyFound","Value":"no-policy-found","Docs":""}]},
|
||||||
"ResultType": {"Name":"ResultType","Docs":"","Values":[{"Name":"ResultSTARTTLSNotSupported","Value":"starttls-not-supported","Docs":""},{"Name":"ResultCertificateHostMismatch","Value":"certificate-host-mismatch","Docs":""},{"Name":"ResultCertificateExpired","Value":"certificate-expired","Docs":""},{"Name":"ResultTLSAInvalid","Value":"tlsa-invalid","Docs":""},{"Name":"ResultDNSSECInvalid","Value":"dnssec-invalid","Docs":""},{"Name":"ResultDANERequired","Value":"dane-required","Docs":""},{"Name":"ResultCertificateNotTrusted","Value":"certificate-not-trusted","Docs":""},{"Name":"ResultSTSPolicyInvalid","Value":"sts-policy-invalid","Docs":""},{"Name":"ResultSTSWebPKIInvalid","Value":"sts-webpki-invalid","Docs":""},{"Name":"ResultValidationFailure","Value":"validation-failure","Docs":""},{"Name":"ResultSTSPolicyFetch","Value":"sts-policy-fetch-error","Docs":""}]},
|
"ResultType": {"Name":"ResultType","Docs":"","Values":[{"Name":"ResultSTARTTLSNotSupported","Value":"starttls-not-supported","Docs":""},{"Name":"ResultCertificateHostMismatch","Value":"certificate-host-mismatch","Docs":""},{"Name":"ResultCertificateExpired","Value":"certificate-expired","Docs":""},{"Name":"ResultTLSAInvalid","Value":"tlsa-invalid","Docs":""},{"Name":"ResultDNSSECInvalid","Value":"dnssec-invalid","Docs":""},{"Name":"ResultDANERequired","Value":"dane-required","Docs":""},{"Name":"ResultCertificateNotTrusted","Value":"certificate-not-trusted","Docs":""},{"Name":"ResultSTSPolicyInvalid","Value":"sts-policy-invalid","Docs":""},{"Name":"ResultSTSWebPKIInvalid","Value":"sts-webpki-invalid","Docs":""},{"Name":"ResultValidationFailure","Value":"validation-failure","Docs":""},{"Name":"ResultSTSPolicyFetch","Value":"sts-policy-fetch-error","Docs":""}]},
|
||||||
"Alignment": {"Name":"Alignment","Docs":"","Values":[{"Name":"AlignmentAbsent","Value":"","Docs":""},{"Name":"AlignmentRelaxed","Value":"r","Docs":""},{"Name":"AlignmentStrict","Value":"s","Docs":""}]},
|
"Alignment": {"Name":"Alignment","Docs":"","Values":[{"Name":"AlignmentAbsent","Value":"","Docs":""},{"Name":"AlignmentRelaxed","Value":"r","Docs":""},{"Name":"AlignmentStrict","Value":"s","Docs":""}]},
|
||||||
|
@ -1191,7 +1269,6 @@ export const types: TypenameMap = {
|
||||||
"DKIMResult": {"Name":"DKIMResult","Docs":"","Values":[{"Name":"DKIMAbsent","Value":"","Docs":""},{"Name":"DKIMNone","Value":"none","Docs":""},{"Name":"DKIMPass","Value":"pass","Docs":""},{"Name":"DKIMFail","Value":"fail","Docs":""},{"Name":"DKIMPolicy","Value":"policy","Docs":""},{"Name":"DKIMNeutral","Value":"neutral","Docs":""},{"Name":"DKIMTemperror","Value":"temperror","Docs":""},{"Name":"DKIMPermerror","Value":"permerror","Docs":""}]},
|
"DKIMResult": {"Name":"DKIMResult","Docs":"","Values":[{"Name":"DKIMAbsent","Value":"","Docs":""},{"Name":"DKIMNone","Value":"none","Docs":""},{"Name":"DKIMPass","Value":"pass","Docs":""},{"Name":"DKIMFail","Value":"fail","Docs":""},{"Name":"DKIMPolicy","Value":"policy","Docs":""},{"Name":"DKIMNeutral","Value":"neutral","Docs":""},{"Name":"DKIMTemperror","Value":"temperror","Docs":""},{"Name":"DKIMPermerror","Value":"permerror","Docs":""}]},
|
||||||
"SPFDomainScope": {"Name":"SPFDomainScope","Docs":"","Values":[{"Name":"SPFDomainScopeAbsent","Value":"","Docs":""},{"Name":"SPFDomainScopeHelo","Value":"helo","Docs":""},{"Name":"SPFDomainScopeMailFrom","Value":"mfrom","Docs":""}]},
|
"SPFDomainScope": {"Name":"SPFDomainScope","Docs":"","Values":[{"Name":"SPFDomainScopeAbsent","Value":"","Docs":""},{"Name":"SPFDomainScopeHelo","Value":"helo","Docs":""},{"Name":"SPFDomainScopeMailFrom","Value":"mfrom","Docs":""}]},
|
||||||
"SPFResult": {"Name":"SPFResult","Docs":"","Values":[{"Name":"SPFAbsent","Value":"","Docs":""},{"Name":"SPFNone","Value":"none","Docs":""},{"Name":"SPFNeutral","Value":"neutral","Docs":""},{"Name":"SPFPass","Value":"pass","Docs":""},{"Name":"SPFFail","Value":"fail","Docs":""},{"Name":"SPFSoftfail","Value":"softfail","Docs":""},{"Name":"SPFTemperror","Value":"temperror","Docs":""},{"Name":"SPFPermerror","Value":"permerror","Docs":""}]},
|
"SPFResult": {"Name":"SPFResult","Docs":"","Values":[{"Name":"SPFAbsent","Value":"","Docs":""},{"Name":"SPFNone","Value":"none","Docs":""},{"Name":"SPFNeutral","Value":"neutral","Docs":""},{"Name":"SPFPass","Value":"pass","Docs":""},{"Name":"SPFFail","Value":"fail","Docs":""},{"Name":"SPFSoftfail","Value":"softfail","Docs":""},{"Name":"SPFTemperror","Value":"temperror","Docs":""},{"Name":"SPFPermerror","Value":"permerror","Docs":""}]},
|
||||||
"Localpart": {"Name":"Localpart","Docs":"","Values":null},
|
|
||||||
"IP": {"Name":"IP","Docs":"","Values":[]},
|
"IP": {"Name":"IP","Docs":"","Values":[]},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,6 +1304,14 @@ export const parser = {
|
||||||
AutoconfCheckResult: (v: any) => parse("AutoconfCheckResult", v) as AutoconfCheckResult,
|
AutoconfCheckResult: (v: any) => parse("AutoconfCheckResult", v) as AutoconfCheckResult,
|
||||||
AutodiscoverCheckResult: (v: any) => parse("AutodiscoverCheckResult", v) as AutodiscoverCheckResult,
|
AutodiscoverCheckResult: (v: any) => parse("AutodiscoverCheckResult", v) as AutodiscoverCheckResult,
|
||||||
AutodiscoverSRV: (v: any) => parse("AutodiscoverSRV", v) as AutodiscoverSRV,
|
AutodiscoverSRV: (v: any) => parse("AutodiscoverSRV", v) as AutodiscoverSRV,
|
||||||
|
ConfigDomain: (v: any) => parse("ConfigDomain", v) as ConfigDomain,
|
||||||
|
DKIM: (v: any) => parse("DKIM", v) as DKIM,
|
||||||
|
Selector: (v: any) => parse("Selector", v) as Selector,
|
||||||
|
Canonicalization: (v: any) => parse("Canonicalization", v) as Canonicalization,
|
||||||
|
DMARC: (v: any) => parse("DMARC", v) as DMARC,
|
||||||
|
MTASTS: (v: any) => parse("MTASTS", v) as MTASTS,
|
||||||
|
TLSRPT: (v: any) => parse("TLSRPT", v) as TLSRPT,
|
||||||
|
Route: (v: any) => parse("Route", v) as Route,
|
||||||
Account: (v: any) => parse("Account", v) as Account,
|
Account: (v: any) => parse("Account", v) as Account,
|
||||||
OutgoingWebhook: (v: any) => parse("OutgoingWebhook", v) as OutgoingWebhook,
|
OutgoingWebhook: (v: any) => parse("OutgoingWebhook", v) as OutgoingWebhook,
|
||||||
IncomingWebhook: (v: any) => parse("IncomingWebhook", v) as IncomingWebhook,
|
IncomingWebhook: (v: any) => parse("IncomingWebhook", v) as IncomingWebhook,
|
||||||
|
@ -1235,7 +1320,6 @@ export const parser = {
|
||||||
SubjectPass: (v: any) => parse("SubjectPass", v) as SubjectPass,
|
SubjectPass: (v: any) => parse("SubjectPass", v) as SubjectPass,
|
||||||
AutomaticJunkFlags: (v: any) => parse("AutomaticJunkFlags", v) as AutomaticJunkFlags,
|
AutomaticJunkFlags: (v: any) => parse("AutomaticJunkFlags", v) as AutomaticJunkFlags,
|
||||||
JunkFilter: (v: any) => parse("JunkFilter", v) as JunkFilter,
|
JunkFilter: (v: any) => parse("JunkFilter", v) as JunkFilter,
|
||||||
Route: (v: any) => parse("Route", v) as Route,
|
|
||||||
PolicyRecord: (v: any) => parse("PolicyRecord", v) as PolicyRecord,
|
PolicyRecord: (v: any) => parse("PolicyRecord", v) as PolicyRecord,
|
||||||
TLSReportRecord: (v: any) => parse("TLSReportRecord", v) as TLSReportRecord,
|
TLSReportRecord: (v: any) => parse("TLSReportRecord", v) as TLSReportRecord,
|
||||||
Report: (v: any) => parse("Report", v) as Report,
|
Report: (v: any) => parse("Report", v) as Report,
|
||||||
|
@ -1292,11 +1376,13 @@ export const parser = {
|
||||||
SuppressAddress: (v: any) => parse("SuppressAddress", v) as SuppressAddress,
|
SuppressAddress: (v: any) => parse("SuppressAddress", v) as SuppressAddress,
|
||||||
TLSResult: (v: any) => parse("TLSResult", v) as TLSResult,
|
TLSResult: (v: any) => parse("TLSResult", v) as TLSResult,
|
||||||
TLSRPTSuppressAddress: (v: any) => parse("TLSRPTSuppressAddress", v) as TLSRPTSuppressAddress,
|
TLSRPTSuppressAddress: (v: any) => parse("TLSRPTSuppressAddress", v) as TLSRPTSuppressAddress,
|
||||||
|
Dynamic: (v: any) => parse("Dynamic", v) as Dynamic,
|
||||||
CSRFToken: (v: any) => parse("CSRFToken", v) as CSRFToken,
|
CSRFToken: (v: any) => parse("CSRFToken", v) as CSRFToken,
|
||||||
DMARCPolicy: (v: any) => parse("DMARCPolicy", v) as DMARCPolicy,
|
DMARCPolicy: (v: any) => parse("DMARCPolicy", v) as DMARCPolicy,
|
||||||
Align: (v: any) => parse("Align", v) as Align,
|
Align: (v: any) => parse("Align", v) as Align,
|
||||||
RUA: (v: any) => parse("RUA", v) as RUA,
|
RUA: (v: any) => parse("RUA", v) as RUA,
|
||||||
Mode: (v: any) => parse("Mode", v) as Mode,
|
Mode: (v: any) => parse("Mode", v) as Mode,
|
||||||
|
Localpart: (v: any) => parse("Localpart", v) as Localpart,
|
||||||
PolicyType: (v: any) => parse("PolicyType", v) as PolicyType,
|
PolicyType: (v: any) => parse("PolicyType", v) as PolicyType,
|
||||||
ResultType: (v: any) => parse("ResultType", v) as ResultType,
|
ResultType: (v: any) => parse("ResultType", v) as ResultType,
|
||||||
Alignment: (v: any) => parse("Alignment", v) as Alignment,
|
Alignment: (v: any) => parse("Alignment", v) as Alignment,
|
||||||
|
@ -1306,7 +1392,6 @@ export const parser = {
|
||||||
DKIMResult: (v: any) => parse("DKIMResult", v) as DKIMResult,
|
DKIMResult: (v: any) => parse("DKIMResult", v) as DKIMResult,
|
||||||
SPFDomainScope: (v: any) => parse("SPFDomainScope", v) as SPFDomainScope,
|
SPFDomainScope: (v: any) => parse("SPFDomainScope", v) as SPFDomainScope,
|
||||||
SPFResult: (v: any) => parse("SPFResult", v) as SPFResult,
|
SPFResult: (v: any) => parse("SPFResult", v) as SPFResult,
|
||||||
Localpart: (v: any) => parse("Localpart", v) as Localpart,
|
|
||||||
IP: (v: any) => parse("IP", v) as IP,
|
IP: (v: any) => parse("IP", v) as IP,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1406,6 +1491,15 @@ export class Client {
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as Domain
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as Domain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DomainConfig returns the configuration for a domain.
|
||||||
|
async DomainConfig(domain: string): Promise<ConfigDomain> {
|
||||||
|
const fn: string = "DomainConfig"
|
||||||
|
const paramTypes: string[][] = [["string"]]
|
||||||
|
const returnTypes: string[][] = [["ConfigDomain"]]
|
||||||
|
const params: any[] = [domain]
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as ConfigDomain
|
||||||
|
}
|
||||||
|
|
||||||
// DomainLocalparts returns the encoded localparts and accounts configured in domain.
|
// DomainLocalparts returns the encoded localparts and accounts configured in domain.
|
||||||
async DomainLocalparts(domain: string): Promise<{ [key: string]: string }> {
|
async DomainLocalparts(domain: string): Promise<{ [key: string]: string }> {
|
||||||
const fn: string = "DomainLocalparts"
|
const fn: string = "DomainLocalparts"
|
||||||
|
@ -2033,6 +2127,42 @@ export class Client {
|
||||||
const params: any[] = [recvID]
|
const params: any[] = [recvID]
|
||||||
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as string
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config returns the dynamic config.
|
||||||
|
async Config(): Promise<Dynamic> {
|
||||||
|
const fn: string = "Config"
|
||||||
|
const paramTypes: string[][] = []
|
||||||
|
const returnTypes: string[][] = [["Dynamic"]]
|
||||||
|
const params: any[] = []
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as Dynamic
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountRoutesSave saves routes for an account.
|
||||||
|
async AccountRoutesSave(accountName: string, routes: Route[] | null): Promise<void> {
|
||||||
|
const fn: string = "AccountRoutesSave"
|
||||||
|
const paramTypes: string[][] = [["string"],["[]","Route"]]
|
||||||
|
const returnTypes: string[][] = []
|
||||||
|
const params: any[] = [accountName, routes]
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as void
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainRoutesSave saves routes for a domain.
|
||||||
|
async DomainRoutesSave(domainName: string, routes: Route[] | null): Promise<void> {
|
||||||
|
const fn: string = "DomainRoutesSave"
|
||||||
|
const paramTypes: string[][] = [["string"],["[]","Route"]]
|
||||||
|
const returnTypes: string[][] = []
|
||||||
|
const params: any[] = [domainName, routes]
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as void
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoutesSave saves global routes.
|
||||||
|
async RoutesSave(routes: Route[] | null): Promise<void> {
|
||||||
|
const fn: string = "RoutesSave"
|
||||||
|
const paramTypes: string[][] = [["[]","Route"]]
|
||||||
|
const returnTypes: string[][] = []
|
||||||
|
const params: any[] = [routes]
|
||||||
|
return await _sherpaCall(this.baseURL, this.authState, { ...this.options }, paramTypes, returnTypes, fn, params) as void
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultBaseURL = (function() {
|
export const defaultBaseURL = (function() {
|
||||||
|
|
Loading…
Reference in a new issue