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