fix(gmail): honor configured timezone for sent mail dates
Co-authored-by: Dinakar Sarbada <dinakars777@users.noreply.github.com>
This commit is contained in:
parent
8409571d60
commit
2c48bd8666
@ -10,6 +10,7 @@
|
||||
- Backup: add Gmail message-list checkpoints, streaming shard construction, and stderr progress counters so full-mailbox backups can resume cleanly after interruption without keeping every raw message in RAM.
|
||||
|
||||
### Fixed
|
||||
- Gmail: build outbound `Date` headers with the configured timezone so replies do not inherit a wrong host-local offset. (#514, #472) — thanks @dinakars777.
|
||||
- Gmail: preserve renewed watch expiration fields when a long-running `gmail watch serve` process records push delivery state after `gmail watch renew` runs separately. (#526)
|
||||
- Gmail: auto-fill draft reply subjects from the original message when `gmail drafts create --reply-to-message-id` omits `--subject`. (#488) — thanks @jbowerbir.
|
||||
- Drive: include `hasThumbnail` and `thumbnailLink` in `drive ls`, `drive search`, and `drive get` JSON responses. (#486) — thanks @gtapps.
|
||||
|
||||
@ -86,7 +86,11 @@ func buildRFC822(opts mailOptions, cfg *rfc822Config) ([]byte, error) {
|
||||
return nil, fmt.Errorf("invalid Subject: %w", err)
|
||||
}
|
||||
writeHeader(&b, "Subject", encodeHeaderIfNeeded(opts.Subject))
|
||||
writeHeader(&b, "Date", time.Now().Format(time.RFC1123Z))
|
||||
dateLocation, err := mailDateLocation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writeHeader(&b, "Date", time.Now().In(dateLocation).Format(time.RFC1123Z))
|
||||
if !hasHeader(opts.AdditionalHeaders, "Message-ID") && !hasHeader(opts.AdditionalHeaders, "Message-Id") {
|
||||
messageID, err := randomMessageID(opts.From)
|
||||
if err != nil {
|
||||
@ -211,6 +215,17 @@ func buildRFC822(opts mailOptions, cfg *rfc822Config) ([]byte, error) {
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
func mailDateLocation() (*time.Location, error) {
|
||||
loc, err := getConfiguredTimezone("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if loc != nil {
|
||||
return loc, nil
|
||||
}
|
||||
return time.Local, nil
|
||||
}
|
||||
|
||||
func writeHeader(b *bytes.Buffer, name, value string) {
|
||||
b.WriteString(name)
|
||||
b.WriteString(": ")
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"net/mail"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBuildRFC822_MissingFields(t *testing.T) {
|
||||
@ -33,6 +35,32 @@ func TestBuildRFC822_AllowMissingTo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRFC822_DateHeaderUsesConfiguredTimezone(t *testing.T) {
|
||||
oldLocal := time.Local
|
||||
time.Local = time.FixedZone("JST", 9*60*60)
|
||||
t.Cleanup(func() { time.Local = oldLocal })
|
||||
t.Setenv("GOG_TIMEZONE", "UTC")
|
||||
|
||||
raw, err := buildRFC822(mailOptions{
|
||||
From: "a@b.com",
|
||||
To: []string{"c@d.com"},
|
||||
Subject: "Hi",
|
||||
Body: "Hello",
|
||||
}, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("buildRFC822: %v", err)
|
||||
}
|
||||
|
||||
msg, err := mail.ReadMessage(strings.NewReader(string(raw)))
|
||||
if err != nil {
|
||||
t.Fatalf("ReadMessage: %v", err)
|
||||
}
|
||||
date := msg.Header.Get("Date")
|
||||
if !strings.HasSuffix(date, "+0000") {
|
||||
t.Fatalf("expected UTC Date header, got %q", date)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRFC822_InvalidHeaders(t *testing.T) {
|
||||
if _, err := buildRFC822(mailOptions{
|
||||
From: "a@b.com\r\nBcc: evil@evil.com",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user