release: 0.4.0: Domain-admin groundwork, send-log auth, packaging fixes
The project's mark is now in use rather than only on file. The README opens Added: - The project's mark is now in use rather than only on file. The README opens Changed: - panel: the sign-in and setup pages are now a column the width of their own - panel: the three monitoring pages — Deliveries, Mail queue, System log — are Fixed: - panel: Deliveries now shows the subject as text rather than as its MIME - panel: table cells may now break inside a word, so no single long value can - panel: the Applications list on a domain page no longer comes apart. It was a Full detail: CHANGELOG.md (0.4.0).
This commit is contained in:
@@ -13,6 +13,7 @@ package milter
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"mime"
|
||||
"net"
|
||||
"net/textproto"
|
||||
"strings"
|
||||
@@ -92,11 +93,35 @@ func (s *session) RcptTo(rcpt string, m *milter.Modifier) (milter.Response, erro
|
||||
// Header captures the Subject. Only the first Subject header is kept.
|
||||
func (s *session) Header(name, value string, m *milter.Modifier) (milter.Response, error) {
|
||||
if s.subject == "" && textproto.CanonicalMIMEHeaderKey(name) == "Subject" {
|
||||
s.subject = value
|
||||
s.subject = decodeSubject(value)
|
||||
}
|
||||
return milter.RespContinue, nil
|
||||
}
|
||||
|
||||
// subjectMaxRunes caps what the journal keeps of a subject. A Subject header
|
||||
// may legally run to hundreds of characters; the log only needs enough to
|
||||
// recognise the message, and the panel shows one row per recipient.
|
||||
const subjectMaxRunes = 200
|
||||
|
||||
// decodeSubject turns the raw Subject header into display text. Anything
|
||||
// non-ASCII arrives as RFC 2047 encoded-words (=?utf-8?Q?=D0=9F…?=), which the
|
||||
// panel would otherwise show verbatim: unreadable, and — being one unbreakable
|
||||
// run — wide enough to push the send-log table out of its card. Go's decoder
|
||||
// covers the UTF-8 and ASCII charsets senders use in practice; for anything
|
||||
// else (windows-1251, koi8-r) it fails and the raw header is kept, which is no
|
||||
// worse than before. Truncation is applied after decoding so the cap counts
|
||||
// characters of the subject, not bytes of its encoding.
|
||||
func decodeSubject(v string) string {
|
||||
if dec, err := (&mime.WordDecoder{}).DecodeHeader(v); err == nil {
|
||||
v = dec
|
||||
}
|
||||
v = strings.TrimSpace(v)
|
||||
if r := []rune(v); len(r) > subjectMaxRunes {
|
||||
v = string(r[:subjectMaxRunes]) + "…"
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Body fires at end-of-message, when the queue-id macro {i} is set and the
|
||||
// message is about to be committed to the queue. This is where the "queued"
|
||||
// rows are written. We accept (this milter is done) without ever rejecting.
|
||||
|
||||
Reference in New Issue
Block a user