~rockorager/go-jmap-devel

go-jmap: dates: force UTC timezone v1 PROPOSED

Robin Jarry: 1
 dates: force UTC timezone

 4 files changed, 53 insertions(+), 0 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~rockorager/go-jmap-devel/patches/45910/mbox | git am -3
Learn more about email & git

[PATCH go-jmap] dates: force UTC timezone Export this patch

In the RFC, it is stated that all (or almost all) dates should be
"UTCDate" (e.g. in the UTC timezone and formatted with a trailing "Z").

Convert the dates to use the UTC timezone when required before
marshaling to JSON. Create type aliases to be able to call
json.Marshal() from MarshalJSON() without a recursion error.

Link: https://www.rfc-editor.org/rfc/rfc8620.html#section-1.4
Link: https://www.rfc-editor.org/rfc/rfc8621.html#section-4.4.1
Link: https://choly.ca/post/go-json-marshalling/
Signed-off-by: Robin Jarry <robin@jarry.cc>
---
 mail/email/filter.go                      | 15 +++++++++++++++
 mail/emailsubmission/emailsubmission.go   | 10 ++++++++++
 mail/emailsubmission/filter.go            | 15 +++++++++++++++
 mail/vacationresponse/vacationresponse.go | 13 +++++++++++++
 4 files changed, 53 insertions(+)

diff --git a/mail/email/filter.go b/mail/email/filter.go
index dfa25a6907d1..faf6fdadf928 100644
--- a/mail/email/filter.go
+++ b/mail/email/filter.go
@@ -1,6 +1,7 @@
package email

import (
	"encoding/json"
	"time"

	"git.sr.ht/~rockorager/go-jmap"
@@ -127,3 +128,17 @@ type FilterCondition struct {
}

func (fc *FilterCondition) implementsFilter() {}

func (fc *FilterCondition) MarshalJSON() ([]byte, error) {
	if fc.Before != nil && fc.Before.Location() != time.UTC {
		utc := fc.Before.UTC()
		fc.Before = &utc
	}
	if fc.After != nil && fc.After.Location() != time.UTC {
		utc := fc.After.UTC()
		fc.After = &utc
	}
	// create a type alias to avoid infinite recursion
	type Alias FilterCondition
	return json.Marshal((*Alias)(fc))
}
diff --git a/mail/emailsubmission/emailsubmission.go b/mail/emailsubmission/emailsubmission.go
index c9aeefcac307..949cc3b48ee4 100644
--- a/mail/emailsubmission/emailsubmission.go
+++ b/mail/emailsubmission/emailsubmission.go
@@ -89,6 +89,16 @@ type EmailSubmission struct {
	MDNBlobIDs []jmap.ID `json:"mdnBlobIds,omitempty"`
}

func (s *EmailSubmission) MarshalJSON() ([]byte, error) {
	if s.SendAt != nil && s.SendAt.Location() != time.UTC {
		utc := s.SendAt.UTC()
		s.SendAt = &utc
	}
	// create a type alias to avoid infinite recursion
	type Alias EmailSubmission
	return json.Marshal((*Alias)(s))
}

type Envelope struct {
	// The email address to use as the return address in the SMTP submission
	MailFrom *Address `json:"mailfrom,omitempty"`
diff --git a/mail/emailsubmission/filter.go b/mail/emailsubmission/filter.go
index 286e7db38f6c..9c35866fa829 100644
--- a/mail/emailsubmission/filter.go
+++ b/mail/emailsubmission/filter.go
@@ -1,6 +1,7 @@
package emailsubmission

import (
	"encoding/json"
	"time"

	"git.sr.ht/~rockorager/go-jmap"
@@ -48,3 +49,17 @@ type FilterCondition struct {
}

func (fc *FilterCondition) implementsFilter() {}

func (fc *FilterCondition) MarshalJSON() ([]byte, error) {
	if fc.Before != nil && fc.Before.Location() != time.UTC {
		utc := fc.Before.UTC()
		fc.Before = &utc
	}
	if fc.After != nil && fc.After.Location() != time.UTC {
		utc := fc.After.UTC()
		fc.After = &utc
	}
	// create a type alias to avoid infinite recursion
	type Alias FilterCondition
	return json.Marshal((*Alias)(fc))
}
diff --git a/mail/vacationresponse/vacationresponse.go b/mail/vacationresponse/vacationresponse.go
index f30e39f89aa8..9be17a2024c2 100644
--- a/mail/vacationresponse/vacationresponse.go
+++ b/mail/vacationresponse/vacationresponse.go
@@ -1,6 +1,7 @@
package vacationresponse

import (
	"encoding/json"
	"time"

	"git.sr.ht/~rockorager/go-jmap"
@@ -49,3 +50,15 @@ type VacationResponse struct {
	// The HTML body to send in the response
	HTMLBody *string `json:"htmlBody,omitempty"`
}

func (v *VacationResponse) MarshalJson() ([]byte, error) {
	if v.FromDate != nil && v.FromDate.Location() != time.UTC {
		utc := v.FromDate.UTC()
		v.FromDate = &utc
	}
	if v.ToDate != nil && v.ToDate.Location() != time.UTC {
		utc := v.ToDate.UTC()
		v.ToDate = &utc
	}
	return json.Marshal(v)
}
-- 
2.41.0