smtpserver: when logging recipients, actually show something about the recipient

before this change, we were logging an empty string, which turned into "[]",
looking like an empty array. misleading and unhelpful.

this is fixed by making struct fields on type recipient "exported" so they can
get logged, and by changing the logging code to log nested
struct/pointer/interface fields if we would otherwise wouldn't log anything
(when only logging more basic data types).

we'll now get log lines like:

	l=info m="deliver attempt to unknown user(s)" pkg=smtpserver recipients="[addr=bogus@test.example]"

for issue #232 by snabb, thanks for reporting!
This commit is contained in:
Mechiel Lukkien
2024-11-01 10:38:31 +01:00
parent 879477a01f
commit 598c5ea6ac
2 changed files with 66 additions and 56 deletions

View File

@ -426,29 +426,39 @@ func stringValue(iscid, nested bool, v any) string {
}
n := rv.NumField()
t := rv.Type()
b := &strings.Builder{}
first := true
for i := 0; i < n; i++ {
fv := rv.Field(i)
if !t.Field(i).IsExported() {
continue
// We first try making a string without recursing into structs/pointers/interfaces,
// but will try again with those fields if we otherwise would otherwise log an
// empty string.
for j := 0; j < 2; j++ {
first := true
b := &strings.Builder{}
for i := 0; i < n; i++ {
fv := rv.Field(i)
if !t.Field(i).IsExported() {
continue
}
if j == 0 && (fv.Kind() == reflect.Struct || fv.Kind() == reflect.Ptr || fv.Kind() == reflect.Interface) {
// Don't recurse.
continue
}
vs := stringValue(false, true, fv.Interface())
if vs == "" {
continue
}
if !first {
b.WriteByte(' ')
}
first = false
k := strings.ToLower(t.Field(i).Name)
b.WriteString(k + "=" + vs)
}
if fv.Kind() == reflect.Struct || fv.Kind() == reflect.Ptr || fv.Kind() == reflect.Interface {
// Don't recurse.
continue
rs := b.String()
if rs != "" {
return rs
}
vs := stringValue(false, true, fv.Interface())
if vs == "" {
continue
}
if !first {
b.WriteByte(' ')
}
first = false
k := strings.ToLower(t.Field(i).Name)
b.WriteString(k + "=" + vs)
}
return b.String()
return ""
}
func writeAttr(w io.Writer, separator, group string, a slog.Attr) {