Skip to content

Commit

Permalink
Feature: Reset message date on release (#194)
Browse files Browse the repository at this point in the history
When releasing a message the date header is now updated with the current date & time.
  • Loading branch information
axllent committed Oct 18, 2023
1 parent 30c392b commit f256d20
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 6 deletions.
46 changes: 43 additions & 3 deletions internal/tools/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import (
)

// RemoveMessageHeaders scans a message for headers, if found them removes them.
// It will only remove a single instance of any header, and is intended to remove
// Bcc & Message-Id.
// It will only remove a single instance of any given message header.
func RemoveMessageHeaders(msg []byte, headers []string) ([]byte, error) {
reader := bytes.NewReader(msg)
m, err := mail.ReadMessage(reader)
Expand Down Expand Up @@ -49,11 +48,52 @@ func RemoveMessageHeaders(msg []byte, headers []string) ([]byte, error) {
}

if len(hdr) > 0 {
logger.Log().Debugf("[release] removing %s header", hdr)
logger.Log().Debugf("[release] removed %s header", hdr)
msg = bytes.Replace(msg, hdr, []byte(""), 1)
}
}
}

return msg, nil
}

// UpdateMessageHeader scans a message for a header and updates its value if found.
func UpdateMessageHeader(msg []byte, header, value string) ([]byte, error) {
reader := bytes.NewReader(msg)
m, err := mail.ReadMessage(reader)
if err != nil {
return nil, err
}

if m.Header.Get(header) != "" {
reBlank := regexp.MustCompile(`^\s+`)
reHdr := regexp.MustCompile(`(?i)^` + regexp.QuoteMeta(header+":"))

scanner := bufio.NewScanner(bytes.NewReader(msg))
found := false
hdr := []byte("")
for scanner.Scan() {
line := scanner.Bytes()
if !found && reHdr.Match(line) {
// add the first line starting with <header>:
hdr = append(hdr, line...)
hdr = append(hdr, []byte("\r\n")...)
found = true
} else if found && reBlank.Match(line) {
// add any following lines starting with a whitespace (tab or space)
hdr = append(hdr, line...)
hdr = append(hdr, []byte("\r\n")...)
} else if found {
// stop scanning, we have the full <header>
break
}
}

if len(hdr) > 0 {
logger.Log().Debugf("[release] replaced %s header", hdr)
msg = bytes.Replace(msg, hdr, []byte(header+": "+value+"\r\n"), 1)
}
}

return msg, nil
}
18 changes: 15 additions & 3 deletions server/apiv1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/mail"
"strconv"
"strings"
"time"

"github.com/axllent/mailpit/config"
"github.com/axllent/mailpit/internal/htmlcheck"
Expand Down Expand Up @@ -632,7 +633,7 @@ func ReleaseMessage(w http.ResponseWriter, r *http.Request) {
from = senders[0].Address
}

msg, err = tools.RemoveMessageHeaders(msg, []string{"Bcc", "Message-Id"})
msg, err = tools.RemoveMessageHeaders(msg, []string{"Bcc"})
if err != nil {
httpError(w, err.Error())
return
Expand All @@ -652,10 +653,21 @@ func ReleaseMessage(w http.ResponseWriter, r *http.Request) {
from = config.SMTPRelayConfig.ReturnPath
}

// update message date
msg, err = tools.UpdateMessageHeader(msg, "Date", time.Now().Format(time.RFC1123Z))
if err != nil {
httpError(w, err.Error())
return
}

// generate unique ID
uid := uuid.New().String() + "@mailpit"
// add unique ID
msg = append([]byte("Message-Id: <"+uid+">\r\n"), msg...)
// update Message-Id with unique ID
msg, err = tools.UpdateMessageHeader(msg, "Message-Id", "<"+uid+">")
if err != nil {
httpError(w, err.Error())
return
}

if err := smtpd.Send(from, tos, msg); err != nil {
logger.Log().Errorf("[smtp] error sending message: %s", err.Error())
Expand Down

0 comments on commit f256d20

Please sign in to comment.