mirror of
https://github.com/mjl-/mox.git
synced 2024-12-26 16:33:47 +03:00
72ac1fde29
- prometheus is now behind an interface, they aren't dependencies for the reusable components anymore. - some dependencies have been inverted: instead of packages importing a main package to get configuration, the main package now sets configuration in these packages. that means fewer internals are pulled in. - some functions now have new parameters for values that were retrieved from package "mox-".
65 lines
2 KiB
Go
65 lines
2 KiB
Go
package mox
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/mjl-/mox/config"
|
|
"github.com/mjl-/mox/dkim"
|
|
"github.com/mjl-/mox/dns"
|
|
"github.com/mjl-/mox/mlog"
|
|
"github.com/mjl-/mox/smtp"
|
|
)
|
|
|
|
// DKIMSelectors returns the selectors to use for signing.
|
|
func DKIMSelectors(dkimConf config.DKIM) []dkim.Selector {
|
|
var l []dkim.Selector
|
|
for _, sign := range dkimConf.Sign {
|
|
sel := dkimConf.Selectors[sign]
|
|
s := dkim.Selector{
|
|
Hash: sel.HashEffective,
|
|
HeaderRelaxed: sel.Canonicalization.HeaderRelaxed,
|
|
BodyRelaxed: sel.Canonicalization.BodyRelaxed,
|
|
Headers: sel.HeadersEffective,
|
|
SealHeaders: !sel.DontSealHeaders,
|
|
Expiration: time.Duration(sel.ExpirationSeconds) * time.Second,
|
|
PrivateKey: sel.Key,
|
|
Domain: sel.Domain,
|
|
}
|
|
l = append(l, s)
|
|
}
|
|
return l
|
|
}
|
|
|
|
// DKIMSign looks up the domain for "from", and uses its DKIM configuration to
|
|
// generate DKIM-Signature headers, for inclusion in a message. The
|
|
// DKIM-Signatur headers, are returned. If no domain was found an empty string and
|
|
// nil error is returned.
|
|
func DKIMSign(ctx context.Context, log mlog.Log, from smtp.Path, smtputf8 bool, data []byte) (string, error) {
|
|
// Add DKIM signature for domain, even if higher up than the full mail hostname.
|
|
// This helps with an assumed (because default) relaxed DKIM policy. If the DMARC
|
|
// policy happens to be strict, the signature won't help, but won't hurt either.
|
|
fd := from.IPDomain.Domain
|
|
var zerodom dns.Domain
|
|
for fd != zerodom {
|
|
confDom, ok := Conf.Domain(fd)
|
|
if !ok {
|
|
var nfd dns.Domain
|
|
_, nfd.ASCII, _ = strings.Cut(fd.ASCII, ".")
|
|
_, nfd.Unicode, _ = strings.Cut(fd.Unicode, ".")
|
|
fd = nfd
|
|
continue
|
|
}
|
|
|
|
selectors := DKIMSelectors(confDom.DKIM)
|
|
dkimHeaders, err := dkim.Sign(ctx, log.Logger, from.Localpart, fd, selectors, smtputf8, bytes.NewReader(data))
|
|
if err != nil {
|
|
return "", fmt.Errorf("dkim sign for domain %s: %v", fd, err)
|
|
}
|
|
return dkimHeaders, nil
|
|
}
|
|
return "", nil
|
|
}
|