mirror of
https://github.com/mjl-/mox.git
synced 2025-07-12 17:44:35 +03:00
implement a catchall address for a domain
by specifying a "destination" in an account that is just "@" followed by the domain, e.g. "@example.org". messages are only delivered to the catchall address when no regular destination matches (taking the per-domain catchall-separator and case-sensisitivity into account). for issue #18
This commit is contained in:
@ -273,6 +273,7 @@ const index = async () => {
|
||||
Object.entries(destinations).sort().map(t =>
|
||||
dom.li(
|
||||
dom.a(t[0], attr({href: '#destinations/'+t[0]})),
|
||||
t[0].startsWith('@') ? ' (catchall)' : [],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -1126,8 +1126,8 @@ func (Admin) Domain(ctx context.Context, domain string) dns.Domain {
|
||||
return d
|
||||
}
|
||||
|
||||
// DomainLocalparts returns the localparts and accounts configured in domain.
|
||||
func (Admin) DomainLocalparts(ctx context.Context, domain string) (localpartAccounts map[smtp.Localpart]string) {
|
||||
// DomainLocalparts returns the encoded localparts and accounts configured in domain.
|
||||
func (Admin) DomainLocalparts(ctx context.Context, domain string) (localpartAccounts map[string]string) {
|
||||
d, err := dns.ParseDomain(domain)
|
||||
xcheckf(ctx, err, "parsing domain")
|
||||
_, ok := mox.Conf.Domain(d)
|
||||
|
@ -509,6 +509,9 @@ const account = async (name) => {
|
||||
lp, '@',
|
||||
dom.a(d, attr({href: '#domains/'+d})),
|
||||
]
|
||||
if (lp === '') {
|
||||
v.unshift('(catchall) ')
|
||||
}
|
||||
}
|
||||
return dom.tr(
|
||||
dom.td(v),
|
||||
@ -568,9 +571,9 @@ const account = async (name) => {
|
||||
fieldset=dom.fieldset(
|
||||
dom.label(
|
||||
style({display: 'inline-block'}),
|
||||
'Email address or localpart',
|
||||
dom.span('Email address or localpart', attr({title: 'If empty, or localpart is empty, a catchall address is configured for the domain.'})),
|
||||
dom.br(),
|
||||
email=dom.input(attr({required: ''})),
|
||||
email=dom.input(),
|
||||
),
|
||||
' ',
|
||||
dom.button('Add address'),
|
||||
@ -748,7 +751,7 @@ const domain = async (d) => {
|
||||
dom.tbody(
|
||||
Object.entries(localpartAccounts).map(t =>
|
||||
dom.tr(
|
||||
dom.td(t[0]),
|
||||
dom.td(t[0] || '(catchall)'),
|
||||
dom.td(dom.a(t[1], attr({href: '#accounts/'+t[1]}))),
|
||||
dom.td(
|
||||
dom.button('Remove address', async function click(e) {
|
||||
@ -758,7 +761,7 @@ const domain = async (d) => {
|
||||
}
|
||||
e.target.disabled = true
|
||||
try {
|
||||
await api.AddressRemove(t[0] + '@'+d)
|
||||
await api.AddressRemove(t[0] + '@' + d)
|
||||
} catch (err) {
|
||||
console.log({err})
|
||||
window.alert('Error: ' + err.message)
|
||||
@ -795,9 +798,9 @@ const domain = async (d) => {
|
||||
fieldset=dom.fieldset(
|
||||
dom.label(
|
||||
style({display: 'inline-block'}),
|
||||
'Localpart',
|
||||
dom.span('Localpart', attr({title: 'An empty localpart is the catchall destination/address for the domain.'})),
|
||||
dom.br(),
|
||||
localpart=dom.input(attr({required: ''})),
|
||||
localpart=dom.input(),
|
||||
),
|
||||
' ',
|
||||
dom.label(
|
||||
|
@ -58,7 +58,7 @@
|
||||
},
|
||||
{
|
||||
"Name": "DomainLocalparts",
|
||||
"Docs": "DomainLocalparts returns the localparts and accounts configured in domain.",
|
||||
"Docs": "DomainLocalparts returns the encoded localparts and accounts configured in domain.",
|
||||
"Params": [
|
||||
{
|
||||
"Name": "domain",
|
||||
@ -3237,11 +3237,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.",
|
||||
"Values": null
|
||||
},
|
||||
{
|
||||
"Name": "ResultType",
|
||||
"Docs": "ResultType represents a TLS error.",
|
||||
@ -3490,6 +3485,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.",
|
||||
"Values": null
|
||||
},
|
||||
{
|
||||
"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.",
|
||||
|
Reference in New Issue
Block a user