mox/message/from.go
Laurent Meunier 9c5d234162
do not require the SMTPUTF8 extension when not needed (#145)
Squashed commit of the following:

commit 11c25d727f
Author: Laurent Meunier <laurent@deltalima.net>
Date:   Sun Mar 31 12:37:09 2024 +0200

    Fix style issue

commit c075a8cd8b
Author: Laurent Meunier <laurent@deltalima.net>
Date:   Sun Mar 31 12:35:04 2024 +0200

    Also check smtputf8 for submitted messages or when in pedantic mode

commit c02328f881
Author: Laurent Meunier <laurent@deltalima.net>
Date:   Sun Mar 31 12:33:20 2024 +0200

    Calls to `newParser` should use `c.smtputf8`

commit a0bbd13afc
Author: Laurent Meunier <laurent@deltalima.net>
Date:   Sun Mar 31 12:32:12 2024 +0200

    Improve SMTPUTF8 tests

commit 08735690f3
Author: Laurent Meunier <laurent@deltalima.net>
Date:   Sat Mar 30 17:22:33 2024 +0100

    do earlier smtputf8-check

commit 3484651691
Author: Laurent Meunier <laurent@deltalima.net>
Date:   Thu Mar 28 17:47:11 2024 +0100

    do not require the SMTPUTF8 extension when not needed

    fix #145
2024-03-31 15:23:53 +02:00

56 lines
1.7 KiB
Go

package message
import (
"fmt"
"io"
"log/slog"
"net/textproto"
"github.com/mjl-/mox/dns"
"github.com/mjl-/mox/mlog"
"github.com/mjl-/mox/smtp"
)
// From extracts the address in the From-header.
//
// An RFC5322 message must have a From header.
// In theory, multiple addresses may be present. In practice zero or multiple
// From headers may be present. From returns an error if there is not exactly
// one address. This address can be used for evaluating a DMARC policy against
// SPF and DKIM results.
func From(elog *slog.Logger, strict bool, r io.ReaderAt, p *Part) (raddr smtp.Address, envelope *Envelope, header textproto.MIMEHeader, rerr error) {
log := mlog.New("message", elog)
// ../rfc/7489:1243
// todo: only allow utf8 if enabled in session/message?
var err error
if p == nil {
var pp Part
pp, err = Parse(log.Logger, strict, r)
if err != nil {
// todo: should we continue with p, perhaps headers can be parsed?
return raddr, nil, nil, fmt.Errorf("parsing message: %v", err)
}
p = &pp
}
header, err = p.Header()
if err != nil {
return raddr, nil, nil, fmt.Errorf("parsing message header: %v", err)
}
from := p.Envelope.From
if len(from) != 1 {
return raddr, nil, nil, fmt.Errorf("from header has %d addresses, need exactly 1 address", len(from))
}
d, err := dns.ParseDomain(from[0].Host)
if err != nil {
return raddr, nil, nil, fmt.Errorf("bad domain in from address: %v", err)
}
lp, err := smtp.ParseLocalpart(from[0].User)
if err != nil {
return raddr, nil, nil, fmt.Errorf("parsing localpart in from address: %v", err)
}
addr := smtp.Address{Localpart: lp, Domain: d}
return addr, p.Envelope, textproto.MIMEHeader(header), nil
}