package jmap
import (
"io"
"time"
"github.com/opencloud-eu/opencloud/pkg/jscalendar"
"github.com/opencloud-eu/opencloud/pkg/jscontact"
)
// https://www.iana.org/assignments/jmap/jmap.xml#jmap-data-types
type ObjectType string
// Where `UTCDate` is given as a type, it means a `Date` where the "time-offset"
// component MUST be `"Z"` (i.e., it must be in UTC time).
//
// For example, `"2014-10-30T06:12:00Z"`.
type UTCDate string
// Where `LocalDate` is given as a type, it means a string in the same format as `Date`
// (see [RFC8620, Section 1.4]), but with the time-offset omitted from the end.
//
// For example, `2014-10-30T14:12:00`.
//
// The interpretation in absolute time depends upon the time zone for the event, which
// may not be a fixed offset (for example when daylight saving time occurs).
//
// [RFC8620, Section 1.4]: https://www.rfc-editor.org/rfc/rfc8620.html#section-1.4
type LocalDate string
// Should the calendar’s events be used as part of availability calculation?
//
// This MUST be one of:
// !- `all“: all events are considered.
// !- `attending“: events the user is a confirmed or tentative participant of are considered.
// !- `none“: all events are ignored (but may be considered if also in another calendar).
//
// This should default to “all” for the calendars in the user’s own account, and “none” for calendars shared with the user.
type IncludeInAvailability string
type TypeOfCalendarAlert string
// `CalendarEventNotification` type.
//
// This MUST be one of
// !- `created`
// !- `updated`
// !- `destroyed`
type CalendarEventNotificationTypeOption string
// `Principal` type.
//
// This MUST be one of the following values:
// !- `individual`: This represents a single person.
// !- `group`: This represents a group of people.
// !- `resource`: This represents some resource, e.g. a projector.
// !- `location`: This represents a location.
// !- `other`: This represents some other undefined principal.
type PrincipalTypeOption string
// Algorithms in this list MUST be present in the ["HTTP Digest Algorithm Values" registry]
// defined by [RFC3230]; however, in JMAP, they must be lowercased, e.g., "md5" rather than
// "MD5".
//
// Clients SHOULD prefer algorithms listed earlier in this list.
//
// ["HTTP Digest Algorithm Values" registry]: https://www.iana.org/assignments/http-dig-alg/http-dig-alg.xhtml
type HttpDigestAlgorithm string
// The ResourceType data type is used to act as a unit of measure for the quota usage.
type ResourceType string
// The Scope data type is used to represent the entities the quota applies to.
type Scope string
// Determines which action must be performed by the MUA or MTA upon receiption.
//
// !- `manual-action`: the disposition described by the disposition type was a result of an
// explicit instruction by the user rather than some sort of automatically performed action.
// (This might include the case when the user has manually configured her MUA to automatically
// respond to valid MDN requests.) Unless prescribed otherwise in a particular mail environment,
// in order to preserve the user's privacy, this MUST be the default for MUAs.
// !- `automatic-action`: the disposition described by the disposition type was a result of an
// automatic action rather than an explicit instruction by the user for this message. This
// is typically generated by a Mail Delivery Agent (e.g., MDN generations by Sieve reject action
// [RFC5429], Fax-over-Email [RFC3249], voice message system (see Voice Profile for Internet
// Mail (VPIM) [RFC3801]), or upon delivery to a mailing list).
type ActionMode string
type SendingMode string
type DispositionTypeOption string
type Duration string
const (
JmapCore = "urn:ietf:params:jmap:core"
JmapMail = "urn:ietf:params:jmap:mail"
JmapMDN = "urn:ietf:params:jmap:mdn" // https://datatracker.ietf.org/doc/rfc9007/
JmapSubmission = "urn:ietf:params:jmap:submission"
JmapVacationResponse = "urn:ietf:params:jmap:vacationresponse"
JmapCalendars = "urn:ietf:params:jmap:calendars"
JmapContacts = "urn:ietf:params:jmap:contacts"
JmapSieve = "urn:ietf:params:jmap:sieve"
JmapBlob = "urn:ietf:params:jmap:blob"
JmapQuota = "urn:ietf:params:jmap:quota"
JmapWebsocket = "urn:ietf:params:jmap:websocket"
JmapPrincipals = "urn:ietf:params:jmap:principals"
JmapPrincipalsOwner = "urn:ietf:params:jmap:principals:owner"
JmapTasks = "urn:ietf:params:jmap:tasks"
JmapTasksRecurrences = "urn:ietf:params:jmap:tasks:recurrences"
JmapTasksAssignees = "urn:ietf:params:jmap:tasks:assignees"
JmapTasksAlerts = "urn:ietf:params:jmap:tasks:alerts"
JmapTasksMultilingual = "urn:ietf:params:jmap:tasks:multilingual"
JmapTasksCustomTimezones = "urn:ietf:params:jmap:tasks:customtimezones"
CoreType = ObjectType("Core")
PushSubscriptionType = ObjectType("PushSubscription")
MailboxType = ObjectType("Mailbox")
ThreadType = ObjectType("Thread")
EmailType = ObjectType("Email")
EmailDeliveryType = ObjectType("EmailDelivery")
SearchSnippetType = ObjectType("SearchSnippet")
IdentityType = ObjectType("Identity")
EmailSubmissionType = ObjectType("EmailSubmission")
VacationResponseType = ObjectType("VacationResponse")
MDNType = ObjectType("MDN")
QuotaType = ObjectType("Quota")
SieveScriptType = ObjectType("SieveScript")
PrincipalType = ObjectType("PrincipalType")
ShareNotificationType = ObjectType("ShareNotification")
AddressBookType = ObjectType("AddressBook")
ContactCardType = ObjectType("ContactCard")
CalendarType = ObjectType("Calendar")
CalendarEventType = ObjectType("CalendarEvent")
CalendarEventNotificationType = ObjectType("CalendarEventNotification")
ParticipantIdentityType = ObjectType("ParticipantIdentity")
JmapKeywordPrefix = "$"
JmapKeywordSeen = "$seen"
JmapKeywordDraft = "$draft"
JmapKeywordFlagged = "$flagged"
JmapKeywordAnswered = "$answered"
JmapKeywordForwarded = "$forwarded"
JmapKeywordPhishing = "$phishing"
JmapKeywordJunk = "$junk"
JmapKeywordNotJunk = "$notjunk"
JmapKeywordMdnSent = "$mdnsent"
// https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml
//JmapMailboxRoleAll = "all"
//JmapMailboxRoleArchive = "archive"
JmapMailboxRoleDrafts = "drafts"
//JmapMailboxRoleFlagged = "flagged"
//JmapMailboxRoleImportant = "important"
JmapMailboxRoleInbox = "inbox"
JmapMailboxRoleJunk = "junk"
JmapMailboxRoleSent = "sent"
//JmapMailboxRoleSubscribed = "subscribed"
JmapMailboxRoleTrash = "trash"
CalendarAlertType = TypeOfCalendarAlert("CalendarAlert")
CalendarEventNotificationTypeOptionCreated = CalendarEventNotificationTypeOption("created")
CalendarEventNotificationTypeOptionUpdated = CalendarEventNotificationTypeOption("updated")
CalendarEventNotificationTypeOptionDestroyed = CalendarEventNotificationTypeOption("destroyed")
// This represents a single person.
PrincipalTypeOptionIndividual = PrincipalTypeOption("individual")
// This represents a group of people.
PrincipalTypeOptionGroup = PrincipalTypeOption("group")
// This represents some resource, e.g. a projector.
PrincipalTypeOptionResource = PrincipalTypeOption("resource")
// This represents a location.
PrincipalTypeOptionLocation = PrincipalTypeOption("location")
// This represents some other undefined principal.
PrincipalTypeOptionOther = PrincipalTypeOption("other")
HttpDigestAlgorithmAdler32 = HttpDigestAlgorithm("adler32")
HttpDigestAlgorithmCrc32c = HttpDigestAlgorithm("crc32c")
HttpDigestAlgorithmMd5 = HttpDigestAlgorithm("md5")
HttpDigestAlgorithmSha = HttpDigestAlgorithm("sha")
HttpDigestAlgorithmSha256 = HttpDigestAlgorithm("sha-256")
HttpDigestAlgorithmSha512 = HttpDigestAlgorithm("sha-512")
HttpDigestAlgorithmUnixSum = HttpDigestAlgorithm("unixsum")
HttpDigestAlgorithmUnixcksum = HttpDigestAlgorithm("unixcksum")
// The quota is measured in a number of data type objects.
//
// For example, a quota can have a limit of 50 `Mail` objects.
ResourceTypeCount = ResourceType("count")
// The quota is measured in size (in octets).
//
// For example, a quota can have a limit of 25000 octets.
ResourceTypeOctets = ResourceType("octets")
// The quota information applies to just the client's account.
ScopeAccount = Scope("account")
// The quota information applies to all accounts sharing this domain.
ScopeDomain = Scope("domain")
// The quota information applies to all accounts belonging to the server.
ScopeGlobal = Scope("global")
// The disposition described by the disposition type was a result of an explicit instruction by the
// user rather than some sort of automatically performed action.
//
// (This might include the case when the user has manually configured her MUA to automatically
// respond to valid MDN requests.)
//
// Unless prescribed otherwise in a particular mail environment, in order to preserve the user's
// privacy, this MUST be the default for MUAs.
ActionModeManualAction = ActionMode("manual-action")
// The disposition described by the disposition type was a result of an automatic action rather than
// an explicit instruction by the user for this message.
//
// This is typically generated by a Mail Delivery Agent (e.g., MDN generations by Sieve reject
// action [RFC5429], Fax-over-Email [RFC3249], voice message system (see Voice Profile
// for Internet Mail (VPIM) [RFC3801]), or upon delivery to a mailing list).
ActionModeAutomaticAction = ActionMode("automatic-action")
// The user explicitly gave permission for this particular MDN to be sent.
//
// Unless prescribed otherwise in a particular mail environment, in order to preserve the
// user's privacy, this MUST be the default for MUAs.
SendingModeMdnSentManually = SendingMode("mdn-sent-manually")
// The MDN was sent because the MUA had previously been configured to do so automatically.
SendingModeMdnSentAutomatically = SendingMode("mdn-sent-automatically")
// The message has been deleted.
//
// The recipient may or may not have seen the message.
//
// The recipient might "undelete" the message at a later time and read the message.
DispositionTypeOptionDeleted = DispositionTypeOption("deleted")
// The message has been sent somewhere in some manner (e.g., printed, faxed, forwarded) without
// necessarily having been previously displayed to the user.
//
// The user may or may not see the message later.
DispositionTypeOptionDispatched = DispositionTypeOption("dispatched")
// The message has been displayed by the MUA to someone reading the recipient's mailbox.
//
// There is no guarantee that the content has been read or understood.
DispositionTypeOptionDisplayed = DispositionTypeOption("displayed")
// The message has been processed in some manner (i.e., by some sort of rules or server)
// without being displayed to the user.
//
// The user may or may not see the message later, or there may not even be a human user
// associated with the mailbox.
DispositionTypeOptionProcessed = DispositionTypeOption("processed")
// All events are considered.
IncludeInAvailabilityAll = IncludeInAvailability("all")
// Events the user is a confirmed or tentative participant of are considered.
IncludeInAvailabilityAttending = IncludeInAvailability("attending")
// All events are ignored (but may be considered if also in another calendar).
IncludeInAvailabilityNone = IncludeInAvailability("none")
)
var (
ObjectTypes = []ObjectType{
CoreType,
PushSubscriptionType,
MailboxType,
ThreadType,
EmailType,
EmailDeliveryType,
SearchSnippetType,
IdentityType,
EmailSubmissionType,
VacationResponseType,
MDNType,
QuotaType,
SieveScriptType,
PrincipalType,
ShareNotificationType,
AddressBookType,
ContactCardType,
CalendarType,
CalendarEventType,
CalendarEventNotificationType,
ParticipantIdentityType,
}
JmapMailboxRoles = []string{
JmapMailboxRoleInbox,
JmapMailboxRoleSent,
JmapMailboxRoleDrafts,
JmapMailboxRoleJunk,
JmapMailboxRoleTrash,
}
CalendarEventNotificationOptionTypes = []CalendarEventNotificationTypeOption{
CalendarEventNotificationTypeOptionCreated,
CalendarEventNotificationTypeOptionUpdated,
CalendarEventNotificationTypeOptionDestroyed,
}
PrincipalTypeOptions = []PrincipalTypeOption{
PrincipalTypeOptionIndividual,
PrincipalTypeOptionGroup,
PrincipalTypeOptionResource,
PrincipalTypeOptionLocation,
PrincipalTypeOptionOther,
}
HttpDigestAlgorithms = []HttpDigestAlgorithm{
HttpDigestAlgorithmAdler32,
HttpDigestAlgorithmCrc32c,
HttpDigestAlgorithmMd5,
HttpDigestAlgorithmSha,
HttpDigestAlgorithmSha256,
HttpDigestAlgorithmSha512,
HttpDigestAlgorithmUnixSum,
HttpDigestAlgorithmUnixcksum,
}
ResourceTypes = []ResourceType{
ResourceTypeCount,
ResourceTypeOctets,
}
Scopes = []Scope{
ScopeAccount,
ScopeDomain,
ScopeGlobal,
}
ActionModes = []ActionMode{
ActionModeManualAction,
ActionModeAutomaticAction,
}
SendingModes = []SendingMode{
SendingModeMdnSentManually,
SendingModeMdnSentAutomatically,
}
DispositionTypeOptions = []DispositionTypeOption{
DispositionTypeOptionDeleted,
DispositionTypeOptionDispatched,
DispositionTypeOptionDisplayed,
DispositionTypeOptionProcessed,
}
IncludeInAvailabilities = []IncludeInAvailability{
IncludeInAvailabilityAll,
IncludeInAvailabilityAttending,
IncludeInAvailabilityNone,
}
)
type SessionMailAccountCapabilities struct {
// The maximum number of Mailboxes that can be can assigned to a single Email object.
//
// This MUST be an integer >= 1, or null for no limit (or rather, the limit is always
// the number of Mailboxes in the account).
MaxMailboxesPerEmail int `json:"maxMailboxesPerEmail"`
// The maximum depth of the Mailbox hierarchy (i.e., one more than the maximum
// number of ancestors a Mailbox may have), or null for no limit.
MaxMailboxDepth int `json:"maxMailboxDepth"`
// The maximum length, in (UTF-8) octets, allowed for the name of a Mailbox.
//
// This MUST be at least 100, although it is recommended servers allow more.
MaxSizeMailboxName int `json:"maxSizeMailboxName"`
// The maximum total size of attachments, in octets, allowed for a single Email object.
//
// A server MAY still reject the import or creation of an Email with a lower attachment size
// total (for example, if the body includes several megabytes of text, causing the size of
// the encoded MIME structure to be over some server-defined limit).
//
// Note that this limit is for the sum of unencoded attachment sizes. Users are generally
// not knowledgeable about encoding overhead, etc., nor should they need to be, so marketing
// and help materials normally tell them the “max size attachments”.
//
// This is the unencoded size they see on their hard drive, so this capability matches that
// and allows the client to consistently enforce what the user understands as the limit.
//
// The server may separately have a limit for the total size of the message [RFC5322],
// created by combining the attachments (often base64 encoded) with the message headers and bodies.
//
// For example, suppose the server advertises maxSizeAttachmentsPerEmail: 50000000 (50 MB).
// The enforced server limit may be for a message size of 70000000 octets.
// Even with base64 encoding and a 2 MB HTML body, 50 MB attachments would fit under this limit.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
MaxSizeAttachmentsPerEmail int `json:"maxSizeAttachmentsPerEmail"`
// A list of all the values the server supports for the “property” field of the Comparator
// object in an Email/query sort.
//
// This MAY include properties the client does not recognise (for example, custom properties
// specified in a vendor extension). Clients MUST ignore any unknown properties in the list.
EmailQuerySortOptions []string `json:"emailQuerySortOptions"`
// If true, the user may create a Mailbox in this account with a null parentId.
//
// (Permission for creating a child of an existing Mailbox is given by the myRights property
// on that Mailbox.)
MayCreateTopLevelMailbox bool `json:"mayCreateTopLevelMailbox"`
}
type SessionSubmissionAccountCapabilities struct {
// The number in seconds of the maximum delay the server supports in sending.
//
// This is 0 if the server does not support delayed send.
MaxDelayedSend int `json:"maxDelayedSend"`
// The set of SMTP submission extensions supported by the server, which the client may use
// when creating an EmailSubmission object.
//
// Each key in the object is the ehlo-name, and the value is a list of ehlo-args.
//
// A JMAP implementation that talks to a submission server [RFC6409] SHOULD have a configuration
// setting that allows an administrator to modify the set of submission EHLO capabilities it may
// expose on this property.
//
// This allows a JMAP server to easily add access to a new submission extension without code changes.
//
// By default, the JMAP server should hide EHLO capabilities that have to do with the transport
// mechanism and thus are only relevant to the JMAP server (for example, PIPELINING, CHUNKING, or STARTTLS).
//
// Examples of Submission extensions to include:
// - FUTURERELEASE [RFC4865]
// - SIZE [RFC1870]
// - DSN [RFC3461]
// - DELIVERYBY [RFC2852]
// - MT-PRIORITY [RFC6710]
//
// A JMAP server MAY advertise an extension and implement the semantics of that extension locally
// on the JMAP server even if a submission server used by JMAP doesn’t implement it.
//
// The full IANA registry of submission extensions can be found at [iana.org].
//
// [RFC6409]: https://www.rfc-editor.org/rfc/rfc6409.html
// [RFC4865]: https://www.rfc-editor.org/rfc/rfc4865.html
// [RFC1870]: https://www.rfc-editor.org/rfc/rfc1870.html
// [RFC3461]: https://www.rfc-editor.org/rfc/rfc3461.html
// [RFC2852]: https://www.rfc-editor.org/rfc/rfc2852.html
// [RFC6710]: https://www.rfc-editor.org/rfc/rfc6710.html
// [iana.org]: https://www.iana.org/assignments/mail-parameters
SubmissionExtensions map[string][]string `json:"submissionExtensions"`
}
// This represents support for the VacationResponse data type and associated API methods.
//
// The value of this property is an empty object in both the JMAP session capabilities
// property and an account’s accountCapabilities property.
type SessionVacationResponseAccountCapabilities struct {
}
type SessionSieveAccountCapabilities struct {
// The maximum length, in octets, allowed for the name of a SieveScript.
//
// For compatibility with ManageSieve, this MUST be at least 512 (up to 128 Unicode characters).
MaxSizeScriptName int `json:"maxSizeScriptName"`
// The maximum size (in octets) of a Sieve script the server is willing to store for the user,
// or null for no limit.
MaxSizeScript int `json:"maxSizeScript"`
// The maximum number of Sieve scripts the server is willing to store for the user, or null for no limit.
MaxNumberScripts int `json:"maxNumberScripts"`
// The maximum number of Sieve "redirect" actions a script can perform during a single evaluation,
// or null for no limit.
//
// Note that this is different from the total number of "redirect" actions a script can contain.
MaxNumberRedirects int `json:"maxNumberRedirects"`
// A list of case-sensitive Sieve capability strings (as listed in the Sieve "require" action;
// see [RFC5228, Section 3.2]) indicating the extensions supported by the Sieve engine.
//
// [RFC5228, Section 3.2]: https://www.rfc-editor.org/rfc/rfc5228.html#section-3.2
SieveExtensions []string `json:"sieveExtensions"`
// A list of URI scheme parts [RFC3986] for notification methods supported by the Sieve "enotify"
// extension [RFC5435], or null if the extension is not supported by the Sieve engine.
//
// [RFC3986]: https://www.rfc-editor.org/rfc/rfc3986.html
// [RFC5435]: https://www.rfc-editor.org/rfc/rfc5435.html
NotificationMethods []string `json:"notificationMethods"`
// A list of URI scheme parts [RFC3986] for externally stored list types supported by the
// Sieve "extlists" extension [RFC6134], or null if the extension is not supported by the Sieve engine.
//
// [RFC3986]: https://www.rfc-editor.org/rfc/rfc3986.html
// [RFC6134]: https://www.rfc-editor.org/rfc/rfc6134.html
ExternalLists []string `json:"externalLists"`
}
type SessionBlobAccountCapabilities struct {
// The maximum size of the blob (in octets) that the server will allow to be created
// (including blobs created by concatenating multiple data sources together).
//
// Clients MUST NOT attempt to create blobs larger than this size.
//
// If this value is null, then clients are not required to limit the size of the blob
// they try to create, though servers can always reject creation of blobs regardless of
// size, e.g., due to lack of disk space or per-user rate limits.
MaxSizeBlobSet int `json:"maxSizeBlobSet"`
// The maximum number of DataSourceObjects allowed per creation in a Blob/upload.
//
// Servers MUST allow at least 64 DataSourceObjects per creation.
MaxDataSources int `json:"maxDataSources"`
// An array of data type names that are supported for Blob/lookup.
//
// If the server does not support lookups, then this will be the empty list.
//
// Note that the supportedTypeNames list may include private types that are not in the
// "JMAP Data Types" registry defined by this document.
//
// Clients MUST ignore type names they do not recognise.
SupportedTypeNames []string `json:"supportedTypeNames"`
// An array of supported digest algorithms that are supported for Blob/get.
//
// If the server does not support calculating blob digests, then this will be the empty
// list.
//
// Algorithms in this list MUST be present in the ["HTTP Digest Algorithm Values" registry]
// defined by [RFC3230]; however, in JMAP, they must be lowercased, e.g., "md5" rather than
// "MD5".
//
// Clients SHOULD prefer algorithms listed earlier in this list.
//
// ["HTTP Digest Algorithm Values" registry]: https://www.iana.org/assignments/http-dig-alg/http-dig-alg.xhtml
SupportedDigestAlgorithms []HttpDigestAlgorithm `json:"supportedDigestAlgorithms"`
}
type SessionQuotaAccountCapabilities struct {
}
type SessionContactsAccountCapabilities struct {
// The maximum number of AddressBooks that can be can assigned to a single ContactCard object.
//
// This MUST be an integer >= 1, or null for no limit (or rather, the limit is always the number of AddressBooks
// in the account).
MaxAddressBooksPerCard uint `json:"maxAddressBooksPerCard,omitzero"`
// If true, the user may create an AddressBook in this account.
MayCreateAddressBook bool `json:"mayCreateAddressBook"`
}
type SessionCalendarsAccountCapabilities struct {
// The maximum number of Calendars that can be assigned to a single CalendarEvent object.
//
// This MUST be an integer >= 1, or null for no limit (or rather, the limit is always the
// number of Calendars in the account).
MaxCalendarsPerEvent *uint `json:"maxCalendarsPerEvent,omitempty"`
// The earliest date-time value the server is willing to accept for any date stored in a CalendarEvent.
MinDateTime *UTCDate `json:"minDateTime,omitempty"`
// The latest date-time value the server is willing to accept for any date stored in a CalendarEvent.
MaxDateTime *UTCDate `json:"maxDateTime,omitempty"`
// The maximum duration the user may query over when asking the server to expand recurrences.
MaxExpandedQueryDuration Duration `json:"maxExpandedQueryDuration,omitzero"`
// The maximum number of participants a single event may have, or null for no limit.
MaxParticipantsPerEvent *uint `json:"maxParticipantsPerEvent,omitzero"`
// If true, the user may create a calendar in this account.
MayCreateCalendar *bool `json:"mayCreateCalendar,omitempty"`
}
type SessionCalendarsParseAccountCapabilities struct {
}
type SessionTasksAccountCapabilities struct {
// The earliest date-time the server is willing to accept for any date stored in a Task.
MinDateTime LocalDate `json:"minDateTime,omitzero"`
// The latest date-time the server is willing to accept for any date stored in a Task.
MaxDateTime LocalDate `json:"maxDateTime,omitzero"`
// If true, the user may create a task list in this account.
MayCreateTaskList bool `json:"mayCreateTaskList"`
}
type SessionTasksRecurrencesAccountCapabilities struct {
// The maximum duration the user may query over when asking the server to expand recurrences.
MaxExpandedQueryDuration Duration `json:"maxExpandedQueryDuration"`
}
type SessionTasksAssigneesAccountCapabilities struct {
// The maximum number of participants a single task may have, or null for no limit.
MaxParticipantsPerTask *uint `json:"maxParticipantsPerTask,omitzero"`
}
type SessionTasksAlertsAccountCapabilities struct {
}
type SessionTasksMultilingualAccountCapabilities struct {
}
type SessionTasksCustomTimezonesAccountCapabilities struct {
}
type SessionPrincipalsAccountCapabilities struct {
// The id of the principal in this account that corresponds to the user fetching this object, if any.
CurrentUserPrincipalId string `json:"currentUserPrincipalId,omitempty"`
}
type SessionPrincipalsOwnerAccountCapabilities struct {
// The id of an account with the `urn:ietf:params:jmap:principals` capability that contains the
// corresponding `Principal` object.
AccountIdForPrincipal string `json:"accountIdForPrincipal,omitempty"`
// The id of the `Principal` that owns this account.
PrincipalId string `json:"principalId,omitempty"`
}
type SessionPrincipalAvailabilityAccountCapabilities struct {
// The maximum duration over which the server is prepared to calculate availability in a single call.
MaxAvailabilityDuration Duration `json:"maxAvailabilityDuration"`
}
type SessionMDNAccountCapabilities struct {
}
type SessionAccountCapabilities struct {
Mail *SessionMailAccountCapabilities `json:"urn:ietf:params:jmap:mail,omitempty"`
Submission *SessionSubmissionAccountCapabilities `json:"urn:ietf:params:jmap:submission,omitempty"`
VacationResponse *SessionVacationResponseAccountCapabilities `json:"urn:ietf:params:jmap:vacationresponse,omitempty"`
Sieve *SessionSieveAccountCapabilities `json:"urn:ietf:params:jmap:sieve,omitempty"`
Blob *SessionBlobAccountCapabilities `json:"urn:ietf:params:jmap:blob,omitempty"`
Quota *SessionQuotaAccountCapabilities `json:"urn:ietf:params:jmap:quota,omitempty"`
Contacts *SessionContactsAccountCapabilities `json:"urn:ietf:params:jmap:contacts,omitempty"`
Calendars *SessionCalendarsAccountCapabilities `json:"urn:ietf:params:jmap:calendars,omitempty"`
CalendarsParse *SessionCalendarsParseAccountCapabilities `json:"urn:ietf:params:jmap:calendars:parse,omitempty"`
Tasks *SessionTasksAccountCapabilities `json:"urn:ietf:params:jmap:tasks,omitempty"`
TasksRecurrences *SessionTasksRecurrencesAccountCapabilities `json:"urn:ietf:params:jmap:tasks:recurrences,omitempty"`
TasksAssignees *SessionTasksAssigneesAccountCapabilities `json:"urn:ietf:params:jmap:tasks:assignees,omitempty"`
TasksAlerts *SessionTasksAlertsAccountCapabilities `json:"urn:ietf:params:jmap:tasks:alerts,omitempty"`
TasksMultilingual *SessionTasksMultilingualAccountCapabilities `json:"urn:ietf:params:jmap:tasks:multilingual,omitempty"`
TasksCustomTimezones *SessionTasksCustomTimezonesAccountCapabilities `json:"urn:ietf:params:jmap:tasks:customtimezones,omitempty"`
Principals *SessionPrincipalsAccountCapabilities `json:"urn:ietf:params:jmap:principals,omitempty"`
PrincipalsOwner *SessionPrincipalsOwnerAccountCapabilities `json:"urn:ietf:params:jmap:principals:owner,omitempty"`
PrincipalsAvailability *SessionPrincipalAvailabilityAccountCapabilities `json:"urn:ietf:params:jmap:principals:availability,omitempty"`
MDN *SessionMDNAccountCapabilities `json:"urn:ietf:params:jmap:mdn,omitempty"`
}
type Account struct {
// A user-friendly string to show when presenting content from this account, e.g., the email address representing the owner of the account.
Name string `json:"name,omitempty"`
// This is true if the account belongs to the authenticated user rather than a group account or a personal account of another user that has been shared with them.
IsPersonal bool `json:"isPersonal"`
// This is true if the entire account is read-only.
IsReadOnly bool `json:"isReadOnly"`
// Account capabilities.
AccountCapabilities SessionAccountCapabilities `json:"accountCapabilities"`
}
type SessionCoreCapabilities struct {
// The maximum file size, in octets, that the server will accept for a single file upload (for any purpose)
MaxSizeUpload int `json:"maxSizeUpload"`
// The maximum number of concurrent requests the server will accept to the upload endpoint.
MaxConcurrentUpload int `json:"maxConcurrentUpload"`
// The maximum size, in octets, that the server will accept for a single request to the API endpoint.
MaxSizeRequest int `json:"maxSizeRequest"`
// The maximum number of concurrent requests the server will accept to the API endpoint.
MaxConcurrentRequests int `json:"maxConcurrentRequests"`
// The maximum number of method calls the server will accept in a single request to the API endpoint.
MaxCallsInRequest int `json:"maxCallsInRequest"`
// The maximum number of objects that the client may request in a single /get type method call.
MaxObjectsInGet int `json:"maxObjectsInGet"`
// The maximum number of objects the client may send to create, update, or destroy in a single /set type method call.
// This is the combined total, e.g., if the maximum is 10, you could not create 7 objects and destroy 6, as this would be 13 actions,
// which exceeds the limit.
MaxObjectsInSet int `json:"maxObjectsInSet"`
// A list of identifiers for algorithms registered in the collation registry, as defined in [@!RFC4790], that the server
// supports for sorting when querying records.
CollationAlgorithms []string `json:"collationAlgorithms,omitempty"`
}
type SessionMailCapabilities struct {
}
type SessionSubmissionCapabilities struct {
}
type SessionVacationResponseCapabilities struct {
}
type SessionSieveCapabilities struct {
}
type SessionBlobCapabilities struct {
}
type SessionQuotaCapabilities struct {
}
type SessionWebsocketCapabilities struct {
// The wss-URI (see [Section 3 of RFC6455]) to use for initiating a JMAP-over-WebSocket
// handshake (the "WebSocket URL endpoint" colloquially).
//
// [Section 3 of RFC6455]: https://www.rfc-editor.org/rfc/rfc6455.html#section-3
Url string `json:"url"`
// This is true if the server supports push notifications over the WebSocket,
// as described in [Section 4.3.5 of RFC 8887].
//
// [Section 4.3.5 of RFC 8887]: https://www.rfc-editor.org/rfc/rfc8887.html#name-jmap-push-notifications
SupportsPush bool `json:"supportsPush"`
}
type SessionContactsCapabilities struct {
}
type SessionCalendarsCapabilities struct {
}
type SessionCalendarsParseCapabilities struct {
}
type SessionTasksCapabilities struct {
}
type SessionTasksRecurrencesCapabilities struct {
}
type SessionTasksAssigneesCapabilities struct {
}
type SessionTasksAlertsCapabilities struct {
}
type SessionTasksMultilingualCapabilities struct {
}
type SessionTasksCustomTimezonesCapabilities struct {
}
type SessionPrincipalCapabilities struct {
// Id of Account with the urn:ietf:params:jmap:calendars capability that contains the calendar data
// for this Principal, or null if either (a) there is none (e.g. the Principal is a group just used
// for permissions management), or (b) the user does not have access to any data in the account
// (with the exception of free/busy, which is governed by the "mayGetAvailability" property).
//
// The corresponding Account object can be found in the Principal's "accounts" property, as
// per Section 2 of [RFC9670].
AccountId string `json:"accountId,omitempty"`
// If true, the user may call the "Principal/getAvailability" method with this Principal.
MayGetAvailability *bool `json:"mayGetAvailability,omitzero"`
// If true, the user may add this Principal as a calendar share target (by adding them to the
// "shareWith" property of a calendar, see Section 4).
MayShareWith *bool `json:"mayShareWith,omitzero"`
// If this Principal may be added as a participant to an event, this is the calendarAddress to
// use to receive iTIP scheduling messages.
CalendarAddress string `json:"calendarAddress,omitempty"`
}
type SessionPrincipalAvailabilityCapabilities struct {
}
type SessionMDNCapabilities struct {
}
type SessionCapabilities struct {
Core *SessionCoreCapabilities `json:"urn:ietf:params:jmap:core,omitempty"`
Mail *SessionMailCapabilities `json:"urn:ietf:params:jmap:mail,omitempty"`
Submission *SessionSubmissionCapabilities `json:"urn:ietf:params:jmap:submission,omitempty"`
VacationResponse *SessionVacationResponseCapabilities `json:"urn:ietf:params:jmap:vacationresponse,omitempty"`
Sieve *SessionSieveCapabilities `json:"urn:ietf:params:jmap:sieve,omitempty"`
Blob *SessionBlobCapabilities `json:"urn:ietf:params:jmap:blob,omitempty"`
Quota *SessionQuotaCapabilities `json:"urn:ietf:params:jmap:quota,omitempty"`
Websocket *SessionWebsocketCapabilities `json:"urn:ietf:params:jmap:websocket,omitempty"`
// This represents support for the `AddressBook` and `ContactCard` data types and associated API methods.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
Contacts *SessionContactsCapabilities `json:"urn:ietf:params:jmap:contacts,omitempty"`
// This represents support for the `Calendar`, `CalendarEvent`, `CalendarEventNotification`,
// and `ParticipantIdentity` data types and associated API methods, except for `CalendarEvent/parse`.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
Calendars *SessionCalendarsCapabilities `json:"urn:ietf:params:jmap:calendars,omitempty"`
// This represents support for the `CalendarEvent/parse` method.
//
// The value of this property is an empty object in the JMAP session `capabilities` property.
CalendarsParse *SessionCalendarsParseCapabilities `json:"urn:ietf:params:jmap:calendars:parse,omitempty"`
// This represents support for the core properties and objects of the `TaskList`,
// `Task` and `TaskNotification` data types and associated API methods.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
Tasks *SessionTasksCapabilities `json:"urn:ietf:params:jmap:tasks,omitempty"`
// This represents support for the `recurrence` properties and objects of the `TaskList`,
// `Task` and `TaskNotification` data types and associated API methods.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
TasksRecurrences *SessionTasksRecurrencesCapabilities `json:"urn:ietf:params:jmap:tasks:recurrences,omitempty"`
// This represents support for the `assignee` properties and objects of the `TaskList`,
// `Task` and `TaskNotification` data types and associated API methods.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
TasksAssignees *SessionTasksAssigneesCapabilities `json:"urn:ietf:params:jmap:tasks:assignees,omitempty"`
// This represents support for the `alerts` properties and objects of the `TaskList`,
// `Task` and `TaskNotification` data types and associated API methods.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
TasksAlerts *SessionTasksAlertsCapabilities `json:"urn:ietf:params:jmap:tasks:alerts,omitempty"`
// This represents support for the multilingual properties and objects of the `TaskList`,
// `Task` and `TaskNotification` data types and associated API methods.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
TasksMultilingual *SessionTasksMultilingualCapabilities `json:"urn:ietf:params:jmap:tasks:multilingual,omitempty"`
// This represents support for the custom time zone properties and objects of the `TaskList`,
// `Task` and `TaskNotification` data types and associated API methods.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
TasksCustomTimezones *SessionTasksCustomTimezonesCapabilities `json:"urn:ietf:params:jmap:tasks:customtimezones,omitempty"`
Principals *SessionPrincipalCapabilities `json:"urn:ietf:params:jmap:principals,omitempty"`
// Represents support for the `Principal/getAvailability` method.
//
// Any account with this capability MUST also have the `urn:ietf:params:jmap:principals` capability.
//
// The value of this property in the JMAP Session `capabilities` property is an empty object.
PrincipalsAvailability *SessionPrincipalAvailabilityCapabilities `json:"urn:ietf:params:jmap:principals:availability,omitempty"`
MDN *SessionMDNCapabilities `json:"urn:ietf:params:jmap:mdn,omitempty"`
}
type SessionPrimaryAccounts struct {
Core string `json:"urn:ietf:params:jmap:core,omitempty"`
Mail string `json:"urn:ietf:params:jmap:mail,omitempty"`
Submission string `json:"urn:ietf:params:jmap:submission,omitempty"`
VacationResponse string `json:"urn:ietf:params:jmap:vacationresponse,omitempty"`
Sieve string `json:"urn:ietf:params:jmap:sieve,omitempty"`
Blob string `json:"urn:ietf:params:jmap:blob,omitempty"`
Quota string `json:"urn:ietf:params:jmap:quota,omitempty"`
Websocket string `json:"urn:ietf:params:jmap:websocket,omitempty"`
Task string `json:"urn:ietf:params:jmap:task,omitempty"`
Calendars string `json:"urn:ietf:params:jmap:calendars,omitempty"`
CalendarsParse string `json:"urn:ietf:params:jmap:calendars:parse,omitempty"`
Contacts string `json:"urn:ietf:params:jmap:contacts,omitempty"`
ContactsParse string `json:"urn:ietf:params:jmap:contacts:parse,omitempty"`
}
type SessionState string
type State string
type Language string
type SessionResponse struct {
Capabilities SessionCapabilities `json:"capabilities"`
Accounts map[string]Account `json:"accounts,omitempty"`
// A map of capability URIs (as found in accountCapabilities) to the account id that is considered to be the user’s main or default
// account for data pertaining to that capability.
// If no account being returned belongs to the user, or in any other way there is no appropriate way to determine a default account,
// there MAY be no entry for a particular URI, even though that capability is supported by the server (and in the capabilities object).
// urn:ietf:params:jmap:core SHOULD NOT be present.
PrimaryAccounts SessionPrimaryAccounts `json:"primaryAccounts"`
// The username associated with the given credentials, or the empty string if none.
Username string `json:"username,omitempty"`
// The URL to use for JMAP API requests.
ApiUrl string `json:"apiUrl,omitempty"`
// The URL endpoint to use when downloading files, in URI Template (level 1) format [@!RFC6570].
// The URL MUST contain variables called accountId, blobId, type, and name.
DownloadUrl string `json:"downloadUrl,omitempty"`
// The URL endpoint to use when uploading files, in URI Template (level 1) format [@!RFC6570].
// The URL MUST contain a variable called accountId.
UploadUrl string `json:"uploadUrl,omitempty"`
// The URL to connect to for push events, as described in Section 7.3, in URI Template (level 1) format [@!RFC6570].
// The URL MUST contain variables called types, closeafter, and ping.
EventSourceUrl string `json:"eventSourceUrl,omitempty"`
// A (preferably short) string representing the state of this object on the server.
// If the value of any other property on the Session object changes, this string will change.
// The current value is also returned on the API Response object (see Section 3.4), allowing clients to quickly
// determine if the session information has changed (e.g., an account has been added or removed),
// so they need to refetch the object.
State SessionState `json:"state,omitempty"`
}
// Method level error types.
const (
// Some internal server resource was temporarily unavailable.
//
// Attempting the same operation later (perhaps after a backoff with a random factor) may succeed.
MethodLevelErrorServerUnavailable = "serverUnavailable"
// An unexpected or unknown error occurred during the processing of the call.
//
// A description property should provide more details about the error. The method call made no changes
// to the server’s state. Attempting the same operation again is expected to fail again.
// Contacting the service administrator is likely necessary to resolve this problem if it is persistent.
MethodLevelErrorServerFail = "serverFail"
// Some, but not all, expected changes described by the method occurred.
//
// The client MUST resynchronise impacted data to determine server state. Use of this error is strongly discouraged.
MethodLevelErrorServerPartialFail = "serverPartialFail"
// The server does not recognise this method name.
MethodLevelErrorUnknownMethod = "unknownMethod"
// One of the arguments is of the wrong type or is otherwise invalid, or a required argument is missing.
//
// A description property MAY be present to help debug with an explanation of what the problem was.
// This is a non-localised string, and it is not intended to be shown directly to end users.
MethodLevelErrorInvalidArguments = "invalidArguments"
// The method used a result reference for one of its arguments, but this failed to resolve.
MethodLevelErrorInvalidResultReference = "invalidResultReference"
// The method and arguments are valid, but executing the method would violate an Access Control List
// (ACL) or other permissions policy.
MethodLevelErrorForbidden = "forbidden"
// The accountId does not correspond to a valid account.
MethodLevelErrorAccountNotFound = "accountNotFound"
// The accountId given corresponds to a valid account, but the account does not support this method or data type.
MethodLevelErrorAccountNotSupportedByMethod = "accountNotSupportedByMethod"
// This method modifies state, but the account is read-only (as returned on the corresponding Account object in
// the JMAP Session resource).
MethodLevelErrorAccountReadOnly = "accountReadOnly"
)
// SetError type values.
const (
// The create/update/destroy would violate an ACL or other permissions policy.
//
// (create; update; destroy).
SetErrorTypeForbidden = "forbidden"
// The create would exceed a server-defined limit on the number or total size of objects of this type.
//
// (create; update).
SetErrorTypeOverQuota = "overQuota"
// The create/update would result in an object that exceeds a server-defined limit for the maximum
// size of a single object of this type.
//
// (create; update).
SetErrorTypeTooLarge = "tooLarge"
// Too many objects of this type have been created recently, and a server-defined rate limit has been reached.
// It may work if tried again later.
//
// (create).
SetErrorTypeRateLimit = "rateLimit"
// The id given to update/destroy cannot be found.
//
// (update; destroy).
SetErrorTypeNotFound = "notFound"
// The PatchObject given to update the record was not a valid patch (see the patch description).
//
// (update).
SetErrorTypeInvalidPatch = "invalidPatch"
// The client requested that an object be both updated and destroyed in the same /set request, and the server
// has decided to therefore ignore the update.
//
// (update).
SetErrorTypeWillDestroy = "willDestroy"
// The record given is invalid in some way. For example:
//
// - It contains properties that are invalid according to the type specification of this record type.
// - It contains a property that may only be set by the server (e.g., “id”) and is different to the current value.
// Note, to allow clients to pass whole objects back, it is not an error to include a server-set property in an
// update as long as the value is identical to the current value on the server.
// - There is a reference to another record (foreign key), and the given id does not correspond to a valid record.
//
// The SetError object SHOULD also have a property called properties of type String[] that lists all the properties
// that were invalid.
//
// Individual methods MAY specify more specific errors for certain conditions that would otherwise result in an
// invalidProperties error. If the condition of one of these is met, it MUST be returned instead of the invalidProperties error.
//
// (create; update).
SetErrorTypeInvalidProperties = "invalidProperties"
// This is a singleton type, so you cannot create another one or destroy the existing one.
//
// (create; destroy).
SetErrorTypeSingleton = "singleton"
// The total number of objects to create, update, or destroy exceeds the maximum number the server is
// willing to process in a single method call.
SetErrorTypeRequestTooLarge = "requestTooLarge"
// An ifInState argument was supplied, and it does not match the current state.
SetErrorTypeStateMismatch = "stateMismatch"
// The Email to be sent is invalid in some way.
//
// The SetError SHOULD contain a property called properties of type String[] that lists all the properties
// of the Email that were invalid.
SetErrorInvalidEmail = "invalidEmail"
// The envelope (supplied or generated) has more recipients than the server allows.
//
// A maxRecipients UnsignedInt property MUST also be present on the SetError specifying
// the maximum number of allowed recipients.
SetErrorTooManyRecipients = "tooManyRecipients"
// The envelope (supplied or generated) does not have any rcptTo email addresses.
SetErrorNoRecipients = "noRecipients"
// The rcptTo property of the envelope (supplied or generated) contains at least one rcptTo value which
// is not a valid email address for sending to.
//
// An invalidRecipients String[] property MUST also be present on the SetError, which is a list of the invalid addresses.
SetErrorInvalidRecipients = "invalidRecipients"
// The server does not permit the user to send a message with this envelope From address [RFC5321].
//
// [RFC5321]: https://datatracker.ietf.org/doc/html/rfc5321
SetErrorForbiddenMailFrom = "forbiddenMailFrom"
// The server does not permit the user to send a message with the From header field [RFC5322] of the message to be sent.
//
// [RFC5322]: https://datatracker.ietf.org/doc/html/rfc5322
SetErrorForbiddenFrom = "forbiddenFrom"
// The user does not have permission to send at all right now for some reason.
//
// A description String property MAY be present on the SetError object to display to the user why they are not permitted.
SetErrorForbiddenToSend = "forbiddenToSend"
// The message has the `$mdnsent` keyword already set.
SetErrorMdnAlreadySent = "mdnAlreadySent"
)
type SetError struct {
// The type of error.
Type string `json:"type"`
// A description of the error to help with debugging that includes an explanation of what the problem was.
//
// This is a non-localised string and is not intended to be shown directly to end users.
Description string `json:"description,omitempty"`
// Lists all the properties of the Email that were invalid.
//
// Only set for the invalidEmail error after a failed EmailSubmission/set errors.
Properties []string `json:"properties,omitempty"`
// Specifies the maximum number of allowed recipients.
//
// Only set for the tooManyRecipients error after a failed EmailSubmission/set errors.
MaxRecipients int `json:"maxRecipients,omitzero"`
// List of invalid addresses.
//
// Only set for the invalidRecipients error after a failed EmailSubmission/set errors.
InvalidRecipients []string `json:"invalidRecipients,omitempty"`
}
type FilterOperatorTerm string
const (
And FilterOperatorTerm = "AND"
Or FilterOperatorTerm = "OR"
Not FilterOperatorTerm = "NOT"
)
type MailboxRights struct {
// If true, the user may use this Mailbox as part of a filter in an Email/query call,
// and the Mailbox may be included in the mailboxIds property of Email objects.
//
// Email objects may be fetched if they are in at least one Mailbox with this permission.
//
// If a sub-Mailbox is shared but not the parent Mailbox, this may be false.
//
// Corresponds to IMAP ACLs lr (if mapping from IMAP, both are required for this to be true).
MayReadItems bool `json:"mayReadItems"`
// The user may add mail to this Mailbox (by either creating a new Email or moving an existing one).
//
// Corresponds to IMAP ACL i.
MayAddItems bool `json:"mayAddItems"`
// The user may remove mail from this Mailbox (by either changing the Mailboxes of an Email or
// destroying the Email).
//
// Corresponds to IMAP ACLs te (if mapping from IMAP, both are required for this to be true).
MayRemoveItems bool `json:"mayRemoveItems"`
// The user may add or remove the $seen keyword to/from an Email.
//
// If an Email belongs to multiple Mailboxes, the user may only modify $seen if they have this
// permission for all of the Mailboxes.
//
// Corresponds to IMAP ACL s.
MaySetSeen bool `json:"maySetSeen"`
// The user may add or remove any keyword other than $seen to/from an Email.
//
// If an Email belongs to multiple Mailboxes, the user may only modify keywords if they have this
// permission for all of the Mailboxes.
//
// Corresponds to IMAP ACL w.
MaySetKeywords bool `json:"maySetKeywords"`
// The user may create a Mailbox with this Mailbox as its parent.
//
// Corresponds to IMAP ACL k.
MayCreateChild bool `json:"mayCreateChild"`
// The user may rename the Mailbox or make it a child of another Mailbox.
//
// Corresponds to IMAP ACL x (although this covers both rename and delete permissions).
MayRename bool `json:"mayRename"`
// The user may delete the Mailbox itself.
//
// Corresponds to IMAP ACL x (although this covers both rename and delete permissions).
MayDelete bool `json:"mayDelete"`
// Messages may be submitted directly to this Mailbox.
//
// Corresponds to IMAP ACL p.
MaySubmit bool `json:"maySubmit"`
}
type Mailbox struct {
// The id of the Mailbox.
Id string `json:"id,omitempty"`
// User-visible name for the Mailbox, e.g., “Inbox”.
//
// This MUST be a Net-Unicode string [@!RFC5198] of at least 1 character in length, subject to the maximum size
// given in the capability object.
//
// There MUST NOT be two sibling Mailboxes with both the same parent and the same name.
//
// Servers MAY reject names that violate server policy (e.g., names containing a slash (/) or control characters).
Name string `json:"name,omitempty"`
// The Mailbox id for the parent of this Mailbox, or null if this Mailbox is at the top level.
//
// Mailboxes form acyclic graphs (forests) directed by the child-to-parent relationship. There MUST NOT be a loop.
ParentId string `json:"parentId,omitempty"`
// Identifies Mailboxes that have a particular common purpose (e.g., the “inbox”), regardless of the name property
// (which may be localised).
//
// This value is shared with IMAP (exposed in IMAP via the SPECIAL-USE extension [RFC6154]).
// However, unlike in IMAP, a Mailbox MUST only have a single role, and there MUST NOT be two Mailboxes in the same
// account with the same role.
//
// Servers providing IMAP access to the same data are encouraged to enforce these extra restrictions in IMAP as well.
// Otherwise, modifying the IMAP attributes to ensure compliance when exposing the data over JMAP is implementation dependent.
//
// The value MUST be one of the Mailbox attribute names listed in the IANA IMAP Mailbox Name Attributes registry,
// as established in [RFC8457], converted to lowercase. New roles may be established here in the future.
//
// An account is not required to have Mailboxes with any particular roles.
//
// [RFC6154]: https://www.rfc-editor.org/rfc/rfc6154.html
// [RFC8457]: https://www.rfc-editor.org/rfc/rfc8457.html
Role string `json:"role,omitempty"`
// Defines the sort order of Mailboxes when presented in the client’s UI, so it is consistent between devices.
//
// Default value: 0
//
// The number MUST be an integer in the range 0 <= sortOrder < 2^31.
//
// A Mailbox with a lower order should be displayed before a Mailbox with a higher order
// (that has the same parent) in any Mailbox listing in the client’s UI.
// Mailboxes with equal order SHOULD be sorted in alphabetical order by name.
// The sorting should take into account locale-specific character order convention.
SortOrder *int `json:"sortOrder,omitempty"`
// The number of Emails in this Mailbox.
TotalEmails int `json:"totalEmails"`
// The number of Emails in this Mailbox that have neither the $seen keyword nor the $draft keyword.
UnreadEmails int `json:"unreadEmails"`
// The number of Threads where at least one Email in the Thread is in this Mailbox.
TotalThreads int `json:"totalThreads"`
// An indication of the number of “unread” Threads in the Mailbox.
UnreadThreads int `json:"unreadThreads"`
// The set of rights (Access Control Lists (ACLs)) the user has in relation to this Mailbox.
//
// These are backwards compatible with IMAP ACLs, as defined in [RFC4314].
//
// [RFC4314]: https://www.rfc-editor.org/rfc/rfc4314.html
MyRights *MailboxRights `json:"myRights,omitempty"`
// Has the user indicated they wish to see this Mailbox in their client?
//
// This SHOULD default to false for Mailboxes in shared accounts the user has access to and true
// for any new Mailboxes created by the user themself.
//
// This MUST be stored separately per user where multiple users have access to a shared Mailbox.
//
// A user may have permission to access a large number of shared accounts, or a shared account with a very
// large set of Mailboxes, but only be interested in the contents of a few of these.
//
// Clients may choose to only display Mailboxes where the isSubscribed property is set to true, and offer
// a separate UI to allow the user to see and subscribe/unsubscribe from the full set of Mailboxes.
//
// However, clients MAY choose to ignore this property, either entirely for ease of implementation or just
// for an account where isPersonal is true (indicating it is the user’s own rather than a shared account).
//
// This property corresponds to IMAP [RFC3501] Mailbox subscriptions.
//
// [RFC3501]: https://www.rfc-editor.org/rfc/rfc3501.html
IsSubscribed *bool `json:"isSubscribed,omitempty"`
}
type MailboxChange struct {
// User-visible name for the Mailbox, e.g., “Inbox”.
//
// This MUST be a Net-Unicode string [@!RFC5198] of at least 1 character in length, subject to the maximum size
// given in the capability object.
//
// There MUST NOT be two sibling Mailboxes with both the same parent and the same name.
//
// Servers MAY reject names that violate server policy (e.g., names containing a slash (/) or control characters).
Name string `json:"name,omitempty"`
// The Mailbox id for the parent of this Mailbox, or null if this Mailbox is at the top level.
//
// Mailboxes form acyclic graphs (forests) directed by the child-to-parent relationship. There MUST NOT be a loop.
ParentId string `json:"parentId,omitempty"`
// Identifies Mailboxes that have a particular common purpose (e.g., the “inbox”), regardless of the name property
// (which may be localised).
//
// This value is shared with IMAP (exposed in IMAP via the SPECIAL-USE extension [RFC6154]).
// However, unlike in IMAP, a Mailbox MUST only have a single role, and there MUST NOT be two Mailboxes in the same
// account with the same role.
//
// Servers providing IMAP access to the same data are encouraged to enforce these extra restrictions in IMAP as well.
// Otherwise, modifying the IMAP attributes to ensure compliance when exposing the data over JMAP is implementation dependent.
//
// The value MUST be one of the Mailbox attribute names listed in the IANA IMAP Mailbox Name Attributes registry,
// as established in [RFC8457], converted to lowercase. New roles may be established here in the future.
//
// An account is not required to have Mailboxes with any particular roles.
//
// [RFC6154]: https://www.rfc-editor.org/rfc/rfc6154.html
// [RFC8457]: https://www.rfc-editor.org/rfc/rfc8457.html
Role string `json:"role,omitempty"`
// Defines the sort order of Mailboxes when presented in the client’s UI, so it is consistent between devices.
//
// Default value: 0
//
// The number MUST be an integer in the range 0 <= sortOrder < 2^31.
//
// A Mailbox with a lower order should be displayed before a Mailbox with a higher order
// (that has the same parent) in any Mailbox listing in the client’s UI.
// Mailboxes with equal order SHOULD be sorted in alphabetical order by name.
// The sorting should take into account locale-specific character order convention.
SortOrder *int `json:"sortOrder,omitempty"`
// Has the user indicated they wish to see this Mailbox in their client?
//
// This SHOULD default to false for Mailboxes in shared accounts the user has access to and true
// for any new Mailboxes created by the user themself.
//
// This MUST be stored separately per user where multiple users have access to a shared Mailbox.
//
// A user may have permission to access a large number of shared accounts, or a shared account with a very
// large set of Mailboxes, but only be interested in the contents of a few of these.
//
// Clients may choose to only display Mailboxes where the isSubscribed property is set to true, and offer
// a separate UI to allow the user to see and subscribe/unsubscribe from the full set of Mailboxes.
//
// However, clients MAY choose to ignore this property, either entirely for ease of implementation or just
// for an account where isPersonal is true (indicating it is the user’s own rather than a shared account).
//
// This property corresponds to IMAP [RFC3501] Mailbox subscriptions.
//
// [RFC3501]: https://www.rfc-editor.org/rfc/rfc3501.html
IsSubscribed *bool `json:"isSubscribed,omitempty"`
}
func (m MailboxChange) AsPatch() PatchObject {
p := PatchObject{}
if m.Name != "" {
p["name"] = m.Name
}
if m.ParentId != "" {
p["parentId"] = m.ParentId
}
if m.Role != "" {
p["role"] = m.Role
}
if m.SortOrder != nil {
p["sortOrder"] = m.SortOrder
}
if m.IsSubscribed != nil {
p["isSubscribed"] = m.IsSubscribed
}
return p
}
type MailboxGetCommand struct {
AccountId string `json:"accountId"`
Ids []string `json:"ids,omitempty"`
}
type MailboxGetRefCommand struct {
AccountId string `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
}
type MailboxSetCommand struct {
AccountId string `json:"accountId"`
IfInState string `json:"ifInState,omitempty"`
Create map[string]MailboxChange `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
Destroy []string `json:"destroy,omitempty"`
}
type MailboxSetResponse struct {
AccountId string `json:"accountId"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
Created map[string]Mailbox `json:"created,omitempty"`
Updated map[string]Mailbox `json:"updated,omitempty"`
Destroyed []string `json:"destroyed,omitempty"`
NotCreated map[string]SetError `json:"notCreated,omitempty"`
NotUpdated map[string]SetError `json:"notUpdated,omitempty"`
NotDestroyed map[string]SetError `json:"notDestroyed,omitempty"`
}
type MailboxChangesCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// The current state of the client.
//
// This is the string that was returned as the state argument in the Mailbox/get response.
//
// The server will return the changes that have occurred since this state.
SinceState string `json:"sinceState,omitempty"`
// The maximum number of ids to return in the response.
//
// The server MAY choose to return fewer than this value but MUST NOT return more.
//
// If not given by the client, the server may choose how many to return.
//
// If supplied by the client, the value MUST be a positive integer greater than 0.
//
// If a value outside of this range is given, the server MUST reject the call with an invalidArguments error.
MaxChanges uint `json:"maxChanges,omitzero"`
}
type MailboxFilterElement interface {
_isAMailboxFilterElement() // marker method
}
type MailboxFilterCondition struct {
ParentId string `json:"parentId,omitempty"`
Name string `json:"name,omitempty"`
Role string `json:"role,omitempty"`
HasAnyRole *bool `json:"hasAnyRole,omitempty"`
IsSubscribed *bool `json:"isSubscribed,omitempty"`
}
func (c MailboxFilterCondition) _isAMailboxFilterElement() {}
var _ MailboxFilterElement = &MailboxFilterCondition{}
type MailboxFilterOperator struct {
Operator FilterOperatorTerm `json:"operator"`
Conditions []MailboxFilterElement `json:"conditions,omitempty"`
}
func (c MailboxFilterOperator) _isAMailboxFilterElement() {}
var _ MailboxFilterElement = &MailboxFilterOperator{}
type MailboxComparator struct {
Property string `json:"property"`
IsAscending bool `json:"isAscending,omitempty"`
Limit int `json:"limit,omitzero"`
CalculateTotal bool `json:"calculateTotal,omitempty"`
}
type MailboxQueryCommand struct {
AccountId string `json:"accountId"`
Filter MailboxFilterElement `json:"filter,omitempty"`
Sort []MailboxComparator `json:"sort,omitempty"`
SortAsTree bool `json:"sortAsTree,omitempty"`
FilterAsTree bool `json:"filterAsTree,omitempty"`
}
type EmailFilterElement interface {
_isAnEmailFilterElement() // marker method
IsNotEmpty() bool
}
type EmailFilterCondition struct {
// A Mailbox id.
//
// An Email must be in this Mailbox to match the condition.
InMailbox string `json:"inMailbox,omitempty"`
// A list of Mailbox ids.
//
// An Email must be in at least one Mailbox not in this list to match the condition.
//
// This is to allow messages solely in trash/spam to be easily excluded from a search.
InMailboxOtherThan []string `json:"inMailboxOtherThan,omitempty"`
// The receivedAt date-time of the Email must be before this date-time to match
// the condition.
Before time.Time `json:"before,omitzero"` // omitzero requires Go 1.24
// The receivedAt date-time of the Email must be the same or after this date-time
// to match the condition.
After time.Time `json:"after,omitzero"`
// The size property of the Email must be equal to or greater than this number to match
// the condition.
MinSize int `json:"minSize,omitempty"`
// The size property of the Email must be less than this number to match the condition.
MaxSize int `json:"maxSize,omitempty"`
// All Emails (including this one) in the same Thread as this Email must have the given
// keyword to match the condition.
AllInThreadHaveKeyword string `json:"allInThreadHaveKeyword,omitempty"`
// At least one Email (possibly this one) in the same Thread as this Email must have the
// given keyword to match the condition.
SomeInThreadHaveKeyword string `json:"someInThreadHaveKeyword,omitempty"`
// All Emails (including this one) in the same Thread as this Email must not have the
// given keyword to match the condition.
NoneInThreadHaveKeyword string `json:"noneInThreadHaveKeyword,omitempty"`
// This Email must have the given keyword to match the condition.
HasKeyword string `json:"hasKeyword,omitempty"`
// This Email must not have the given keyword to match the condition.
NotKeyword string `json:"notKeyword,omitempty"`
// The hasAttachment property of the Email must be identical to the value given to match
// the condition.
HasAttachment bool `json:"hasAttachment,omitempty"`
// Looks for the text in Emails.
//
// The server MUST look up text in the From, To, Cc, Bcc, and Subject header fields of the
// message and SHOULD look inside any text/* or other body parts that may be converted to
// text by the server.
//
// The server MAY extend the search to any additional textual property.
Text string `json:"text,omitempty"`
// Looks for the text in the From header field of the message.
From string `json:"from,omitempty"`
// Looks for the text in the To header field of the message.
To string `json:"to,omitempty"`
// Looks for the text in the Cc header field of the message.
Cc string `json:"cc,omitempty"`
// Looks for the text in the Bcc header field of the message.
Bcc string `json:"bcc,omitempty"`
// Looks for the text in the Subject header field of the message.
Subject string `json:"subject,omitempty"`
// Looks for the text in one of the body parts of the message.
//
// The server MAY exclude MIME body parts with content media types other than text/*
// and message/* from consideration in search matching.
//
// Care should be taken to match based on the text content actually presented to an end user
// by viewers for that media type or otherwise identified as appropriate for search indexing.
//
// Matching document metadata uninteresting to an end user (e.g., markup tag and attribute
// names) is undesirable.
Body string `json:"body,omitempty"`
// The array MUST contain either one or two elements.
//
// The first element is the name of the header field to match against.
//
// The second (optional) element is the text to look for in the header field value.
//
// If not supplied, the message matches simply if it has a header field of the given name.
Header []string `json:"header,omitempty"`
}
func (f EmailFilterCondition) _isAnEmailFilterElement() {
}
func (f EmailFilterCondition) IsNotEmpty() bool {
if !f.After.IsZero() {
return true
}
if f.AllInThreadHaveKeyword != "" {
return true
}
if len(f.Bcc) > 0 {
return true
}
if !f.Before.IsZero() {
return true
}
if f.Body != "" {
return true
}
if f.Cc != "" {
return true
}
if f.From != "" {
return true
}
if f.HasAttachment {
return true
}
if f.HasKeyword != "" {
return true
}
if len(f.Header) > 0 {
return true
}
if f.InMailbox != "" {
return true
}
if len(f.InMailboxOtherThan) > 0 {
return true
}
if f.MaxSize != 0 {
return true
}
if f.MinSize != 0 {
return true
}
if f.NoneInThreadHaveKeyword != "" {
return true
}
if f.NotKeyword != "" {
return true
}
if f.SomeInThreadHaveKeyword != "" {
return true
}
if f.Subject != "" {
return true
}
if f.Text != "" {
return true
}
if f.To != "" {
return true
}
return false
}
var _ EmailFilterElement = &EmailFilterCondition{}
type EmailFilterOperator struct {
Operator FilterOperatorTerm `json:"operator"`
Conditions []EmailFilterElement `json:"conditions,omitempty"`
}
func (o EmailFilterOperator) _isAnEmailFilterElement() {
}
func (o EmailFilterOperator) IsNotEmpty() bool {
return len(o.Conditions) > 0
}
var _ EmailFilterElement = &EmailFilterOperator{}
type EmailComparator struct {
// The name of the property on the objects to compare.
Property string `json:"property,omitempty"`
// If true, sort in ascending order.
//
// Optional; default value: true.
//
// If false, reverse the comparator’s results to sort in descending order.
IsAscending bool `json:"isAscending,omitempty"`
// The identifier, as registered in the collation registry defined in [RFC4790],
// for the algorithm to use when comparing the order of strings.
//
// Optional; default is server dependent.
//
// The algorithms the server supports are advertised in the capabilities object returned
// with the Session object.
//
// [RFC4790]: https://www.rfc-editor.org/rfc/rfc4790.html
Collation string `json:"collation,omitempty"`
// Email-specific: keyword that must be included in the Email object.
Keyword string `json:"keyword,omitempty"`
}
// If an anchor argument is given, the anchor is looked for in the results after filtering
// and sorting.
//
// If found, the anchorOffset is then added to its index. If the resulting index is now negative,
// it is clamped to 0. This index is now used exactly as though it were supplied as the position
// argument. If the anchor is not found, the call is rejected with an anchorNotFound error.
//
// If an anchor is specified, any position argument supplied by the client MUST be ignored.
// If no anchor is supplied, any anchorOffset argument MUST be ignored.
//
// A client can use anchor instead of position to find the index of an id within a large set of results.
type EmailQueryCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// Determines the set of Emails returned in the results.
//
// If null, all objects in the account of this type are included in the results.
Filter EmailFilterElement `json:"filter,omitempty"`
// Lists the names of properties to compare between two Email records, and how to compare
// them, to determine which comes first in the sort.
//
// If two Email records have an identical value for the first comparator, the next comparator
// will be considered, and so on. If all comparators are the same (this includes the case
// where an empty array or null is given as the sort argument), the sort order is server
// dependent, but it MUST be stable between calls to Email/query.
Sort []EmailComparator `json:"sort,omitempty"`
// If true, Emails in the same Thread as a previous Email in the list (given the
// filter and sort order) will be removed from the list.
//
// This means only one Email at most will be included in the list for any given Thread.
CollapseThreads bool `json:"collapseThreads,omitempty"`
// The zero-based index of the first id in the full list of results to return.
//
// If a negative value is given, it is an offset from the end of the list.
// Specifically, the negative value MUST be added to the total number of results given
// the filter, and if still negative, it’s clamped to 0. This is now the zero-based
// index of the first id to return.
//
// If the index is greater than or equal to the total number of objects in the results
// list, then the ids array in the response will be empty, but this is not an error.
Position int `json:"position,omitempty"`
// An Email id.
//
// If supplied, the position argument is ignored.
// The index of this id in the results will be used in combination with the anchorOffset
// argument to determine the index of the first result to return.
Anchor string `json:"anchor,omitempty"`
// The index of the first result to return relative to the index of the anchor,
// if an anchor is given.
//
// Default: 0.
//
// This MAY be negative.
//
// For example, -1 means the Email immediately preceding the anchor is the first result in
// the list returned.
AnchorOffset int `json:"anchorOffset,omitzero"`
// The maximum number of results to return.
//
// If null, no limit presumed.
// The server MAY choose to enforce a maximum limit argument.
// In this case, if a greater value is given (or if it is null), the limit is clamped
// to the maximum; the new limit is returned with the response so the client is aware.
//
// If a negative value is given, the call MUST be rejected with an invalidArguments error.
Limit *uint `json:"limit,omitempty"`
// Does the client wish to know the total number of results in the query?
//
// This may be slow and expensive for servers to calculate, particularly with complex filters,
// so clients should take care to only request the total when needed.
CalculateTotal bool `json:"calculateTotal,omitempty"`
}
type EmailGetCommand struct {
// The ids of the Email objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that
// data type and the number of records does not exceed the maxObjectsInGet limit.
Ids []string `json:"ids,omitempty"`
// The id of the account to use.
AccountId string `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each Email object.
//
// If null, the following properties are returned:
//
// [ "id", "blobId", "threadId", "mailboxIds", "keywords", "size",
// "receivedAt", "messageId", "inReplyTo", "references", "sender", "from",
// "to", "cc", "bcc", "replyTo", "subject", "sentAt", "hasAttachment",
// "preview", "bodyValues", "textBody", "htmlBody", "attachments" ]
//
// The id property of the object is always returned, even if not explicitly requested.
//
// If an invalid property is requested, the call MUST be rejected with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
// A list of properties to fetch for each EmailBodyPart returned.
//
// If omitted, this defaults to:
//
// [ "partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "language", "location" ]
//
BodyProperties []string `json:"bodyProperties,omitempty"`
// (default: false) If true, the bodyValues property includes any text/* part in the textBody property.
FetchTextBodyValues bool `json:"fetchTextBodyValues,omitzero"`
// (default: false) If true, the bodyValues property includes any text/* part in the htmlBody property.
FetchHTMLBodyValues bool `json:"fetchHTMLBodyValues,omitzero"`
// (default: false) If true, the bodyValues property includes any text/* part in the bodyStructure property.
FetchAllBodyValues bool `json:"fetchAllBodyValues,omitzero"`
// If greater than zero, the value property of any EmailBodyValue object returned in bodyValues
// MUST be truncated if necessary so it does not exceed this number of octets in size.
//
// If 0 (the default), no truncation occurs.
//
// The server MUST ensure the truncation results in valid UTF-8 and does not occur mid-codepoint.
//
// If the part is of type text/html, the server SHOULD NOT truncate inside an HTML tag, e.g., in
// the middle of .
//
// There is no requirement for the truncated form to be a balanced tree or valid HTML (indeed, the original
// source may well be neither of these things).
MaxBodyValueBytes uint `json:"maxBodyValueBytes,omitempty"`
}
// Reference to Previous Method Results
//
// To allow clients to make more efficient use of the network and avoid round trips, an argument to one method
// can be taken from the result of a previous method call in the same request.
//
// To do this, the client prefixes the argument name with # (an [octothorpe]).
//
// When processing a method call, the server MUST first check the arguments object for any names beginning with #.
//
// If found, the result reference should be resolved and the value used as the “real” argument.
//
// The method is then processed as normal.
//
// If any result reference fails to resolve, the whole method MUST be rejected with an invalidResultReference error.
//
// If an arguments object contains the same argument name in normal and referenced form (e.g., foo and #foo),
// the method MUST return an invalidArguments error.
//
// To resolve:
//
// 1. Find the first response with a method call id identical to the resultOf property of the ResultReference
// in the methodResponses array from previously processed method calls in the same request.
// If none, evaluation fails.
// 2. If the response name is not identical to the name property of the ResultReference, evaluation fails.
// 3. Apply the path to the arguments object of the response (the second item in the response array)
// following the JSON Pointer algorithm [RFC6901], except with the following addition in “Evaluation” (see Section 4):
// 4. If the currently referenced value is a JSON array, the reference token may be exactly the single character *,
// making the new referenced value the result of applying the rest of the JSON Pointer tokens to every item in the
// array and returning the results in the same order in a new array.
// 5. If the result of applying the rest of the pointer tokens to each item was itself an array, the contents of this
// array are added to the output rather than the array itself (i.e., the result is flattened from an array of
// arrays to a single array).
//
// [octothorpe]; https://en.wiktionary.org/wiki/octothorpe
// [RFC6901]: https://datatracker.ietf.org/doc/html/rfc6901
type ResultReference struct {
// The method call id of a previous method call in the current request.
ResultOf string `json:"resultOf"`
// The required name of a response to that method call.
Name Command `json:"name"`
// A pointer into the arguments of the response selected via the name and resultOf properties.
//
// This is a JSON Pointer [RFC6901], except it also allows the use of * to map through an array.
//
// [RFC6901]: https://datatracker.ietf.org/doc/html/rfc6901
Path string `json:"path,omitempty"`
}
type EmailGetRefCommand struct {
// The ids of the Email objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that
// data type and the number of records does not exceed the maxObjectsInGet limit.
IdsRef *ResultReference `json:"#ids,omitempty"`
// The id of the account to use.
AccountId string `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each Email object.
//
// If null, the following properties are returned:
//
// [ "id", "blobId", "threadId", "mailboxIds", "keywords", "size",
// "receivedAt", "messageId", "inReplyTo", "references", "sender", "from",
// "to", "cc", "bcc", "replyTo", "subject", "sentAt", "hasAttachment",
// "preview", "bodyValues", "textBody", "htmlBody", "attachments" ]
//
// The id property of the object is always returned, even if not explicitly requested.
//
// If an invalid property is requested, the call MUST be rejected with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
// A list of properties to fetch for each EmailBodyPart returned.
//
// If omitted, this defaults to:
//
// [ "partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "language", "location" ]
//
BodyProperties []string `json:"bodyProperties,omitempty"`
// (default: false) If true, the bodyValues property includes any text/* part in the textBody property.
FetchTextBodyValues bool `json:"fetchTextBodyValues,omitzero"`
// (default: false) If true, the bodyValues property includes any text/* part in the htmlBody property.
FetchHTMLBodyValues bool `json:"fetchHTMLBodyValues,omitzero"`
// (default: false) If true, the bodyValues property includes any text/* part in the bodyStructure property.
FetchAllBodyValues bool `json:"fetchAllBodyValues,omitzero"`
// If greater than zero, the value property of any EmailBodyValue object returned in bodyValues
// MUST be truncated if necessary so it does not exceed this number of octets in size.
//
// If 0 (the default), no truncation occurs.
//
// The server MUST ensure the truncation results in valid UTF-8 and does not occur mid-codepoint.
//
// If the part is of type text/html, the server SHOULD NOT truncate inside an HTML tag, e.g., in
// the middle of .
//
// There is no requirement for the truncated form to be a balanced tree or valid HTML (indeed, the original
// source may well be neither of these things).
MaxBodyValueBytes uint `json:"maxBodyValueBytes,omitempty"`
}
type EmailChangesCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// The current state of the client.
//
// This is the string that was returned as the state argument in the Email/get response.
// The server will return the changes that have occurred since this state.
SinceState State `json:"sinceState,omitzero,omitempty"`
// The maximum number of ids to return in the response.
//
// The server MAY choose to return fewer than this value but MUST NOT return more.
// If not given by the client, the server may choose how many to return.
// If supplied by the client, the value MUST be a positive integer greater than 0.
MaxChanges uint `json:"maxChanges,omitzero"`
}
type EmailAddress struct {
// The display-name of the mailbox [RFC5322].
//
// If this is a quoted-string:
// 1. The surrounding DQUOTE characters are removed.
// 2. Any quoted-pair is decoded.
// 3. White space is unfolded, and then any leading and trailing white space is removed.
// If there is no display-name but there is a comment immediately following the addr-spec, the value of this
// SHOULD be used instead. Otherwise, this property is null.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
//
// example: $emailAddressName
Name string `json:"name,omitempty"`
// The addr-spec of the mailbox [RFC5322].
//
// Any syntactically correct encoded sections [RFC2047] with a known encoding MUST be decoded,
// following the same rules as for the Text form.
//
// Parsing SHOULD be best effort in the face of invalid structure to accommodate invalid messages and
// semi-complete drafts. EmailAddress objects MAY have an email property that does not conform to the
// addr-spec form (for example, may not contain an @ symbol).
//
// [RFC2047]: https://www.rfc-editor.org/rfc/rfc2047.html
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
//
// example: $emailAddressEmail
Email string `json:"email,omitempty"`
}
type EmailAddressGroup struct {
// The display-name of the group [RFC5322], or null if the addresses are not part of a group.
//
// If this is a quoted-string, it is processed the same as the name in the EmailAddress type.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
Name string `json:"name,omitempty"`
// The mailbox values that belong to this group, represented as EmailAddress objects.
Addresses []EmailAddress `json:"addresses,omitempty"`
}
type EmailHeader struct {
// The header field name as defined in [RFC5322], with the same capitalization that it has in the message.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
Name string `json:"name"`
// The header field value as defined in [RFC5322], in Raw form.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
Value string `json:"value"`
}
// Email body part.
//
// The client may specify a `partId` OR a `blobId`, but not both.
// If a `partId` is given, this `partId` MUST be present in the `bodyValues` property.
//
// The `charset` property MUST be omitted if a `partId` is given (the part’s content is included
// in `bodyValues`, and the server may choose any appropriate encoding).
//
// The `size` property MUST be omitted if a `partId` is given. If a `blobId` is given, it may be
// included but is ignored by the server (the size is actually calculated from the blob content
// itself).
//
// A `Content-Transfer-Encoding` header field MUST NOT be given.
type EmailBodyPart struct {
// Identifies this part uniquely within the Email.
//
// This is scoped to the `emailId` and has no meaning outside of the JMAP Email object representation.
// This is null if, and only if, the part is of type `multipart/*`.
//
// example: $attachmentPartId
PartId string `json:"partId,omitempty"`
// The id representing the raw octets of the contents of the part, after decoding any known
// `Content-Transfer-Encoding` (as defined in [RFC2045]), or null if, and only if, the part is of type `multipart/*`.
//
// Note that two parts may be transfer-encoded differently but have the same blob id if their decoded octets are identical
// and the server is using a secure hash of the data for the blob id.
// If the transfer encoding is unknown, it is treated as though it had no transfer encoding.
//
// [RFC2045]: https://www.rfc-editor.org/rfc/rfc2045.html
//
// example: $blobId
BlobId string `json:"blobId,omitempty"`
// The size, in octets, of the raw data after content transfer decoding (as referenced by the `blobId`, i.e.,
// the number of octets in the file the user would download).
//
// example: 31219
Size int `json:"size,omitempty"`
// This is a list of all header fields in the part, in the order they appear in the message.
//
// The values are in Raw form.
Headers []EmailHeader `json:"headers,omitempty"`
// This is the decoded filename parameter of the `Content-Disposition` header field per [RFC2231], or
// (for compatibility with existing systems) if not present, then it’s the decoded name parameter of
// the `Content-Type` header field per [RFC2047].
//
// [RFC2231]: https://www.rfc-editor.org/rfc/rfc2231.html
// [RFC2047]: https://www.rfc-editor.org/rfc/rfc2047.html
//
// name: $attachmentName
Name string `json:"name,omitempty"`
// The value of the `Content-Type` header field of the part, if present; otherwise, the implicit type as per
// the MIME standard (`text/plain` or `message/rfc822` if inside a `multipart/digest`).
//
// [CFWS] is removed and any parameters are stripped.
//
// [CFWS]: https://www.rfc-editor.org/rfc/rfc5322#section-3.2.2
//
// example: $attachmentType
Type string `json:"type,omitempty"`
// The value of the `charset` parameter of the `Content-Type` header field, if present, or null if the header
// field is present but not of type `text/*`.
//
// If there is no `Content-Type` header field, or it exists and is of type `text/*` but has no `charset` parameter,
// this is the implicit charset as per the MIME standard: `us-ascii`.
//
// example: $attachmentCharset
Charset string `json:"charset,omitempty"`
// The value of the `Content-Disposition` header field of the part, if present;
// otherwise, it’s null.
//
// [CFWS] is removed and any parameters are stripped.
//
// [CFWS]: https://www.rfc-editor.org/rfc/rfc5322#section-3.2.2
//
// example: $attachmentDisposition
Disposition string `json:"disposition,omitempty"`
// The value of the `Content-Id` header field of the part, if present; otherwise it’s null.
//
// [CFWS] and surrounding angle brackets (`<>`) are removed.
//
// This may be used to reference the content from within a `text/html` body part HTML using the `cid:` protocol,
// as defined in [RFC2392].
//
// [RFC2392]: https://www.rfc-editor.org/rfc/rfc2392.html
// [CFWS]: https://www.rfc-editor.org/rfc/rfc5322#section-3.2.2
//
// example: $attachmentCid
Cid string `json:"cid,omitempty"`
// The list of language tags, as defined in [RFC3282], in the `Content-Language` header field of the part,
// if present.
//
// [RFC3282]: https://www.rfc-editor.org/rfc/rfc3282.html
Language string `json:"language,omitempty"`
// The URI, as defined in [RFC2557], in the `Content-Location` header field of the part, if present.
//
// [RFC2557]: https://www.rfc-editor.org/rfc/rfc2557.html
Location string `json:"location,omitempty"`
// If the type is `multipart/*`, this contains the body parts of each child.
SubParts []EmailBodyPart `json:"subParts,omitempty"`
}
type EmailBodyValue struct {
// The value of the body part after decoding `Content-Transfer-Encoding` and the `Content-Type` charset,
// if both known to the server, and with any CRLF replaced with a single LF.
//
// The server MAY use heuristics to determine the charset to use for decoding if the charset is unknown,
// no charset is given, or it believes the charset given is incorrect.
//
// Decoding is best effort; the server SHOULD insert the unicode replacement character (`U+FFFD`) and continue
// when a malformed section is encountered.
//
// Note that due to the charset decoding and line ending normalisation, the length of this string will
// probably not be exactly the same as the size property on the corresponding EmailBodyPart.
Value string `json:"value,omitempty"`
// This is true if malformed sections were found while decoding the charset,
// or the charset was unknown, or the content-transfer-encoding was unknown.
//
// Default value is false.
IsEncodingProblem bool `json:"isEncodingProblem,omitzero"`
// This is true if the value has been truncated.
//
// Default value is false.
IsTruncated bool `json:"isTruncated,omitzero"`
}
const (
EmailPropertyId = "id"
EmailPropertyBlodId = "blobId"
EmailPropertyThreadId = "threadId"
EmailPropertyMailboxIds = "mailboxIds"
EmailPropertyKeywords = "keywords"
EmailPropertySize = "size"
EmailPropertyReceivedAt = "receivedAt"
EmailPropertyHeaders = "headers"
EmailPropertyMessageId = "messageId"
EmailPropertyInReplyTo = "inReplyTo"
EmailPropertyReferences = "references"
EmailPropertySender = "sender"
EmailPropertyFrom = "from"
EmailPropertyTo = "to"
EmailPropertyCc = "cc"
EmailPropertyBcc = "bcc"
EmailPropertyReplyTo = "replyTo"
EmailPropertySubject = "subject"
EmailPropertySentAt = "sentAt"
EmailPropertyBodyStructure = "bodyStructure"
EmailPropertyBodyValues = "bodyValues"
EmailPropertyTextBody = "textBody"
EmailPropertyHtmlBody = "htmlBody"
EmailPropertyAttachments = "attachments"
EmailPropertyHasAttachment = "hasAttachment"
EmailPropertyPreview = "preview"
)
var EmailProperties = []string{
EmailPropertyId,
EmailPropertyBlodId,
EmailPropertyThreadId,
EmailPropertyMailboxIds,
EmailPropertyKeywords,
EmailPropertySize,
EmailPropertyReceivedAt,
EmailPropertyHeaders,
EmailPropertyMessageId,
EmailPropertyInReplyTo,
EmailPropertyReferences,
EmailPropertySender,
EmailPropertyFrom,
EmailPropertyTo,
EmailPropertyCc,
EmailPropertyBcc,
EmailPropertyReplyTo,
EmailPropertySubject,
EmailPropertySentAt,
EmailPropertyBodyStructure,
EmailPropertyBodyValues,
EmailPropertyTextBody,
EmailPropertyHtmlBody,
EmailPropertyAttachments,
EmailPropertyHasAttachment,
EmailPropertyPreview,
}
// An Email.
//
// swagger:model
type Email struct {
// The id of the Email object.
//
// Note that this is the JMAP object id, NOT the `Message-ID` header field value of the message [RFC5322].
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
//
// required: true
// example: $emailId
Id string `json:"id,omitempty"`
// The id representing the raw octets of the message [RFC5322] for this Email.
//
// This may be used to download the raw original message or to attach it directly to another Email, etc.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
//
// example: $blobId
BlobId string `json:"blobId,omitempty"`
// The id of the Thread to which this Email belongs.
//
// example: $threadId
ThreadId string `json:"threadId,omitempty"`
// The number of emails (this one included) that are in the thread this email is in.
// Note that this is not part of the JMAP specification, and is only calculated when requested.
ThreadSize int `json:"threadSize,omitzero"`
// The account ID this email belongs to.
// Note that this is not part of the JMAP specification, and is only contained in all-account operations.
AccountId string `json:"accountId,omitempty"`
// The set of Mailbox ids this Email belongs to.
//
// An Email in the mail store MUST belong to one or more Mailboxes at all times (until it is destroyed).
// The set is represented as an object, with each key being a Mailbox id.
//
// The value for each key in the object MUST be true.
//
// example: {"a": true}
MailboxIds map[string]bool `json:"mailboxIds,omitempty"`
// A set of keywords that apply to the Email.
//
// The set is represented as an object, with the keys being the keywords.
//
// The value for each key in the object MUST be true.
//
// Keywords are shared with IMAP.
//
// The six system keywords from IMAP get special treatment.
//
// The following four keywords have their first character changed from \ in IMAP to $ in JMAP and have particular semantic meaning:
//
// - $draft: The Email is a draft the user is composing.
// - $seen: The Email has been read.
// - $flagged: The Email has been flagged for urgent/special attention.
// - $answered: The Email has been replied to.
//
// The IMAP \Recent keyword is not exposed via JMAP. The IMAP \Deleted keyword is also not present: IMAP uses a delete+expunge model,
// which JMAP does not. Any message with the \Deleted keyword MUST NOT be visible via JMAP (and so are not counted in the
// “totalEmails”, “unreadEmails”, “totalThreads”, and “unreadThreads” Mailbox properties).
//
// Users may add arbitrary keywords to an Email.
// For compatibility with IMAP, a keyword is a case-insensitive string of 1–255 characters in the ASCII subset
// %x21–%x7e (excludes control chars and space), and it MUST NOT include any of these characters:
//
// ( ) { ] % * " \
//
// Because JSON is case sensitive, servers MUST return keywords in lowercase.
//
// The [IMAP and JMAP Keywords] registry as established in [RFC5788] assigns semantic meaning to some other
// keywords in common use.
//
// New keywords may be established here in the future. In particular, note:
//
// - $forwarded: The Email has been forwarded.
// - $phishing: The Email is highly likely to be phishing.
// Clients SHOULD warn users to take care when viewing this Email and disable links and attachments.
// - $junk: The Email is definitely spam.
// Clients SHOULD set this flag when users report spam to help train automated spam-detection systems.
// - $notjunk: The Email is definitely not spam.
// Clients SHOULD set this flag when users indicate an Email is legitimate, to help train automated spam-detection systems.
//
// [IMAP and JMAP Keywords]: https://www.iana.org/assignments/imap-jmap-keywords/
// [RFC5788]: https://www.rfc-editor.org/rfc/rfc5788.html
Keywords map[string]bool `json:"keywords,omitempty"`
// The size, in octets, of the raw data for the message [RFC5322]
// (as referenced by the blobId, i.e., the number of octets in the file the user would download).
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
Size int `json:"size,omitzero"`
// The date the Email was received by the message store.
//
// This is the internal date in IMAP [RFC3501].
//
// [RFC3501]: https://www.rfc-editor.org/rfc/rfc3501.html
ReceivedAt time.Time `json:"receivedAt,omitzero"`
// This is a list of all header fields [RFC5322], in the same order they appear in the message.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
Headers []EmailHeader `json:"headers,omitempty"`
// The value is identical to the value of header:Message-ID:asMessageIds.
//
// For messages conforming to [RFC5322] this will be an array with a single entry.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
MessageId []string `json:"messageId,omitempty"`
// The value is identical to the value of header:In-Reply-To:asMessageIds.
InReplyTo []string `json:"inReplyTo,omitempty"`
// The value is identical to the value of header:References:asMessageIds.
References []string `json:"references,omitempty"`
// The value is identical to the value of header:Sender:asAddresses.
Sender []EmailAddress `json:"sender,omitempty"`
// The value is identical to the value of header:From:asAddresses.
From []EmailAddress `json:"from,omitempty"`
// The value is identical to the value of header:To:asAddresses.
To []EmailAddress `json:"to,omitempty"`
// The value is identical to the value of header:Cc:asAddresses.
Cc []EmailAddress `json:"cc,omitempty"`
// The value is identical to the value of header:Bcc:asAddresses.
Bcc []EmailAddress `json:"bcc,omitempty"`
// The value is identical to the value of header:Reply-To:asAddresses.
ReplyTo []EmailAddress `json:"replyTo,omitempty"`
// The value is identical to the value of header:Subject:asText.
Subject string `json:"subject,omitempty"`
// The value is identical to the value of header:Date:asDate.
SentAt time.Time `json:"sentAt,omitzero"`
// This is the full MIME structure of the message body, without recursing into message/rfc822 or message/global parts.
//
// Note that EmailBodyParts may have subParts if they are of type multipart/*.
BodyStructure *EmailBodyPart `json:"bodyStructure,omitzero"`
// This is a map of partId to an EmailBodyValue object for none, some, or all text/* parts.
//
// Which parts are included and whether the value is truncated is determined by various arguments to Email/get and Email/parse.
BodyValues map[string]EmailBodyValue `json:"bodyValues,omitempty"`
// A list of text/plain, text/html, image/*, audio/*, and/or video/* parts to display (sequentially) as the
// message body, with a preference for text/plain when alternative versions are available.
TextBody []EmailBodyPart `json:"textBody,omitempty"`
// A list of text/plain, text/html, image/*, audio/*, and/or video/* parts to display (sequentially) as the
// message body, with a preference for text/html when alternative versions are available.
HtmlBody []EmailBodyPart `json:"htmlBody,omitempty"`
// A list, traversing depth-first, of all parts in bodyStructure.
//
// They must satisfy either of the following conditions:
//
// - not of type multipart/* and not included in textBody or htmlBody
// - of type image/*, audio/*, or video/* and not in both textBody and htmlBody
//
// None of these parts include subParts, including message/* types.
//
// Attached messages may be fetched using the Email/parse method and the blobId.
//
// Note that a text/html body part HTML may reference image parts in attachments by using cid:
// links to reference the Content-Id, as defined in [RFC2392], or by referencing the Content-Location.
//
// [RFC2392]: https://www.rfc-editor.org/rfc/rfc2392.html
Attachments []EmailBodyPart `json:"attachments,omitempty"`
// This is true if there are one or more parts in the message that a client UI should offer as downloadable.
//
// A server SHOULD set hasAttachment to true if the attachments list contains at least one item that
// does not have Content-Disposition: inline.
//
// The server MAY ignore parts in this list that are processed automatically in some way or are referenced
// as embedded images in one of the text/html parts of the message.
//
// The server MAY set hasAttachment based on implementation-defined or site-configurable heuristics.
HasAttachment bool `json:"hasAttachment,omitempty"`
// A plaintext fragment of the message body.
//
// This is intended to be shown as a preview line when listing messages in the mail store and may be truncated
// when shown.
//
// The server may choose which part of the message to include in the preview; skipping quoted sections and
// salutations and collapsing white space can result in a more useful preview.
//
// This MUST NOT be more than 256 characters in length.
//
// As this is derived from the message content by the server, and the algorithm for doing so could change over
// time, fetching this for an Email a second time MAY return a different result.
// However, the previous value is not considered incorrect, and the change SHOULD NOT cause the Email object
// to be considered as changed by the server.
Preview string `json:"preview,omitempty"`
}
type AddressParameters struct {
HoldUntil time.Time `json:"HOLDUNTIL,omitzero"`
HoldForSeconds uint `json:"HOLDFOR,omitzero"`
}
type Address struct {
// The email address being represented by the object.
//
// This is a “Mailbox” as used in the Reverse-path or Forward-path of the MAIL FROM or RCPT TO command in [RFC5321].
//
// [RFC5321]: https://datatracker.ietf.org/doc/html/rfc5321
Email string `json:"email,omitempty"`
// Any parameters to send with the email address (either mail-parameter or rcpt-parameter as appropriate,
// as specified in [RFC5321]).
//
// If supplied, each key in the object is a parameter name, and the value is either the parameter value (type String)
// or null if the parameter does not take a value.
//
// [RFC5321]: https://datatracker.ietf.org/doc/html/rfc5321
Parameters *AddressParameters `json:"parameters,omitempty"`
}
// Information for use when sending via SMTP.
type Envelope struct {
// The email address to use as the return address in the SMTP submission,
// plus any parameters to pass with the MAIL FROM address.
MailFrom Address `json:"mailFrom"`
// The email addresses to send the message to, and any RCPT TO parameters to pass with the recipient.
RcptTo []Address `json:"rcptTo"`
}
type EmailSubmissionUndoStatus string
const (
// It may be possible to cancel this submission.
UndoStatusPending EmailSubmissionUndoStatus = "pending"
// The message has been relayed to at least one recipient in a manner that cannot be recalled.
// It is no longer possible to cancel this submission.
UndoStatusFinal EmailSubmissionUndoStatus = "final"
// The submission was canceled and will not be delivered to any recipient.
UndoStatusCanceled EmailSubmissionUndoStatus = "canceled"
)
type DeliveryStatusDelivered string
const (
// The message is in a local mail queue and status will change once it exits the local mail
// queues.
// The smtpReply property may still change.
DeliveredQueued DeliveryStatusDelivered = "queued"
// The message was successfully delivered to the mail store of the recipient.
// The smtpReply property is final.
DeliveredYes DeliveryStatusDelivered = "yes"
// Delivery to the recipient permanently failed.
// The smtpReply property is final.
DeliveredNo DeliveryStatusDelivered = "no"
// The final delivery status is unknown, (e.g., it was relayed to an external machine
// and no further information is available).
//
// The smtpReply property may still change if a DSN arrives.
DeliveredUnknown DeliveryStatusDelivered = "unknown"
)
type DeliveryStatusDisplayed string
const (
// The display status is unknown.
//
// This is the initial value.
DisplayedUnknown DeliveryStatusDisplayed = "unknown"
// The recipient’s system claims the message content has been displayed to the recipient.
//
// Note that there is no guarantee that the recipient has noticed, read, or understood the content.
DisplayedYes DeliveryStatusDisplayed = "yes"
)
type DeliveryStatus struct {
// The SMTP reply string returned for this recipient when the server last tried to
// relay the message, or in a later Delivery Status Notification (DSN, as defined in
// [RFC3464]) response for the message.
//
// This SHOULD be the response to the RCPT TO stage, unless this was accepted and the
// message as a whole was rejected at the end of the DATA stage, in which case the
// DATA stage reply SHOULD be used instead.
//
// [RFC3464]: https://datatracker.ietf.org/doc/html/rfc3464
SmtpReply string `json:"smtpReply"`
// Represents whether the message has been successfully delivered to the recipient.
//
// This MUST be one of the following values:
// - queued: The message is in a local mail queue and status will change once it exits
// the local mail queues. The smtpReply property may still change.
// - yes: The message was successfully delivered to the mail store of the recipient.
// The smtpReply property is final.
// - no: Delivery to the recipient permanently failed. The smtpReply property is final.
// - unknown: The final delivery status is unknown, (e.g., it was relayed to an external
// machine and no further information is available).
// The smtpReply property may still change if a DSN arrives.
Delivered DeliveryStatusDelivered `json:"delivered"`
// Represents whether the message has been displayed to the recipient.
//
// This MUST be one of the following values:
// - unknown: The display status is unknown. This is the initial value.
// - yes: The recipient’s system claims the message content has been displayed to the recipient.
// Note that there is no guarantee that the recipient has noticed, read, or understood the content.
Displayed DeliveryStatusDisplayed `json:"displayed"`
}
type EmailSubmission struct {
// The id of the EmailSubmission (server-set).
Id string `json:"id"`
// The id of the Identity to associate with this submission.
IdentityId string `json:"identityId"`
// The id of the Email to send.
//
// The Email being sent does not have to be a draft, for example, when “redirecting” an existing Email
// to a different address.
EmailId string `json:"emailId"`
// The Thread id of the Email to send (server-set).
//
// This is set by the server to the threadId property of the Email referenced by the emailId.
ThreadId string `json:"threadId"`
// Information for use when sending via SMTP.
//
// If the envelope property is null or omitted on creation, the server MUST generate this from the
// referenced Email as follows:
//
// - mailFrom: The email address in the Sender header field, if present; otherwise,
// it’s the email address in the From header field, if present.
// In either case, no parameters are added.
// - rcptTo: The deduplicated set of email addresses from the To, Cc, and Bcc header fields,
// if present, with no parameters for any of them.
Envelope *Envelope `json:"envelope,omitempty"`
// The date the submission was/will be released for delivery (server-set).
SendAt time.Time `json:"sendAt,omitzero"`
// This represents whether the submission may be canceled (server-set).
//
// This is server set on create and MUST be one of the following values:
//
// - pending: It may be possible to cancel this submission.
// - final: The message has been relayed to at least one recipient in a manner that cannot be
// recalled. It is no longer possible to cancel this submission.
// - canceled: The submission was canceled and will not be delivered to any recipient.
UndoStatus EmailSubmissionUndoStatus `json:"undoStatus"`
// This represents the delivery status for each of the submission’s recipients, if known (server-set).
//
// This property MAY not be supported by all servers, in which case it will remain null.
//
// Servers that support it SHOULD update the EmailSubmission object each time the status of any of
// the recipients changes, even if some recipients are still being retried.
//
// This value is a map from the email address of each recipient to a DeliveryStatus object.
DeliveryStatus map[string]DeliveryStatus `json:"deliveryStatus"`
// A list of blob ids for DSNs [RFC3464] received for this submission,
// in order of receipt, oldest first (server-set) .
//
// The blob is the whole MIME message (with a top-level content-type of multipart/report), as received.
//
// [RFC3464]: https://datatracker.ietf.org/doc/html/rfc3464
DsnBlobIds []string `json:"dsnBlobIds,omitempty"`
// A list of blob ids for MDNs [RFC8098] received for this submission,
// in order of receipt, oldest first (server-set).
//
// The blob is the whole MIME message (with a top-level content-type of multipart/report), as received.
//
// [RFC8098]: https://datatracker.ietf.org/doc/html/rfc8098
MdnBlobIds []string `json:"mdnBlobIds,omitempty"`
}
type EmailSubmissionGetCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// The ids of the EmailSubmission objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that data
// type and the number of records does not exceed the maxObjectsInGet limit.
Ids []string `json:"ids,omitempty"`
// If supplied, only the properties listed in the array are returned for each EmailSubmission object.
//
// If null, all properties of the object are returned. The id property of the object is always returned,
// even if not explicitly requested. If an invalid property is requested, the call MUST be rejected
// with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
}
type EmailSubmissionGetRefCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// The ids of the EmailSubmission objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that data
// type and the number of records does not exceed the maxObjectsInGet limit.
IdRef *ResultReference `json:"#ids,omitempty"`
// If supplied, only the properties listed in the array are returned for each EmailSubmission object.
//
// If null, all properties of the object are returned. The id property of the object is always returned,
// even if not explicitly requested. If an invalid property is requested, the call MUST be rejected
// with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
}
type EmailSubmissionGetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data
// of this type in the account (not just the objects returned in this call).
//
// If the data changes, this string MUST change. If the EmailSubmission data is unchanged,
// servers SHOULD return the same state string on subsequent requests for this data type.
//
// When a client receives a response with a different state string to a previous call,
// it MUST either throw away all currently cached objects for the type or call
// EmailSubmission/changes to get the exact changes.
State State `json:"state"`
// An array of the EmailSubmission objects requested.
//
// This is the empty array if no objects were found or if the ids argument passed in
// was also an empty array.
//
// The results MAY be in a different order to the ids in the request arguments.
// If an identical id is included more than once in the request, the server MUST only
// include it once in either the list or the notFound argument of the response.
List []EmailSubmission `json:"list,omitempty"`
// This array contains the ids passed to the method for records that do not exist.
//
// The array is empty if all requested ids were found or if the ids argument passed in was
// either null or an empty array.
NotFound []string `json:"notFound,omitempty"`
}
// Patch Object.
//
// Example:
//
// - moves it from the drafts folder (which has Mailbox id “7cb4e8ee-df87-4757-b9c4-2ea1ca41b38e”)
// to the sent folder (which we presume has Mailbox id “73dbcb4b-bffc-48bd-8c2a-a2e91ca672f6”)
//
// - removes the $draft flag and
//
// {
// "mailboxIds/7cb4e8ee-df87-4757-b9c4-2ea1ca41b38e": null,
// "mailboxIds/73dbcb4b-bffc-48bd-8c2a-a2e91ca672f6": true,
// "keywords/$draft": null
// }
type PatchObject map[string]any
// same as EmailSubmission but without the server-set attributes
type EmailSubmissionCreate struct {
// The id of the Identity to associate with this submission.
IdentityId string `json:"identityId"`
// The id of the Email to send.
//
// The Email being sent does not have to be a draft, for example, when “redirecting” an existing
// Email to a different address.
EmailId string `json:"emailId"`
// Information for use when sending via SMTP.
Envelope *Envelope `json:"envelope,omitempty"`
}
type EmailSubmissionSetCommand struct {
AccountId string `json:"accountId"`
Create map[string]EmailSubmissionCreate `json:"create,omitempty"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
// A map of EmailSubmission id to an object containing properties to update on the Email object
// referenced by the EmailSubmission if the create/update/destroy succeeds.
//
// (For references to EmailSubmissions created in the same “/set” invocation, this is equivalent
// to a creation-reference, so the id will be the creation id prefixed with a #.)
OnSuccessUpdateEmail map[string]PatchObject `json:"onSuccessUpdateEmail,omitempty"`
// A list of EmailSubmission ids for which the Email with the corresponding emailId should be destroyed
// if the create/update/destroy succeeds.
//
// (For references to EmailSubmission creations, this is equivalent to a creation-reference so the
// id will be the creation id prefixed with a #.)
OnSuccessDestroyEmail []string `json:"onSuccessDestroyEmail,omitempty"`
}
type CreatedEmailSubmission struct {
Id string `json:"id"`
}
type EmailSubmissionSetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
// This is the state the client will be in after applying the set of changes to the old state.
NewState State `json:"newState"`
// If true, the client may call EmailSubmission/changes again with the newState returned to get further
// updates.
//
// If false, newState is the current server state.
HasMoreChanges bool `json:"hasMoreChanges"`
// An array of ids for records that have been created since the old state.
Created map[string]CreatedEmailSubmission `json:"created,omitempty"`
// A map of the creation id to a SetError object for each record that failed to be created, or
// null if all successful.
NotCreated map[string]SetError `json:"notCreated,omitempty"`
// TODO(pbleser-oc) add updated and destroyed when they are needed
}
type Command string
type Invocation struct {
Command Command
Parameters any
Tag string
}
func invocation(command Command, parameters any, tag string) Invocation {
return Invocation{
Command: command,
Parameters: parameters,
Tag: tag,
}
}
type TypeOfRequest string
const RequestType = TypeOfRequest("Request")
type Request struct {
// The set of capabilities the client wishes to use.
//
// The client MAY include capability identifiers even if the method calls it makes do not utilise those capabilities.
// The server advertises the set of specifications it supports in the Session object (see [Section 2]), as keys on
// the capabilities property.
//
// [Section 2]: https://jmap.io/spec-core.html#the-jmap-session-resource
Using []string `json:"using"`
// An array of method calls to process on the server.
//
// The method calls MUST be processed sequentially, in order.
MethodCalls []Invocation `json:"methodCalls"`
// A map of a (client-specified) creation id to the id the server assigned when a record was successfully created (optional).
CreatedIds map[string]string `json:"createdIds,omitempty"`
// This MUST be the string "Request".
// The specification extends the Response object with two additional arguments when used over a WebSocket.
Type TypeOfRequest `json:"@type,omitempty"`
// A client-specified identifier for the request to be echoed back in the response to this request (optional).
Id string `json:"id,omitempty"`
}
type TypeOfResponse string
const ResponseType = TypeOfResponse("Response")
type Response struct {
// An array of responses, in the same format as the methodCalls on the Request object.
// The output of the methods MUST be added to the methodResponses array in the same order that the methods are processed.
MethodResponses []Invocation `json:"methodResponses"`
// A map of a (client-specified) creation id to the id the server assigned when a record was successfully created.
//
// Optional; only returned if given in the request.
//
// This MUST include all creation ids passed in the original createdIds parameter of the Request object, as well as any
// additional ones added for newly created records.
CreatedIds map[string]string `json:"createdIds,omitempty"`
// The current value of the “state” string on the Session object, as described in [Section 2].
// Clients may use this to detect if this object has changed and needs to be refetched.
//
// [Section 2]: https://jmap.io/spec-core.html#the-jmap-session-resource
SessionState SessionState `json:"sessionState"`
// This MUST be the string "Response".
// The specification extends the Response object with two additional arguments when used over a WebSocket.
Type TypeOfResponse `json:"@type,omitempty"`
// MUST be returned if an identifier is included in the request (optional).
RequestId string `json:"requestId,omitempty"`
}
type EmailQueryResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A string encoding the current state of the query on the server.
//
// This string MUST change if the results of the query (i.e., the matching ids and their sort order) have changed.
// The queryState string MAY change if something has changed on the server, which means the results may have changed
// but the server doesn’t know for sure.
//
// The queryState string only represents the ordered list of ids that match the particular query (including its sort/filter).
// There is no requirement for it to change if a property on an object matching the query changes but the query results are unaffected
// (indeed, it is more efficient if the queryState string does not change in this case).
//
// The queryState string only has meaning when compared to future responses to a query with the same type/sort/filter or when used with
// /queryChanges to fetch changes.
//
// Should a client receive back a response with a different queryState string to a previous call, it MUST either throw away the currently
// cached query and fetch it again (note, this does not require fetching the records again, just the list of ids) or call
// Email/queryChanges to get the difference.
QueryState State `json:"queryState"`
// This is true if the server supports calling Email/queryChanges with these filter/sort parameters.
//
// Note, this does not guarantee that the Email/queryChanges call will succeed, as it may only be possible for a limited time
// afterwards due to server internal implementation details.
CanCalculateChanges bool `json:"canCalculateChanges"`
// The zero-based index of the first result in the ids array within the complete list of query results.
Position uint `json:"position"`
// The list of ids for each Email in the query results, starting at the index given by the position argument of this
// response and continuing until it hits the end of the results or reaches the limit number of ids.
//
// If position is >= total, this MUST be the empty list.
Ids []string `json:"ids"`
// The total number of Emails in the results (given the filter).
//
// Only if requested.
//
// This argument MUST be omitted if the calculateTotal request argument is not true.
Total uint `json:"total,omitempty,omitzero"`
// The limit enforced by the server on the maximum number of results to return (if set by the server).
//
// This is only returned if the server set a limit or used a different limit than that given in the request.
Limit uint `json:"limit,omitempty,omitzero"`
}
type EmailGetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type
// in the account (not just the objects returned in this call).
//
// If the data changes, this string MUST change.
// If the Email data is unchanged, servers SHOULD return the same state string on subsequent requests for this data type.
State State `json:"state"`
// An array of the Email objects requested.
//
// This is the empty array if no objects were found or if the ids argument passed in was also an empty array.
//
// The results MAY be in a different order to the ids in the request arguments.
//
// If an identical id is included more than once in the request, the server MUST only include it once in either
// the list or the notFound argument of the response.
List []Email `json:"list"`
// This array contains the ids passed to the method for records that do not exist.
//
// The array is empty if all requested ids were found or if the ids argument passed in was either null or an empty array.
NotFound []string `json:"notFound"`
}
type EmailChangesResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
// This is the state the client will be in after applying the set of changes to the old state.
NewState State `json:"newState"`
// If true, the client may call Email/changes again with the newState returned to get further updates.
// If false, newState is the current server state.
HasMoreChanges bool `json:"hasMoreChanges"`
// An array of ids for records that have been created since the old state.
Created []string `json:"created,omitempty"`
// An array of ids for records that have been updated since the old state.
Updated []string `json:"updated,omitempty"`
// An array of ids for records that have been destroyed since the old state.
Destroyed []string `json:"destroyed,omitempty"`
}
type MailboxGetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type in the account
// (not just the objects returned in this call).
// If the data changes, this string MUST change.
// If the Mailbox data is unchanged, servers SHOULD return the same state string on subsequent requests for this data type.
// When a client receives a response with a different state string to a previous call, it MUST either throw away all currently
// cached objects for the type or call Foo/changes to get the exact changes.
State State `json:"state"`
// An array of the Mailbox objects requested.
// This is the empty array if no objects were found or if the ids argument passed in was also an empty array.
// The results MAY be in a different order to the ids in the request arguments.
// If an identical id is included more than once in the request, the server MUST only include it once in either
// the list or the notFound argument of the response.
List []Mailbox `json:"list"`
// This array contains the ids passed to the method for records that do not exist.
// The array is empty if all requested ids were found or if the ids argument passed in was either null or an empty array.
NotFound []any `json:"notFound"`
}
type MailboxChangesResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
// This is the state the client will be in after applying the set of changes to the old state.
NewState State `json:"newState"`
// If true, the client may call Mailbox/changes again with the newState returned to get further updates.
//
// If false, newState is the current server state.
HasMoreChanges bool `json:"hasMoreChanges"`
// An array of ids for records that have been created since the old state.
Created []string `json:"created,omitempty"`
// An array of ids for records that have been updated since the old state.
Updated []string `json:"updated,omitempty"`
// An array of ids for records that have been destroyed since the old state.
Destroyed []string `json:"destroyed,omitempty"`
// If only the “totalEmails”, “unreadEmails”, “totalThreads”, and/or “unreadThreads” Mailbox properties have
// changed since the old state, this will be the list of properties that may have changed.
//
// If the server is unable to tell if only counts have changed, it MUST just be null.
UpdatedProperties []string `json:"updatedProperties,omitempty"`
}
type MailboxQueryResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A string encoding the current state of the query on the server.
//
// This string MUST change if the results of the query (i.e., the matching ids and their sort order) have changed.
// The queryState string MAY change if something has changed on the server, which means the results may have
// changed but the server doesn’t know for sure.
//
// The queryState string only represents the ordered list of ids that match the particular query (including its
// sort/filter). There is no requirement for it to change if a property on an object matching the query changes
// but the query results are unaffected (indeed, it is more efficient if the queryState string does not change
// in this case). The queryState string only has meaning when compared to future responses to a query with the
// same type/sort/filter or when used with /queryChanges to fetch changes.
//
// Should a client receive back a response with a different queryState string to a previous call, it MUST either
// throw away the currently cached query and fetch it again (note, this does not require fetching the records
// again, just the list of ids) or call Mailbox/queryChanges to get the difference.
QueryState State `json:"queryState"`
// This is true if the server supports calling Mailbox/queryChanges with these filter/sort parameters.
//
// Note, this does not guarantee that the Mailbox/queryChanges call will succeed, as it may only be possible for
// a limited time afterwards due to server internal implementation details.
CanCalculateChanges bool `json:"canCalculateChanges"`
// The zero-based index of the first result in the ids array within the complete list of query results.
Position int `json:"position"`
// The list of ids for each Mailbox in the query results, starting at the index given by the position argument
// of this response and continuing until it hits the end of the results or reaches the limit number of ids.
//
// If position is >= total, this MUST be the empty list.
Ids []string `json:"ids"`
// The total number of Mailbox in the results (given the filter) (only if requested).
//
// This argument MUST be omitted if the calculateTotal request argument is not true.
Total int `json:"total,omitzero"`
// The limit enforced by the server on the maximum number of results to return (if set by the server).
//
// This is only returned if the server set a limit or used a different limit than that given in the request.
Limit int `json:"limit,omitzero"`
}
type EmailCreate struct {
// The set of Mailbox ids this Email belongs to.
//
// An Email in the mail store MUST belong to one or more Mailboxes at all times
// (until it is destroyed).
//
// The set is represented as an object, with each key being a Mailbox id.
// The value for each key in the object MUST be true.
MailboxIds map[string]bool `json:"mailboxIds,omitempty"`
// A set of keywords that apply to the Email.
//
// The set is represented as an object, with the keys being the keywords.
// The value for each key in the object MUST be true.
Keywords map[string]bool `json:"keywords,omitempty"`
// This is a list of all header fields [RFC5322], in the same order they appear in the message.
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
Headers []EmailHeader `json:"headers,omitempty"`
// The value is identical to the value of header:In-Reply-To:asMessageIds.
InReplyTo []string `json:"inReplyTo,omitempty"`
// The value is identical to the value of header:References:asMessageIds.
References []string `json:"references,omitempty"`
// The value is identical to the value of header:Sender:asAddresses.
Sender []EmailAddress `json:"sender,omitempty"`
// The ["From:" field] specifies the author(s) of the message, that is, the mailbox(es)
// of the person(s) or system(s) responsible for the writing of the message
//
// ["From:" field]: https://www.rfc-editor.org/rfc/rfc5322.html#section-3.6.2
From []EmailAddress `json:"from,omitempty"`
// The value is identical to the value of header:To:asAddresses.
To []EmailAddress `json:"to,omitempty"`
// The value is identical to the value of header:Cc:asAddresses.
Cc []EmailAddress `json:"cc,omitempty"`
// The value is identical to the value of header:Bcc:asAddresses.
Bcc []EmailAddress `json:"bcc,omitempty"`
// The value is identical to the value of header:Reply-To:asAddresses.
ReplyTo []EmailAddress `json:"replyTo,omitempty"`
// The "Subject:" field contains a short string identifying the topic of the message.
Subject string `json:"subject,omitempty"`
// The date the Email was received by the message store.
//
// (default: time of most recent Received header, or time of import on server if none).
ReceivedAt time.Time `json:"receivedAt,omitzero"`
// The origination date specifies the date and time at which the creator of the message indicated that
// the message was complete and ready to enter the mail delivery system.
//
// For instance, this might be the time that a user pushes the "send" or "submit" button in an
// application program.
//
// In any case, it is specifically not intended to convey the time that the message is actually transported,
// but rather the time at which the human or other creator of the message has put the message into its final
// form, ready for transport.
//
// (For example, a portable computer user who is not connected to a network might queue a message for delivery.
// The origination date is intended to contain the date and time that the user queued the message, not the time
// when the user connected to the network to send the message.)
SentAt time.Time `json:"sentAt,omitzero"`
// This is the full MIME structure of the message body, without recursing into message/rfc822 or message/global parts.
//
// Note that EmailBodyParts may have subParts if they are of type multipart/*.
BodyStructure *EmailBodyPart `json:"bodyStructure,omitempty"`
// This is a map of partId to an EmailBodyValue object for none, some, or all text/* parts.
BodyValues map[string]EmailBodyValue `json:"bodyValues,omitempty"`
// A list of text/plain, text/html, image/*, audio/*, and/or video/* parts to display (sequentially) as the
// message body, with a preference for text/plain when alternative versions are available.
TextBody []EmailBodyPart `json:"textBody,omitempty"`
// A list of text/plain, text/html, image/*, audio/*, and/or video/* parts to display (sequentially) as the
// message body, with a preference for text/html when alternative versions are available.
HtmlBody []EmailBodyPart `json:"htmlBody,omitempty"`
// A list, traversing depth-first, of all parts in bodyStructure.
//
// They must satisfy either of the following conditions:
//
// - not of type multipart/* and not included in textBody or htmlBody
// - of type image/*, audio/*, or video/* and not in both textBody and htmlBody
//
// None of these parts include subParts, including message/* types.
//
// Attached messages may be fetched using the Email/parse method and the blobId.
//
// Note that a text/html body part HTML may reference image parts in attachments by using cid:
// links to reference the Content-Id, as defined in [RFC2392], or by referencing the Content-Location.
//
// [RFC2392]: https://www.rfc-editor.org/rfc/rfc2392.html
Attachments []EmailBodyPart `json:"attachments,omitempty"`
}
type EmailUpdate map[string]any
type EmailSetCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// This is a state string as returned by the `Email/get` method.
//
// If supplied, the string must match the current state; otherwise, the method will be aborted and a
// `stateMismatch` error returned.
//
// If null, any changes will be applied to the current state.
IfInState string `json:"ifInState,omitempty"`
// A map of a creation id (a temporary id set by the client) to Email objects,
// or null if no objects are to be created.
//
// The Email object type definition may define default values for properties.
//
// Any such property may be omitted by the client.
//
// The client MUST omit any properties that may only be set by the server.
Create map[string]EmailCreate `json:"create,omitempty"`
// A map of an id to a `Patch` object to apply to the current Email object with that id,
// or null if no objects are to be updated.
//
// A `PatchObject` is of type `String[*]` and represents an unordered set of patches.
//
// The keys are a path in JSON Pointer Format [@!RFC6901], with an implicit leading `/` (i.e., prefix each key
// with `/` before applying the JSON Pointer evaluation algorithm).
//
// All paths MUST also conform to the following restrictions; if there is any violation, the update
// MUST be rejected with an `invalidPatch` error:
// !- The pointer MUST NOT reference inside an array (i.e., you MUST NOT insert/delete from an array; the array MUST be replaced in its entirety instead).
// !- All parts prior to the last (i.e., the value after the final slash) MUST already exist on the object being patched.
// !- There MUST NOT be two patches in the `PatchObject` where the pointer of one is the prefix of the pointer of the other, e.g., `"alerts/1/offset"` and `"alerts"`.
//
// The value associated with each pointer determines how to apply that patch:
// !- If null, set to the default value if specified for this property; otherwise, remove the property from the patched object. If the key is not present in the parent, this a no-op.
// !- Anything else: The value to set for this property (this may be a replacement or addition to the object being patched).
//
// Any server-set properties MAY be included in the patch if their value is identical to the current server value
// (before applying the patches to the object). Otherwise, the update MUST be rejected with an `invalidProperties` `SetError`.
//
// This patch definition is designed such that an entire Email object is also a valid `PatchObject`.
//
// The client may choose to optimise network usage by just sending the diff or may send the whole object; the server
// processes it the same either way.
Update map[string]EmailUpdate `json:"update,omitempty"`
// A list of ids for Email objects to permanently delete, or null if no objects are to be destroyed.
Destroy []string `json:"destroy,omitempty"`
}
type EmailSetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// The state string that would have been returned by Email/get before making the
// requested changes, or null if the server doesn’t know what the previous state
// string was.
OldState State `json:"oldState,omitempty"`
// The state string that will now be returned by Email/get.
NewState State `json:"newState"`
// A map of the creation id to an object containing any properties of the created Email object
// that were not sent by the client.
//
// This includes all server-set properties (such as the id in most object types) and any properties
// that were omitted by the client and thus set to a default by the server.
//
// This argument is null if no Email objects were successfully created.
Created map[string]*Email `json:"created,omitempty"`
// The keys in this map are the ids of all Emails that were successfully updated.
//
// The value for each id is an Email object containing any property that changed in a way not
// explicitly requested by the PatchObject sent to the server, or null if none.
//
// This lets the client know of any changes to server-set or computed properties.
//
// This argument is null if no Email objects were successfully updated.
Updated map[string]*Email `json:"updated,omitempty"`
// A list of Email ids for records that were successfully destroyed, or null if none.
Destroyed []string `json:"destroyed,omitempty"`
// A map of the creation id to a SetError object for each record that failed to be created,
// or null if all successful.
NotCreated map[string]SetError `json:"notCreated,omitempty"`
// A map of the Email id to a SetError object for each record that failed to be updated,
// or null if all successful.
NotUpdated map[string]SetError `json:"notUpdated,omitempty"`
// A map of the Email id to a SetError object for each record that failed to be destroyed,
// or null if all successful.
NotDestroyed map[string]SetError `json:"notDestroyed,omitempty"`
}
const (
EmailMimeType = "message/rfc822"
)
type EmailImport struct {
// The id of the blob containing the raw message [RFC5322].
//
// [RFC5322]: https://www.rfc-editor.org/rfc/rfc5322.html
BlobId string `json:"blobId"`
// The ids of the Mailboxes to assign this Email to.
//
// At least one Mailbox MUST be given.
MailboxIds map[string]bool `json:"mailboxIds"`
// The keywords to apply to the Email.
Keywords map[string]bool `json:"keywords"`
// (default: time of most recent Received header, or time of import
// on server if none) The receivedAt date to set on the Email.
ReceivedAt time.Time `json:"receivedAt"`
}
type EmailImportCommand struct {
AccountId string `json:"accountId"`
// This is a state string as returned by the Email/get method.
//
// If supplied, the string must match the current state of the account referenced
// by the accountId; otherwise, the method will be aborted and a stateMismatch
// error returned.
//
// If null, any changes will be applied to the current state.
IfInState string `json:"ifInState,omitempty"`
// A map of creation id (client specified) to EmailImport objects.
Emails map[string]EmailImport `json:"emails"`
}
// Successfully imported Email.
type ImportedEmail struct {
// Id of the successfully imported Email.
Id string `json:"id"`
// Blob id of the successfully imported Email.
BlobId string `json:"blobId"`
// Thread id of the successfully imported Email.
ThreadId string `json:"threadId"`
// Size of the successfully imported Email.
Size int `json:"size"`
}
type EmailImportResponse struct {
// The id of the account used for this call.
AccountId string `json:"accountId"`
// The state string that would have been returned by Email/get on this account
// before making the requested changes, or null if the server doesn’t know
// what the previous state string was.
OldState State `json:"oldState"`
// The state string that will now be returned by Email/get on this account.
NewState State `json:"newState"`
// A map of the creation id to an object containing the id, blobId, threadId,
// and size properties for each successfully imported Email, or null if none.
Created map[string]ImportedEmail `json:"created"`
// A map of the creation id to a SetError object for each Email that failed to
// be created, or null if all successful.
NotCreated map[string]SetError `json:"notCreated"`
}
// Replies are grouped together with the original message to form a Thread.
//
// In JMAP, a Thread is simply a flat list of Emails, ordered by date.
//
// Every Email MUST belong to a Thread, even if it is the only Email in the Thread.
type Thread struct {
// The id of the Thread.
Id string
// The ids of the Emails in the Thread, sorted by the receivedAt date of the Email,
// oldest first.
//
// If two Emails have an identical date, the sort is server dependent but MUST be
// stable (sorting by id is recommended).
EmailIds []string
}
type ThreadGetCommand struct {
AccountId string `json:"accountId"`
Ids []string `json:"ids,omitempty"`
}
type ThreadGetRefCommand struct {
AccountId string `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
}
type ThreadGetResponse struct {
AccountId string
State State
List []Thread
NotFound []any
}
type IdentityGetCommand struct {
AccountId string `json:"accountId"`
Ids []string `json:"ids,omitempty"`
}
type IdentitySetCommand struct {
AccountId string `json:"accountId"`
IfInState string `json:"ifInState,omitempty"`
Create map[string]Identity `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
Destroy []string `json:"destroy,omitempty"`
}
type IdentitySetResponse struct {
AccountId string `json:"accountId"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
Created map[string]Identity `json:"created,omitempty"`
Updated map[string]Identity `json:"updated,omitempty"`
Destroyed []string `json:"destroyed,omitempty"`
NotCreated map[string]SetError `json:"notCreated,omitempty"`
NotUpdated map[string]SetError `json:"notUpdated,omitempty"`
NotDestroyed map[string]SetError `json:"notDestroyed,omitempty"`
}
type Identity struct {
// The id of the Identity.
Id string `json:"id,omitempty"`
// The “From” name the client SHOULD use when creating a new Email from this Identity.
Name string `json:"name,omitempty"`
// The “From” email address the client MUST use when creating a new Email from this Identity.
//
// If the mailbox part of the address (the section before the “@”) is the single character
// * (e.g., *@example.com) then the client may use any valid address ending in that domain
// (e.g., foo@example.com).
Email string `json:"email,omitempty"`
// The Reply-To value the client SHOULD set when creating a new Email from this Identity.
ReplyTo string `json:"replyTo,omitempty"`
// The Bcc value the client SHOULD set when creating a new Email from this Identity.
Bcc *[]EmailAddress `json:"bcc,omitempty"`
// A signature the client SHOULD insert into new plaintext messages that will be sent from
// this Identity.
//
// Clients MAY ignore this and/or combine this with a client-specific signature preference.
TextSignature *string `json:"textSignature,omitempty"`
// A signature the client SHOULD insert into new HTML messages that will be sent from this
// Identity.
//
// This text MUST be an HTML snippet to be inserted into the section of the HTML.
//
// Clients MAY ignore this and/or combine this with a client-specific signature preference.
HtmlSignature *string `json:"htmlSignature,omitempty"`
// Is the user allowed to delete this Identity?
//
// Servers may wish to set this to false for the user’s username or other default address.
//
// Attempts to destroy an Identity with mayDelete: false will be rejected with a standard
// forbidden SetError.
MayDelete bool `json:"mayDelete,omitzero"`
}
func (i Identity) AsPatch() PatchObject {
p := PatchObject{}
if i.Name != "" {
p["name"] = i.Name
}
if i.Email != "" {
p["email"] = i.Email
}
if i.ReplyTo != "" {
p["replyTo"] = i.ReplyTo
}
if i.Bcc != nil {
p["bcc"] = i.Bcc
}
if i.TextSignature != nil {
p["textSignature"] = i.TextSignature
}
if i.HtmlSignature != nil {
p["htmlSignature"] = i.HtmlSignature
}
return p
}
type IdentityGetResponse struct {
AccountId string `json:"accountId"`
State State `json:"state"`
List []Identity `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
}
type VacationResponseGetCommand struct {
AccountId string `json:"accountId"`
}
// Vacation Response
//
// A vacation response sends an automatic reply when a message is delivered to the mail store,
// informing the original sender that their message may not be read for some time.
//
// Automated message sending can produce undesirable behaviour.
// To avoid this, implementors MUST follow the recommendations set forth in [RFC3834].
//
// The VacationResponse object represents the state of vacation-response-related settings for an account.
//
// [RFC3834]: https://www.rfc-editor.org/rfc/rfc3834.html
type VacationResponse struct {
// The id of the object.
// There is only ever one VacationResponse object, and its id is "singleton"
Id string `json:"id,omitempty"`
// Should a vacation response be sent if a message arrives between the "fromDate" and "toDate"?
IsEnabled bool `json:"isEnabled"`
// If "isEnabled" is true, messages that arrive on or after this date-time (but before the "toDate" if defined) should receive the
// user's vacation response. If null, the vacation response is effective immediately.
FromDate time.Time `json:"fromDate,omitzero"`
// If "isEnabled" is true, messages that arrive before this date-time but on or after the "fromDate" if defined) should receive the
// user's vacation response. If null, the vacation response is effective indefinitely.
ToDate time.Time `json:"toDate,omitzero"`
// The subject that will be used by the message sent in response to messages when the vacation response is enabled.
// If null, an appropriate subject SHOULD be set by the server.
Subject string `json:"subject,omitempty"`
// The plaintext body to send in response to messages when the vacation response is enabled.
// If this is null, the server SHOULD generate a plaintext body part from the "htmlBody" when sending vacation responses
// but MAY choose to send the response as HTML only. If both "textBody" and "htmlBody" are null, an appropriate default
// body SHOULD be generated for responses by the server.
TextBody string `json:"textBody,omitempty"`
// The HTML body to send in response to messages when the vacation response is enabled.
// If this is null, the server MAY choose to generate an HTML body part from the "textBody" when sending vacation responses
// or MAY choose to send the response as plaintext only.
HtmlBody string `json:"htmlBody,omitempty"`
}
type VacationResponseGetResponse struct {
// The identifier of the account this response pertains to.
AccountId string `json:"accountId"`
// A string representing the state on the server for all the data of this type in the account
// (not just the objects returned in this call).
//
// If the data changes, this string MUST change. If the data is unchanged, servers SHOULD return the same state string
// on subsequent requests for this data type.
State State `json:"state,omitempty"`
// An array of VacationResponse objects.
List []VacationResponse `json:"list,omitempty"`
// Contains identifiers of requested objects that were not found.
NotFound []any `json:"notFound,omitempty"`
}
type VacationResponseSetCommand struct {
AccountId string `json:"accountId"`
IfInState string `json:"ifInState,omitempty"`
Create map[string]VacationResponse `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
Destroy []string `json:"destroy,omitempty"`
}
type VacationResponseSetResponse struct {
AccountId string `json:"accountId"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
Created map[string]VacationResponse `json:"created,omitempty"`
Updated map[string]VacationResponse `json:"updated,omitempty"`
Destroyed []string `json:"destroyed,omitempty"`
NotCreated map[string]SetError `json:"notCreated,omitempty"`
NotUpdated map[string]SetError `json:"notUpdated,omitempty"`
NotDestroyed map[string]SetError `json:"notDestroyed,omitempty"`
}
// One of these attributes must be set, but not both.
type DataSourceObject struct {
DataAsText string `json:"data:asText,omitempty"`
DataAsBase64 string `json:"data:asBase64,omitempty"`
}
type UploadObject struct {
Data []DataSourceObject `json:"data"`
Type string `json:"type,omitempty"`
}
type BlobUploadCommand struct {
AccountId string `json:"accountId"`
Create map[string]UploadObject `json:"create"`
}
type BlobUploadCreateResult struct {
Id string `json:"id"`
Type string `json:"type,omitempty"`
Size int `json:"size"`
}
type BlobUploadResponse struct {
AccountId string `json:"accountId"`
Created map[string]BlobUploadCreateResult `json:"created"`
}
const (
BlobPropertyDataAsText = "data:asText"
BlobPropertyDataAsBase64 = "data:asBase64"
// Returns data:asText if the selected octets are valid UTF-8 or data:asBase64.
BlobPropertyData = "data"
BlobPropertySize = "size"
// https://www.iana.org/assignments/http-digest-hash-alg/http-digest-hash-alg.xhtml
BlobPropertyDigestSha256 = "digest:sha256"
// https://www.iana.org/assignments/http-digest-hash-alg/http-digest-hash-alg.xhtml
BlobPropertyDigestSha512 = "digest:sha512"
)
type BlobGetCommand struct {
AccountId string `json:"accountId"`
Ids []string `json:"ids,omitempty"`
Properties []string `json:"properties,omitempty"`
Offset int `json:"offset,omitzero"`
Length int `json:"length,omitzero"`
}
type BlobGetRefCommand struct {
AccountId string `json:"accountId"`
IdRef *ResultReference `json:"#ids,omitempty"`
Properties []string `json:"properties,omitempty"`
Offset int `json:"offset,omitzero"`
Length int `json:"length,omitzero"`
}
type Blob struct {
// The unique identifier of the blob.
Id string `json:"id"`
// (raw octets, must be UTF-8)
DataAsText string `json:"data:asText,omitempty"`
// (base64 representation of octets)
DataAsBase64 string `json:"data:asBase64,omitempty"`
// The base64 encoding of the digest of the octets in the selected range,
// calculated using the SHA-256 algorithm.
DigestSha256 string `json:"digest:sha256,omitempty"`
// The base64 encoding of the digest of the octets in the selected range,
// calculated using the SHA-512 algorithm.
DigestSha512 string `json:"digest:sha512,omitempty"`
// If an encoding problem occured.
//
// The data fields contain a representation of the octets within the selected range
// that are present in the blob.
//
// If the octets selected are not valid UTF-8 (including truncating in the middle of a
// multi-octet sequence) and data or data:asText was requested, then the key isEncodingProblem
// MUST be set to true, and the data:asText response value MUST be null.
//
// In the case where data was requested and the data is not valid UTF-8, then data:asBase64
// MUST be returned.
IsEncodingProblem bool `json:"isEncodingProblem,omitzero"`
// When requesting a range: the isTruncated property in the result MUST be
// set to true to tell the client that the requested range could not be fully satisfied.
IsTruncated bool `json:"isTruncated,omitzero"`
// The number of octets in the entire blob.
Size int `json:"size"`
}
// Picks the best digest if available, or ""
func (b *Blob) Digest() string {
if b.DigestSha512 != "" {
return b.DigestSha512
} else if b.DigestSha256 != "" {
return b.DigestSha256
} else {
return ""
}
}
type BlobGetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A string representing the state on the server for all the data of this type in the
// account (not just the objects returned in this call).
//
// If the data changes, this string MUST change. If the Blob data is unchanged, servers
// SHOULD return the same state string on subsequent requests for this data type.
//
// When a client receives a response with a different state string to a previous call,
// it MUST either throw away all currently cached objects for the type or call
// Blob/changes to get the exact changes.
State State `json:"state,omitempty"`
// An array of the Blob objects requested.
//
// This is the empty array if no objects were found or if the ids argument passed in
// was also an empty array. The results MAY be in a different order to the ids in the
// request arguments. If an identical id is included more than once in the request,
// the server MUST only include it once in either the list or the notFound argument of the response.
List []Blob `json:"list,omitempty"`
// This array contains the ids passed to the method for records that do not exist.
//
// The array is empty if all requested ids were found or if the ids argument passed
// in was either null or an empty array.
NotFound []any `json:"notFound,omitempty"`
}
type BlobDownload struct {
Body io.ReadCloser
Size int
Type string
ContentDisposition string
CacheControl string
}
type UploadedBlob struct {
BlobId string `json:"blobId"`
Size int `json:"size,omitzero"`
Type string `json:"type,omitempty"`
}
// When doing a search on a String property, the client may wish to show the relevant
// section of the body that matches the search as a preview and to highlight any
// matching terms in both this and the subject of the Email.
//
// Search snippets represent this data.
//
// What is a relevant section of the body for preview is server defined. If the server is
// unable to determine search snippets, it MUST return null for both the subject and preview
// properties.
//
// Note that unlike most data types, a SearchSnippet DOES NOT have a property called id.
type SearchSnippet struct {
// The Email id the snippet applies to.
EmailId string `json:"emailId"`
// If text from the filter matches the subject, this is the subject of the Email
// with the following transformations:
//
// 1. Any instance of the following three characters MUST be replaced by an
// appropriate HTML entity: & (ampersand), < (less-than sign), and > (greater-than sign)
// HTML. Other characters MAY also be replaced with an HTML entity form.
// 2. The matching words/phrases from the filter are wrapped in HTML tags.
//
// If the subject does not match text from the filter, this property is null.
Subject string `json:"subject,omitempty"`
// If text from the filter matches the plaintext or HTML body, this is the
// relevant section of the body (converted to plaintext if originally HTML),
// with the same transformations as the subject property.
//
// It MUST NOT be bigger than 255 octets in size.
//
// If the body does not contain a match for the text from the filter, this property is null.
Preview string `json:"preview,omitempty"`
}
type SearchSnippetGetRefCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// The same filter as passed to Email/query.
Filter EmailFilterElement `json:"filter,omitempty"`
// The ids of the Emails to fetch snippets for.
EmailIdRef *ResultReference `json:"#emailIds,omitempty"`
}
type SearchSnippetGetResponse struct {
AccountId string `json:"accountId"`
List []SearchSnippet `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
}
type StateChangeType string
const TypeOfStateChange = StateChangeType("StateChange")
type StateChange struct {
// This MUST be the string "StateChange".
Type StateChangeType `json:"@type"`
// A map of an "account id" to an object encoding the state of data types that have
// changed for that account since the last StateChange object was pushed, for each
// of the accounts to which the user has access and for which something has changed.
//
// The value is a map. The keys are the type name "Foo" e.g., "Mailbox" or "Email"),
// and the value is the "state" property that would currently be returned by a call to
// "Foo/get".
//
// The client can compare the new state strings with its current values to see whether
// it has the current data for these types. If not, the changes can then be efficiently
// fetched in a single standard API request (using the /changes type methods).
Changed map[string]map[ObjectType]string `json:"changed"`
// A (preferably short) string that encodes the entire server state visible to the user
// (not just the objects returned in this call).
//
// The purpose of the "pushState" token is to allow a client to immediately get any changes
// that occurred while it was disconnected. If the server does not support "pushState" tokens,
// the client will have to issue a series of "/changes" requests upon reconnection to update
// its state to match that of the server.
PushState State `json:"pushState"`
}
type AddressBookRights struct {
// The user may fetch the ContactCards in this AddressBook.
MayRead bool `json:"mayRead"`
// The user may create, modify or destroy all ContactCards in this AddressBook, or move them to or from this AddressBook.
MayWrite bool `json:"mayWrite"`
// The user may modify the “shareWith” property for this AddressBook.
MayAdmin bool `json:"mayAdmin"`
// The user may delete the AddressBook itself.
MayDelete bool `json:"mayDelete"`
}
// An AddressBook is a named collection of ContactCards.
//
// All ContactCards are associated with one or more AddressBook.
type AddressBook struct {
// The id of the AddressBook (immutable; server-set).
Id string `json:"id"`
// The user-visible name of the AddressBook.
//
// This may be any UTF-8 string of at least 1 character in length and maximum 255 octets in size.
Name string `json:"name"`
// An optional longer-form description of the AddressBook, to provide context in shared environments
// where users need more than just the name.
Description string `json:"description,omitempty"`
// Defines the sort order of AddressBooks when presented in the client’s UI, so it is consistent between devices.
//
// The number MUST be an integer in the range 0 <= sortOrder < 2^31.
//
// An AddressBook with a lower order should be displayed before a AddressBook with a higher order in any list
// of AddressBooks in the client’s UI.
//
// AddressBooks with equal order SHOULD be sorted in alphabetical order by name.
//
// The sorting should take into account locale-specific character order convention.
//
// Default: 0
SortOrder uint `json:"sortOrder,omitzero"`
// This SHOULD be true for exactly one AddressBook in any account, and MUST NOT be true for more than one
// AddressBook within an account.
//
// The default AddressBook should be used by clients whenever they need to choose an AddressBook for the user
// within this account, and they do not have any other information on which to make a choice.
//
// For example, if the user creates a new contact card, the client may automatically set the card as belonging
// to the default AddressBook from the user’s primary account.
IsDefault bool `json:"isDefault,omitzero"`
// True if the user has indicated they wish to see this AddressBook in their client.
//
// This SHOULD default to false for AddressBooks in shared accounts the user has access to and true for any
// new AddressBooks created by the user themself.
//
// If false, the AddressBook and its contents SHOULD only be displayed when the user explicitly requests it
// or to offer it for the user to subscribe to.
IsSubscribed bool `json:"isSubscribed"`
// A map of Principal id to rights for principals this AddressBook is shared with.
//
// The principal to which this AddressBook belongs MUST NOT be in this set.
//
// This is null if the AddressBook is not shared with anyone.
//
// May be modified only if the user has the mayAdmin right.
//
// The account id for the principals may be found in the urn:ietf:params:jmap:principals:owner capability
// of the Account to which the AddressBook belongs.
ShareWith map[string]AddressBookRights `json:"shareWith,omitempty"`
// The set of access rights the user has in relation to this AddressBook (server-set).
MyRights AddressBookRights `json:"myRights"`
}
type CalendarRights struct {
// The user may read the free-busy information for this calendar.
MayReadFreeBusy bool `json:"mayReadFreeBusy"`
// The user may fetch the events in this calendar.
MayReadItems bool `json:"mayReadItems"`
// The user may create, modify or destroy all events in this calendar, or move events
// to or from this calendar.
//
// If this is `true`, the `mayWriteOwn`, `mayUpdatePrivate` and `mayRSVP`
// properties MUST all also be `true`.
MayWriteAll bool `json:"mayWriteAll"`
// The user may create, modify or destroy an event on this calendar if either they are
// the owner of the event or the event has no owner.
//
// This means the user may also transfer ownership by updating an event so they are no longer an owner.
MayWriteOwn bool `json:"mayWriteOwn"`
// The user may modify per-user properties on all events in the calendar, even if they would
// not otherwise have permission to modify that event.
//
// These properties MUST all be stored per-user, and changes do not affect any other user of the calendar.
//
// The user may also modify these properties on a per-occurrence basis for recurring events
// (updating the `recurrenceOverrides` property of the event to do so).
MayUpdatePrivate bool `json:"mayUpdatePrivate"`
// The user may modify the following properties of any `Participant` object that corresponds
// to one of the user's `ParticipantIdentity` objects in the account, even if they would not
// otherwise have permission to modify that event.
//
// !- `participationStatus`
// !- `participationComment`
// !- `expectReply`
// !- `scheduleAgent`
// !- `scheduleSequence`
// !- `scheduleUpdated`
//
// If the event has its `mayInviteSelf` property set to `true`, then the user may also add a
// new `Participant` to the event with `scheduleId`/`sendTo` properties that are the same as
// the `scheduleId`/`sendTo` properties of one of the user's `ParticipantIdentity` objects in
// the account.
//
// The `roles` property of the participant MUST only contain `attendee`.
//
// If the event has its `mayInviteOthers` property set to `true` and there is an existing
// `Participant` in the event corresponding to one of the user's `ParticipantIdentity` objects
// in the account, then the user may also add new participants.
//
// The `roles` property of any new participant MUST only contain `attendee`.
//
// The user may also do all of the above on a per-occurrence basis for recurring events
// (updating the recurrenceOverrides property of the event to do so).
MayRSVP bool `json:"mayRSVP"`
// The user may modify the `shareWith` property for this calendar.
MayAdmin bool `json:"mayAdmin"`
// The user may delete the calendar itself.
MayDelete bool `json:"mayDelete"`
}
// A Calendar is a named collection of events.
//
// All events are associated with at least one calendar.
//
// The user is an owner for an event if the `CalendarEvent` object has a `participants`
// property, and one of the `Participant` objects both:
// 1. Has the `owner` role.
// 2. Corresponds to one of the user's `ParticipantIdentity` objects in the account.
//
// An event has no owner if its `participants` property is null or omitted, or if none
// of the `Participant` objects have the `owner` role.
type Calendar struct {
// The id of the calendar (immutable; server-set).
Id string `json:"id"`
// The user-visible name of the calendar.
//
// This may be any UTF-8 string of at least 1 character in length and maximum 255 octets in size.
Name string `json:"name"`
// An optional longer-form description of the calendar, to provide context in shared environments
// where users need more than just the name.
Description string `json:"description,omitempty"`
// A color to be used when displaying events associated with the calendar.
//
// If not null, the value MUST be a case-insensitive color name taken from the set of names
// defined in Section 4.3 of CSS Color Module Level 3 COLORS, or an RGB value in hexadecimal
// notation, as defined in Section 4.2.1 of CSS Color Module Level 3.
//
// The color SHOULD have sufficient contrast to be used as text on a white background.
Color string `json:"color,omitempty"`
// Defines the sort order of calendars when presented in the client’s UI, so it is consistent
// between devices.
//
// The number MUST be an integer in the range 0 <= sortOrder < 2^31.
//
// A calendar with a lower order should be displayed before a calendar with a higher order in any
// list of calendars in the client’s UI.
//
// Calendars with equal order SHOULD be sorted in alphabetical order by name.
//
// The sorting should take into account locale-specific character order convention.
SortOrder uint `json:"sortOrder,omitzero"`
// True if the user has indicated they wish to see this Calendar in their client.
//
// This SHOULD default to `false` for Calendars in shared accounts the user has access to and `true`
// for any new Calendars created by the user themself.
//
// If false, the calendar SHOULD only be displayed when the user explicitly requests it or to offer
// it for the user to subscribe to.
//
// For example, a company may have a large number of shared calendars which all employees have
// permission to access, but you would only subscribe to the ones you care about and want to be able
// to have normally accessible.
IsSubscribed bool `json:"isSubscribed"`
// Should the calendar’s events be displayed to the user at the moment?
//
// Clients MUST ignore this property if `isSubscribed` is false.
//
// If an event is in multiple calendars, it should be displayed if `isVisible` is `true`
// for any of those calendars.
//
// default: true
IsVisible bool `json:"isVisible"`
// This SHOULD be true for exactly one calendar in any account, and MUST NOT be true for more
// than one calendar within an account (server-set).
//
// The default calendar should be used by clients whenever they need to choose a calendar
// for the user within this account, and they do not have any other information on which to make
// a choice.
//
// For example, if the user creates a new event, the client may automatically set the event as
// belonging to the default calendar from the user’s primary account.
IsDefault bool `json:"isDefault,omitzero"`
// Should the calendar’s events be used as part of availability calculation?
//
// This MUST be one of:
// !- `all``: all events are considered.
// !- `attending``: events the user is a confirmed or tentative participant of are considered.
// !- `none``: all events are ignored (but may be considered if also in another calendar).
//
// This should default to “all” for the calendars in the user’s own account, and “none” for calendars shared with the user.
IncludeInAvailability IncludeInAvailability `json:"includeInAvailability,omitempty"`
// A map of alert ids to Alert objects (see [@!RFC8984], Section 4.5.2) to apply for events
// where `showWithoutTime` is `false` and `useDefaultAlerts` is `true`.
//
// Ids MUST be unique across all default alerts in the account, including those in other
// calendars; a UUID is recommended.
//
// The "trigger" MUST NOT be an `AbsoluteTrigger`, as this would fire for every event at the same
// time and so does not make sense for a default alert.
//
// If omitted on creation, the default is server dependent.
//
// For example, servers may choose to always default to null, or may copy the alerts from the default calendar.
DefaultAlertsWithTime map[string]jscalendar.Alert `json:"defaultAlertsWithTime,omitempty"`
// A map of alert ids to Alert objects (see [@!RFC8984], Section 4.5.2) to apply for events where
// `showWithoutTime` is `true` and `useDefaultAlerts` is `true`.
//
// Ids MUST be unique across all default alerts in the account, including those in other
// calendars; a UUID is recommended.
//
// The "trigger" MUST NOT be an `AbsoluteTrigger`, as this would fire for every event at the
// same time and so does not make sense for a default alert.
//
// If omitted on creation, the default is server dependent.
//
// For example, servers may choose to always default to null, or may copy the alerts from the default calendar.
DefaultAlertsWithoutTime map[string]jscalendar.Alert `json:"defaultAlertsWithoutTime,omitempty"`
// The time zone to use for events without a time zone when the server needs to resolve them into
// absolute time, e.g., for alerts or availability calculation.
//
// The value MUST be a time zone id from the IANA Time Zone Database TZDB.
//
// If null, the `timeZone` of the account’s associated `Principal` will be used.
//
// Clients SHOULD use this as the default for new events in this calendar if set.
TimeZone string `json:"timeZone,omitempty"`
// A map of `Principal` id to rights for principals this calendar is shared with.
//
// The principal to which this calendar belongs MUST NOT be in this set.
//
// This is null if the calendar is not shared with anyone.
//
// May be modified only if the user has the `mayAdmin` right.
//
// The account id for the principals may be found in the `urn:ietf:params:jmap:principals:owner`
// capability of the `Account` to which the calendar belongs.
ShareWith map[string]CalendarRights `json:"shareWith,omitempty"`
// The set of access rights the user has in relation to this Calendar.
//
// If any event is in multiple calendars, the user has the following rights:
// !- The user may fetch the event if they have the mayReadItems right on any calendar the event is in.
// !- The user may remove an event from a calendar (by modifying the event’s “calendarIds” property) if the user
// has the appropriate permission for that calendar.
// !- The user may make other changes to the event if they have the right to do so in all calendars to which the
// event belongs.
MyRights *CalendarRights `json:"myRights,omitempty"`
}
// A CalendarEvent object contains information about an event, or recurring series of events,
// that takes place at a particular time.
//
// It is a JSCalendar Event object, as defined in [@!RFC8984], with additional properties.
type CalendarEvent struct {
// The id of the CalendarEvent (immutable; server-set).
//
// The id uniquely identifies a JSCalendar Event with a particular `uid` and
// `recurrenceId` within a particular account.
Id string `json:"id,omitempty"`
// This is only defined if the `id` property is a synthetic id, generated by the
// server to represent a particular instance of a recurring event (immutable; server-set).
//
// This property gives the id of the "real" `CalendarEvent` this was generated from.
BaseEventId string `json:"baseEventId,omitempty"`
// The set of Calendar ids this event belongs to.
//
// An event MUST belong to one or more Calendars at all times (until it is destroyed).
//
// The set is represented as an object, with each key being a Calendar id.
//
// The value for each key in the object MUST be `true`.
CalendarIds map[string]bool `json:"calendarIds,omitempty"`
// If true, this event is to be considered a draft.
//
// The server will not send any scheduling messages to participants or send push notifications
// for alerts.
//
// This may only be set to `true` upon creation.
//
// Once set to `false`, the value cannot be updated to `true`.
//
// This property MUST NOT appear in `recurrenceOverrides`.
IsDraft bool `json:"isDraft,omitzero"`
// Is this the authoritative source for this event (i.e., does it control scheduling for
// this event; the event has not been added as a result of an invitation from another calendar system)?
//
// This is true if, and only if:
// !- the event’s `replyTo` property is null; or
// !- the account will receive messages sent to at least one of the methods specified in the `replyTo` property of the event.
IsOrigin bool `json:"isOrigin,omitzero"`
// For simple clients that do not implement time zone support.
//
// Clients should only use this if also asking the server to expand recurrences, as you cannot accurately
// expand a recurrence without the original time zone.
//
// This property is calculated at fetch time by the server.
//
// Time zones are political and they can and do change at any time.
//
// Fetching exactly the same property again may return a different results if the time zone data has been updated on the server.
//
// Time zone data changes are not considered `updates` to the event.
//
// If set, the server will convert the UTC date to the event's current time zone and store the local time.
//
// This property is not included in `CalendarEvent/get` responses by default and must be requested explicitly.
//
// Floating events (events without a time zone) will be interpreted as per the time zone given as a `CalendarEvent/get` argument.
//
// Note that it is not possible to accurately calculate the expansion of recurrence rules or recurrence overrides with the
// `utcStart` property rather than the local start time. Even simple recurrences such as "repeat weekly" may cross a
// daylight-savings boundary and end up at a different UTC time. Clients that wish to use "utcStart" are RECOMMENDED to
// request the server expand recurrences.
UtcStart UTCDate `json:"utcStart,omitzero"`
// The server calculates the end time in UTC from the start/timeZone/duration properties of the event.
//
// This property is not included by default and must be requested explicitly.
//
// Like `utcStart`, it is calculated at fetch time if requested and may change due to time zone data changes.
//
// Floating events will be interpreted as per the time zone given as a `CalendarEvent/get` argument.
UtcEnd UTCDate `json:"utcEnd,omitzero"`
jscalendar.Event
}
const (
CalendarEventPropertyId = "id"
CalendarEventPropertyBaseEventId = "baseEventId"
CalendarEventPropertyCalendarIds = "calendarIds"
CalendarEventPropertyIsDraft = "isDraft"
CalendarEventPropertyIsOrigin = "isOrigin"
CalendarEventPropertyUtcStart = "utcStart"
CalendarEventPropertyUtcEnd = "utcEnd"
CalendarEventPropertyType = "type"
CalendarEventPropertyStart = "start"
CalendarEventPropertyDuration = "duration"
CalendarEventPropertyStatus = "status"
CalendarEventPropertyRelatedTo = "relatedTo"
CalendarEventPropertySequence = "sequence"
CalendarEventPropertyShowWithoutTime = "showWithoutTime"
CalendarEventPropertyLocations = "locations"
CalendarEventPropertyVirtualLocations = "virtualLocations"
CalendarEventPropertyRecurrenceId = "recurrenceId"
CalendarEventPropertyRecurrenceIdTimeZone = "recurrenceIdTimeZone"
CalendarEventPropertyRecurrenceRules = "recurrenceRules"
CalendarEventPropertyExcludedRecurrenceRules = "excludedRecurrenceRules"
CalendarEventPropertyRecurrenceOverrides = "recurrenceOverrides"
CalendarEventPropertyExcluded = "excluded"
CalendarEventPropertyPriority = "priority"
CalendarEventPropertyFreeBusyStatus = "freeBusyStatus"
CalendarEventPropertyPrivacy = "privacy"
CalendarEventPropertyReplyTo = "replyTo"
CalendarEventPropertySentBy = "sentBy"
CalendarEventPropertyParticipants = "participants"
CalendarEventPropertyRequestStatus = "requestStatus"
CalendarEventPropertyUseDefaultAlerts = "useDefaultAlerts"
CalendarEventPropertyAlerts = "alerts"
CalendarEventPropertyLocalizations = "localizations"
CalendarEventPropertyTimeZone = "timeZone"
CalendarEventPropertyMayInviteSelf = "mayInviteSelf"
CalendarEventPropertyMayInviteOthers = "mayInviteOthers"
CalendarEventPropertyHideAttendees = "hideAttendees"
CalendarEventPropertyUid = "uid"
CalendarEventPropertyProdId = "prodId"
CalendarEventPropertyCreated = "created"
CalendarEventPropertyUpdated = "updated"
CalendarEventPropertyTitle = "title"
CalendarEventPropertyDescription = "description"
CalendarEventPropertyDescriptionContentType = "descriptionContentType"
CalendarEventPropertyLinks = "links"
CalendarEventPropertyLocale = "locale"
CalendarEventPropertyKeywords = "keywords"
CalendarEventPropertyCategories = "categories"
CalendarEventPropertyColor = "color"
CalendarEventPropertyTimeZones = "timeZones"
)
var CalendarEventProperties = []string{
CalendarEventPropertyId,
CalendarEventPropertyBaseEventId,
CalendarEventPropertyCalendarIds,
CalendarEventPropertyIsDraft,
CalendarEventPropertyIsOrigin,
CalendarEventPropertyUtcStart,
CalendarEventPropertyUtcEnd,
CalendarEventPropertyType,
CalendarEventPropertyStart,
CalendarEventPropertyDuration,
CalendarEventPropertyStatus,
CalendarEventPropertyRelatedTo,
CalendarEventPropertySequence,
CalendarEventPropertyShowWithoutTime,
CalendarEventPropertyLocations,
CalendarEventPropertyVirtualLocations,
CalendarEventPropertyRecurrenceId,
CalendarEventPropertyRecurrenceIdTimeZone,
CalendarEventPropertyRecurrenceRules,
CalendarEventPropertyExcludedRecurrenceRules,
CalendarEventPropertyRecurrenceOverrides,
CalendarEventPropertyExcluded,
CalendarEventPropertyPriority,
CalendarEventPropertyFreeBusyStatus,
CalendarEventPropertyPrivacy,
CalendarEventPropertyReplyTo,
CalendarEventPropertySentBy,
CalendarEventPropertyParticipants,
CalendarEventPropertyRequestStatus,
CalendarEventPropertyUseDefaultAlerts,
CalendarEventPropertyAlerts,
CalendarEventPropertyLocalizations,
CalendarEventPropertyTimeZone,
CalendarEventPropertyMayInviteSelf,
CalendarEventPropertyMayInviteOthers,
CalendarEventPropertyHideAttendees,
CalendarEventPropertyUid,
CalendarEventPropertyProdId,
CalendarEventPropertyCreated,
CalendarEventPropertyUpdated,
CalendarEventPropertyTitle,
CalendarEventPropertyDescription,
CalendarEventPropertyDescriptionContentType,
CalendarEventPropertyLinks,
CalendarEventPropertyLocale,
CalendarEventPropertyKeywords,
CalendarEventPropertyCategories,
CalendarEventPropertyColor,
CalendarEventPropertyTimeZones,
}
// A ParticipantIdentity stores information about a URI that represents the user within that account in an event’s participants.
type ParticipantIdentity struct {
// The id of the ParticipantIdentity (immutable; server-set).
Id string `json:"id"`
// The display name of the participant to use when adding this participant to an event, e.g. "Joe Bloggs".
//
// default:
Name string `json:"name,omitempty"`
// The URI that represents this participant for scheduling.
//
// This URI MAY also be the URI for one of the sendTo methods.
ScheduleId string `json:"scheduleId"`
// Represents methods by which the participant may receive invitations and updates to an event.
//
// The keys in the property value are the available methods and MUST only contain ASCII alphanumeric
// characters (`A-Za-z0-9`).
//
// The value is a URI for the method specified in the key.
SendTo map[string]string `json:"sendTo,omitempty"`
// This SHOULD be true for exactly one participant identity in any account, and MUST NOT be true for more
// than one participant identity within an account (server-set).
//
// The default identity should be used by clients whenever they need to choose an identity for the user
// within this account, and they do not have any other information on which to make a choice.
//
// For example, if creating a scheduled event in this account, the default identity may be automatically
// added as an owner. (But the client may ignore this if, for example, it has its own feature to allow
// users to choose which identity to use based on the invitees.)
IsDefault bool `json:"isDefault,omitzero"`
}
type CalendarAlert struct {
// This MUST be the string `CalendarAlert`.
Type TypeOfCalendarAlert `json:"@type,omitempty"`
// The account id for the calendar in which the alert triggered.
AccountId string `json:"accountId"`
// The CalendarEvent id for the alert that triggered.
//
// Note, for a recurring event this is the id of the base event, never a synthetic id for a particular instance.
CalendarEventId string `json:"calendarEventId"`
// The uid property of the CalendarEvent for the alert that triggered.
Uid string `json:"uid"`
// The `recurrenceId` for the instance of the event for which this alert is being
// triggered, or null if the event is not recurring.
RecurrenceId LocalDate `json:"recurrenceId,omitzero"`
// The id for the alert that triggered.
AlertId string `json:"alertId"`
}
type Person struct {
// The name of the person who made the change.
Name string `json:"name"`
// The email of the person who made the change, or null if no email is available.
Email string `json:"email,omitempty"`
// The id of the `Principal` corresponding to the person who made the change, if any.
//
// This will be null if the change was due to receving an iTIP message.
PrincipalId string `json:"principalId,omitempty"`
// The `scheduleId` URI of the person who made the change, if any.
//
// This will normally be set if the change was made due to receving an iTIP message.
ScheduleId string `json:"scheduleId,omitempty"`
}
type CalendarEventNotification struct {
// The id of the `CalendarEventNotification`.
Id string `json:"id"`
// The time this notification was created.
Created UTCDate `json:"created,omitzero"`
// Who made the change.
ChangedBy *Person `json:"person,omitempty"`
// Comment sent along with the change by the user that made it.
//
// (e.g. `COMMENT` property in an iTIP message), if any.
Comment string `json:"comment,omitempty"`
// `CalendarEventNotification` type.
//
// This MUST be one of
// !- `created`
// !- `updated`
// !- `destroyed`
Type CalendarEventNotificationTypeOption `json:"type"`
// The id of the CalendarEvent that this notification is about.
//
// If the change only affects a single instance of a recurring event, the server MAY set the
// `event` and `event`atch properties for just that instance; the `calendarEventId` MUST
// still be for the base event.
CalendarEventId string `json:"calendarEventId"`
// Is this event a draft? (created/updated only)
IsDraft bool `json:"isDraft,omitzero"`
// The data before the change (if updated or destroyed),
// or the data after creation (if created).
Event *jscalendar.Event `json:"event,omitempty"`
// A patch encoding the change between the data in the event property,
// and the data after the update (updated only).
EventPatch PatchObject `json:"eventPatch,omitempty"`
}
// Denotes the task list has a special purpose.
//
// This MUST be one of the following:
// !- `inbox`: This is the principal’s default task list;
// !- `trash`: This task list holds messages the user has discarded;
type TaskListRole string
const (
// This is the principal’s default task list.
TaskListRoleInbox = TaskListRole("inbox")
// This task list holds messages the user has discarded.
TaskListRoleTrash = TaskListRole("trash")
)
var (
DefaultWorkflowStatuses = []string{
"completed",
"failed",
"in-process",
"needs-action",
"cancelled",
"pending",
}
)
type TaskRights struct {
// The user may fetch the tasks in this task list.
MayReadItems bool `json:"mayReadItems"`
// The user may create, modify or destroy all tasks in this task list,
// or move tasks to or from this task list.
//
// If this is `true`, the `mayWriteOwn`, `mayUpdatePrivate` and `mayRSVP` properties
// MUST all also be `true`.
MayWriteAll bool `json:"mayWriteAll"`
// The user may create, modify or destroy a task on this task list if either they are
// the owner of the task (see below) or the task has no owner.
//
// This means the user may also transfer ownership by updating a task so they are no longer
// an owner.
MayWriteOwn bool `json:"mayWriteOwn"`
// The user may modify the following properties on all tasks in the task list, even
// if they would not otherwise have permission to modify that task.
//
// These properties MUST all be stored per-user, and changes do not affect any other user of the task list.
//
// The user may also modify the above on a per-occurrence basis for recurring tasks
// (updating the `recurrenceOverrides` property of the task to do so).
MayUpdatePrivate bool `json:"mayUpdatePrivate"`
// The user may modify the following properties of any `Participant` object that corresponds
// to one of the user’s `ParticipantIdentity` objects in the account, even if they would not
// otherwise have permission to modify that task
// !- `participationStatus`
// !- `participationComment`
// !- `expectReply`
//
// If the task has its `mayInviteSelf` property set to true, then the user may also add a new
// `Participant` to the task with a `sendTo` property that is the same as the `sendTo` property
// of one of the user’s `ParticipantIdentity` objects in the account.
// The `roles` property of the participant MUST only contain `attendee`.
//
// If the task has its `mayInviteOthers` property set to `true` and there is an existing
// `Participant` in the task corresponding to one of the user’s `ParticipantIdentity` objects
// in the account, then the user may also add new participants.
// The `roles` property of any new participant MUST only contain `attendee`.
//
// The user may also do all of the above on a per-occurrence basis for recurring tasks
// (updating the `recurrenceOverrides` property of the task to do so).
MayRSVP bool `json:"mayRSVP"`
// The user may modify sharing for this task list.
MayAdmin bool `json:"mayAdmin"`
// The user may delete the task list itself (server-set).
//
// This property MUST be false if the account to which this task list belongs has the `isReadOnly`
// property set to true.
MayDelete bool `json:"mayDelete"`
}
type TaskList struct {
// The id of the task list (immutable; server-set).
Id string `json:"id,omitempty"`
// Denotes the task list has a special purpose.
//
// This MUST be one of the following:
// !- `inbox`: This is the principal’s default task list;
// !- `trash`: This task list holds messages the user has discarded;
Role TaskListRole `json:"role,omitempty"`
// The user-visible name of the task list.
//
// This may be any UTF-8 string of at least 1 character in length and maximum 255 octets in size.
Name string `json:"name,omitempty"`
// An optional longer-form description of the task list, to provide context in shared environments
// where users need more than just the name.
Description string `json:"description,omitempty"`
// A color to be used when displaying tasks associated with the task list.
//
// If not null, the value MUST be a case-insensitive color name taken from the set of names defined
// in Section 4.3 of CSS Color Module Level 3 COLORS, or an RGB value in hexadecimal notation,
// as defined in Section 4.2.1 of CSS Color Module Level 3.
//
// The color SHOULD have sufficient contrast to be used as text on a white background.
Color string `json:"color,omitempty"`
// A map of keywords to the colors used when displaying the keywords associated to a task.
//
// The same considerations, as for `color` above, apply.
KeywordColors map[string]string `json:"keywordColors,omitempty"`
// A map of categories to the colors used when displaying the categories associated to a task.
//
// The same considerations, as for `color` above, apply.
CategoryColors map[string]string `json:"categoryColors,omitempty"`
// Defines the sort order of task lists when presented in the client’s UI, so it is consistent
// between devices.
//
// The number MUST be an integer in the range 0 ≤ sortOrder < 2^31.
//
// A task list with a lower order should be displayed before a list with a higher order in any list
// of task lists in the client’s UI.
//
// Task lists with equal order SHOULD be sorted in alphabetical order by name.
//
// The sorting should take into account locale-specific character order convention.
SortOrder uint `json:"sortOrder,omitzero"`
// Has the user indicated they wish to see this task list in their client?
//
// This SHOULD default to false for task lists in shared accounts the user has access to,
// and true for any new task list created by the user themselves.
//
// If false, the task list should only be displayed when the user explicitly
// requests it or to offer it for the user to subscribe to.
IsSubscribed bool `json:"isSubscribed,omitzero"`
// The time zone to use for tasks without a time zone when the server needs to resolve them
// into absolute time, e.g., for alerts or availability calculation.
//
// The value MUST be a time zone id from the IANA Time Zone Database TZDB.
//
// If null, the timeZone of the account’s associated Principal will be used.
//
// Clients SHOULD use this as the default for new tasks in this task list, if set.
TimeZone string `json:"timeZone,omitempty"`
// Defines the allowed values for `workflowStatus`.
//
// The default values are based on the values defined within [@!RFC8984], Section 5.2.5 and `pending`.
//
// `pending` indicates the task has been created and accepted, but it currently is on-hold.
//
// As naming and workflows differ between systems, mapping the status correctly to the present values
// of the `Task` can be challenging. In the most simple case, a task system may support merely two states - `done`
// and `not-done`.
//
// On the other hand, statuses and their semantic meaning can differ between systems or task lists (e.g. projects).
//
// In case of uncertainty, here are some recommendations for mapping commonly observed values that can help
// during implementation:
// !- `completed`: `done` (most simple case), `closed`, `verified`, …
// !- `in-process`: `in-progress`, `active`, `assigned`, …
// !- `needs-action`: `not-done` (most simple case), `not-started`, `new`, …
// !- `pending`: `waiting`, `deferred`, `on-hold`, `paused`, …
WorkflowStatuses []string `json:"workflowStatuses,omitempty"`
// A map of `Principal` id to rights for principals this task list is shared with.
//
// The principal to which this task list belongs MUST NOT be in this set.
//
// This is null if the task list is not shared with anyone.
//
// May be modified only if the user has the `mayAdmin` right.
//
// The account id for the principals may be found in the `urn:ietf:params:jmap:principals:owner` capability
// of the `Account` to which the task list belongs.
ShareWith map[string]TaskRights `json:"shareWith,omitempty"`
// The set of access rights the user has in relation to this `TaskList`.
//
// The user may fetch the task if they have the `mayReadItems` right on any task list the task is in.
//
// The user may remove a task from a task list (by modifying the task’s `taskListId` property) if the user has the
// appropriate permission for that task list.
//
// The user may make other changes to the task if they have the right to do so in all task list to which the task belongs.
MyRights *TaskRights `json:"myRights,omitempty"`
// A map of alert ids to `Alert` objects (see [@!RFC8984], Section 4.5.2) to apply for tasks
// where `showWithoutTime` is `false` and `useDefaultAlerts` is `true`.
//
// Ids MUST be unique across all default alerts in the account, including those in other task
// lists; a UUID is recommended.
//
// If omitted on creation, the default is server dependent.
//
// For example, servers may choose to always default to null, or may copy the alerts from the default task list.
DefaultAlertsWithTime map[string]jscalendar.Alert `json:"defaultAlertsWithTime,omitempty"`
// A map of alert ids to `Alert` objects (see [@!RFC8984], Section 4.5.2) to apply for tasks
// where `showWithoutTime` is `true` and `useDefaultAlerts` is `true`.
//
// Ids MUST be unique across all default alerts in the account, including those in other task
// lists; a UUID is recommended.
//
// If omitted on creation, the default is server dependent. For example, servers may choose to always
// default to `null`, or may copy the alerts from the default task list.
DefaultAlertsWithoutTime map[string]jscalendar.Alert `json:"defaultAlertsWithoutTime,omitempty"`
}
type TypeOfChecklist string
type TypeOfCheckItem string
type TypeOfTaskPerson string
type TypeOfComment string
type TaskNotificationTypeOption string
const ChecklistType = TypeOfChecklist("Checklist")
const CheckItemType = TypeOfCheckItem("CheckItem")
const TaskPersonType = TypeOfTaskPerson("Person")
const CommentType = TypeOfComment("Comment")
const TaskNotificationTypeOptionCreated = TaskNotificationTypeOption("created")
const TaskNotificationTypeOptionUpdated = TaskNotificationTypeOption("updated")
const TaskNotificationTypeOptionDestroyed = TaskNotificationTypeOption("destroyed")
// The Person object has the following properties of which either principalId or uri MUST be defined.
type TaskPerson struct {
// Specifies the type of this object, this MUST be `Person`.
Type TypeOfTaskPerson `json:"@type,omitempty"`
// The name of the person.
Name string `json:"name,omitempty"`
// A URI value that identifies the person.
//
// This SHOULD be the `scheduleId` of the participant that this item was assigned to.
Uri string `json:"uri,omitempty"`
// The id of the Principal corresponding to the person, if any.
PrincipalId string `json:"principalId,omitempty"`
}
type Comment struct {
// Specifies the type of this object, this MUST be `Comment`.
Type TypeOfComment `json:"@type,omitempty"`
// The free text value of this comment.
Message string `json:"message"`
// The date and time when this note was created.
Created UTCDate `json:"created,omitzero"`
// The date and time when this note was updated.
Updated UTCDate `json:"updated,omitzero"`
// The author of this comment.
Author *TaskPerson `json:"author,omitempty"`
}
type CheckItem struct {
// Specifies the type of this object, this MUST be `CheckItem`.
Type TypeOfCheckItem `json:"@type,omitempty"`
// Title of the item.
Title string `json:"title,omitempty"`
// Defines the sort order of `CheckItem` when presented in the client’s UI.
//
// The number MUST be an integer in the range 0 <= sortOrder < 2^31.
//
// An item with a lower order should be displayed before an item with a higher order.
//
// Items with equal order SHOULD be sorted in alphabetical order by name.
//
// The sorting should take into account locale-specific character order convention.
SortOrder uint `json:"sortOrder,omitzero"`
// The date and time when this item was updated.
Updated UTCDate `json:"updated,omitzero"`
IsComplete bool `json:"isComplete,omitzero"`
// The person that this item is assigned to.
//
// The `Person` object has the following properties of which either `principalId` or `uri`
// MUST be defined.
Assignee *TaskPerson `json:"assignee,omitempty"`
// Free-text comments associated with this task.
Comments map[string]Comment `json:"comments,omitempty"`
}
type Checklist struct {
// Specifies the type of this object, this MUST be `Checklist`.
Type TypeOfChecklist `json:"@type,omitempty"`
// Title of the list.
Title string `json:"title,omitempty"`
// The items of the check list.
CheckItems []CheckItem `json:"checkItems,omitempty"`
}
// A `Task` object contains information about a task.
//
// It is a JSTask object, as defined in [@!RFC8984]. However, as use-cases of task systems vary, this
// Section defines relevant parts of the JSTask object to implement the core task capability as well
// as several extensions to it.
//
// Only the core capability MUST be implemented by any task system.
//
// Implementers can choose the extensions that fit their own use case.
//
// For example, the recurrence extension allows having a `Task` object represent a series of recurring `Task`s.
type Task struct {
// The id of the Task.
//
// This property is immutable.
//
// The id uniquely identifies a JSTask with a particular `uid` and `recurrenceId` within a particular account.
Id string `json:"id"`
// The `TaskList` id this task belongs to.
//
// A task MUST belong to exactly one `TaskList` at all times (until it is destroyed).
TaskListId string `json:"taskListId"`
// If `true`, this task is to be considered a draft.
//
// The server will not send any push notifications for alerts.
//
// This may only be set to true upon creation.
//
// Once set to `false`, the value cannot be updated to `true`.
//
// This property MUST NOT appear in `recurrenceOverrides`.
IsDraft bool `json:"isDraft,omitzero"`
UtcStart UTCDate `json:"utcStart,omitzero"`
UtcDue UTCDate `json:"utcDue,omitzero"`
SortOrder uint `json:"sortOrder,omitzero"`
WorkflowStatus string `json:"workflowStatus,omitempty"`
jscalendar.Task
// This specifies the estimated amount of work the task takes to complete.
//
// In Agile software development or Scrum, it is known as complexity or story points.
//
// The number has no actual unit, but a larger number means more work.
EstimatedWork uint `json:"estimatedWork,omitzero"`
// This specifies the impact or severity of the task, but does not say anything
// about the actual prioritization.
//
// Some examples are: `minor`, `trivial`, `major` or `block`.
//
// Usually, the priority of a task is based upon its impact and urgency.
Impact string `json:"impact,omitempty"`
// A map of Checklist IDs to Checklist objects, containing checklist items.
Checklists map[string]Checklist `json:"checklists,omitempty"`
// This is only defined if the id property is a synthetic id, generated by the server
// to represent a particular instance of a recurring Task (immutable; server-set).
//
// This property gives the id of the “real” Task this was generated from.
BaseTaskId string `json:"baseTaskId,omitempty"`
// Is this the authoritative source for this task (i.e., does it control scheduling
// for this task; the task has not been added as a result of an invitation from another
// task management system)?
//
// This is `true` if, and only if:
// !- the task’s “replyTo” property is null; or
// !- the account will receive messages sent to at least one of the methods specified in
// the `replyTo` property of the task.
IsOrigin bool `json:"isOrigin,omitzero"`
// If true, any user that has access to the task may add themselves to it as a participant
// with the `attendee` role.
//
// This property MUST NOT be altered in the `recurrenceOverrides`; it may only be set on the master object.
//
// This indicates the task will accept “party crasher” RSVPs via iTIP, subject to any other domain-specific
// restrictions, and users may add themselves to the task via JMAP as long as they have the `mayRSVP`
// permission for the task list.
//
// default: false
MayInviteSelf bool `json:"mayInviteSelf,omitzero"`
// If true, any current participant with the `attendee` role may add new participants with
// the `attendee` role to the task.
//
// This property MUST NOT be altered in the `recurrenceOverrides`; it may only be set on the master object.
//
// default: false
MayInviteOthers bool `json:"mayInviteOthers,omitzero"`
// If true, only the owners of the task may see the full set of participants.
//
// Other sharees of the task may only see the owners and themselves.
//
// This property MUST NOT be altered in the `recurrenceOverrides`; it may only be set on the master object.
HideAttendees bool `json:"hideAttendees,omitzero"`
}
// The `TaskNotification` data type records changes made by external entities to tasks in task lists
// the user is subscribed to.
//
// Notifications are stored in the same `Account` as the `Task` that was changed.
type TaskNotification struct {
// The id of the `TaskNotification`.
Id string `json:"id"`
// The time this notification was created.
Created UTCDate `json:"created,omitzero"`
// Who made the change.
ChangedBy *TaskPerson `json:"changedBy,omitempty"`
// Comment sent along with the change by the user that made it.
//
// (e.g. `COMMENT` property in an iTIP message), if any.
Comment string `json:"comment,omitempty"`
// This MUST be one of
// !- `created`
// !- `updated`
// !- `destroyed`
Type TaskNotificationTypeOption `json:"type"`
// The id of the Task that this notification is about.
TaskId string `json:"taskId"`
// Is this task a draft? (created/updated only)
IsDraft bool `json:"isDraft,omitzero"`
// The data before the change (if updated or destroyed), or the data after creation (if created).
Task *jscalendar.Task `json:"task,omitempty"`
// A patch encoding the change between the data in the task property, and the data after the update updated only).
TaskPatch PatchObject `json:"taskPatch,omitempty"`
}
// A Principal represents an individual, group, location (e.g. a room), resource (e.g. a projector) or other entity
// in a collaborative environment.
//
// Sharing in JMAP is generally configured by assigning rights to certain data within an account to other principals,
// for example a user may assign permission to read their calendar to a principal representing another user, or their team.
//
// In a shared environment such as a workplace, a user may have access to a large number of principals.
//
// In most systems the user will have access to a single `Account` containing `Principal` objects, but they may
// have access to multiple if, for example, aggregating data from different places.
type Principal struct {
// The id of the principal.
Id string `json:"id"`
// `Principal` type.
//
// This MUST be one of the following values:
// !- `individual`: This represents a single person.
// !- `group`: This represents a group of people.
// !- `resource`: This represents some resource, e.g. a projector.
// !- `location`: This represents a location.
// !- `other`: This represents some other undefined principal.
Type PrincipalTypeOption `json:"type"`
// The name of the principal, e.g. `"Jane Doe"`, or `"Room 4B"`.
Name string `json:"name"`
// A longer description of the principal, for example details about the
// facilities of a resource, or null if no description available.
Description string `json:"description,omitempty"`
// An email address for the principal, or null if no email is available.
Email string `json:"email,omitempty"`
// The time zone for this principal, if known.
//
// If not null, the value MUST be a time zone id from the IANA Time Zone Database TZDB.
TimeZone string `json:"timeZone,omitempty"`
// A map of JMAP capability URIs to domain specific information about the principal in relation
// to that capability, as defined in the document that registered the capability.
Capabilities map[string]any `json:"capabilities,omitempty"`
// A map of account id to `Account` object for each JMAP Account containing data for
// this principal that the user has access to, or null if none.
Accounts map[string]Account `json:"accounts,omitempty"`
}
type ShareChangePerson struct {
// The name of the person who made the change.
Name string `json:"name"`
// The email of the person who made the change, or null if no email is available.
Email string `json:"email,omitempty"`
// The id of the Principal corresponding to the person who made the change, or null if no associated principal.
PrincipalId string `json:"principalId,omitempty"`
}
type ShareNotification struct {
// The id of the `ShareNotification`.
Id string `json:"id"`
// The time this notification was created.
Created UTCDate `json:"created,omitzero"`
// Who made the change.
ChangedBy ShareChangePerson `json:"changedBy"`
// The name of the data type for the object whose permissions have changed, e.g. `Calendar` or `Mailbox`.
ObjectType ObjectType `json:"objectType"`
// The id of the account where this object exists.
ObjectAccountId string `json:"objectAccountId"`
// The id of the object that this notification is about.
ObjectId string `json:"objectId"`
// The name of the object at the time the notification was made.
Name string `json:"name"`
// The `myRights` property of the object for the user before the change.
OldRights map[string]bool `json:"oldRights,omitempty"`
// The `myRights` property of the object for the user after the change.
NewRights map[string]bool `json:"newRights,omitempty"`
}
// TODO unused
type Shareable struct {
// Has the user indicated they wish to see this data?
//
// The initial value for this when data is shared by another user is implementation dependent,
// although data types may give advice on appropriate defaults.
IsSubscribed bool `json:"isSubscribed,omitzero"`
// The set of permissions the user currently has.
//
// Appropriate permissions are domain specific and must be defined per data type.
MyRights map[string]bool `json:"myRights,omitempty"`
// A map of principal id to rights to give that principal, or null if not shared with anyone.
//
// The account id for the principal id can be found in the capabilities of the `Account` this object is in.
//
// Users with appropriate permission may set this property to modify who the data is shared with.
//
// The principal that owns the account this data is in MUST NOT be in the set of sharees; their rights are implicit.
ShareWith map[string]map[string]bool `json:"shareWith,omitempty"`
}
// The Quota is an object that displays the limit set to an account usage.
//
// It then shows as well the current usage in regard to that limit.
type Quota struct {
// The unique identifier for this object.
Id string `json:"id"`
// The resource type of the quota.
ResourceType ResourceType `json:"resourceType"`
// The current usage of the defined quota, using the `resourceType` defined as unit of measure.
//
// Computation of this value is handled by the server.
Used uint `json:"used"`
// The hard limit set by this quota, using the `resourceType` defined as unit of measure.
//
// Objects in scope may not be created or updated if this limit is reached.
HardLimit uint `json:"hardLimit"`
// The Scope data type is used to represent the entities the quota applies to.
//
// It is defined as a "String" with values from the following set:
// !- `account`: The quota information applies to just the client's account.
// !- `domain`: The quota information applies to all accounts sharing this domain.
// !- `global`: The quota information applies to all accounts belonging to the server.
Scope Scope `json:"scope"`
// The name of the quota.
//
// Useful for managing quotas and using queries for searching.
Name string `json:"name"`
// A list of all the type names as defined in the "JMAP Types Names" registry
// (e.g., `Email`, `Calendar`, etc.) to which this quota applies.
//
// This allows the quotas to be assigned to distinct or shared data types.
//
// The server MUST filter out any types for which the client did not request the associated capability
// in the `using` section of the request.
//
// Further, the server MUST NOT return Quota objects for which there are no types recognized by the client.
Types []ObjectType `json:"types,omitempty"`
// The warn limit set by this quota, using the `resourceType` defined as unit of measure.
//
// It can be used to send a warning to an entity about to reach the hard limit soon, but with no
// action taken yet.
//
// If set, it SHOULD be lower than the `softLimit` (if present and different from null) and the `hardLimit`.
WarnLimit uint `json:"warnLimit,omitzero"`
// The soft limit set by this quota, using the `resourceType` defined as unit of measure.
//
// It can be used to still allow some operations but refuse some others.
//
// What is allowed or not is up to the server.
//
// For example, it could be used for blocking outgoing events of an entity (sending emails, creating
// calendar events, etc.) while still receiving incoming events (receiving emails, receiving calendars
// events, etc.).
//
// If set, it SHOULD be higher than the `warnLimit` (if present and different from null) but lower
// than the `hardLimit`.
SoftLimit uint `json:"softLimit,omitzero"`
// Arbitrary, free, human-readable description of this quota.
//
// It might be used to explain where the different limits come from and explain the entities and data
// types this quota applies to.
//
// The description MUST be encoded in UTF-8 [RFC3629] as described in [RFC8620], Section 1.5, and
// selected based on an `Accept-Language` header in the request (as defined in [RFC9110], Section 12.5.4)
// or out-of-band information about the user's language or locale.
Description string `json:"description,omitempty"`
}
// See [RFC8098] for the exact meaning of these different fields.
//
// These fields are defined as case insensitive in [RFC8098] but are case sensitive in this RFC
// and MUST be converted to lowercase by "MDN/parse".
type Disposition struct {
ActionMode ActionMode `json:"actionMode,omitempty"`
SendingMode SendingMode `json:"sendingMode,omitempty"`
Type DispositionTypeOption `json:"type,omitempty"`
}
// Message Disposition Notifications (MDNs) are defined in [RFC8098] and are used as "read receipts",
// "acknowledgements", or "receipt notifications".
//
// A client can come across MDNs in different ways:
// 1. When receiving an email message, an MDN can be sent to the sender. This specification defines an `MDN/send` method to cover this case.
// 2. When sending an email message, an MDN can be requested. This must be done with the help of a header field, as already specified by [RFC8098];
// the header field can already be handled by guidance in [RFC8621].
// 3. When receiving an MDN, the MDN could be related to an existing sent message. This is already covered by [RFC8621] in the
// `EmailSubmission` object. A client might want to display detailed information about a received MDN.
// This specification defines an `MDN/parse` method to cover this case.
type MDN struct {
// The `Email` id of the received message to which this MDN is related.
//
// This property MUST NOT be null for `MDN/send` but MAY be null in the response from the `MDN/parse` method.
ForEmailId string `json:"forEmailId,omitempty"`
// The subject used as `Subject` header field for this MDN.
Subject string `json:"subject,omitempty"`
// The human-readable part of the MDN, as plain text.
TextBody string `json:"textBody,omitempty"`
// If true, the content of the original message will appear in the third component of the `multipart/report` generated
// for the MDN.
//
// See [RFC8098] for details and security considerations.
IncludeOriginalMessage bool `json:"includeOriginalMessage,omitzero"`
// The name of the Mail User Agent (MUA) creating this MDN.
//
// It is used to build the MDN report part of the MDN.
//
// Note that a null value may have better privacy properties.
ReportingUA string `json:"reportingUA,omitempty"`
// The object containing the diverse MDN disposition options.
Disposition Disposition `json:"disposition"`
// The name of the gateway or Message Transfer Agent (MTA) that translated a foreign (non-Internet)
// message disposition notification into this MDN (server-set).
MdnGateway string `json:"mdnGateway,omitempty"`
// The original recipient address as specified by the sender of the message for which the MDN is being issued (server-set).
OriginalRecipient string `json:"originalRecipient,omitempty"`
// The recipient for which the MDN is being issued.
//
// If set, it overrides the value that would be calculated by the server from the `Identity` defined
// in the `MDN/send` method, unless explicitly set by the client.
FinalRecipient string `json:"finalRecipient,omitempty"`
// The `Message-ID` header field [RFC5322] (not the JMAP id) of the message for which the MDN is being issued.
OriginalMessageId string `json:"originalMessageId,omitempty"`
// Additional information in the form of text messages when the `error` disposition modifier appears.
Error []string `json:"error,omitempty"`
// The object where keys are extension-field names, and values are extension-field values (see [RFC8098], Section 3.3).
ExtensionFields map[string]string `json:"extensionFields,omitempty"`
}
type SendMDN struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// The id of the `Identity` to associate with these MDNs.
//
// The server will use this identity to define the sender of the MDNs and to set the `finalRecipient` field.
IdentityId string `json:"identityId"`
// A map of the creation id (client specified) to MDN objects.
Send map[string]MDN `json:"send,omitempty"`
// A map of the id to an object containing properties to update on the `Email` object referenced by the `MDN/send`
// if the sending succeeds.
//
// This will always be a backward reference to the creation id.
OnSuccessUpdateEmail map[string]PatchObject `json:"onSuccessUpdateEmail,omitempty"`
}
type QuotaGetCommand struct {
AccountId string `json:"accountId"`
Ids []string `json:"ids,omitempty"`
}
type QuotaGetResponse struct {
AccountId string `json:"accountId"`
State State `json:"state,omitempty"`
List []Quota `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
}
type AddressBookGetCommand struct {
AccountId string `json:"accountId"`
Ids []string `json:"ids,omitempty"`
}
type AddressBookGetResponse struct {
AccountId string `json:"accountId"`
State State `json:"state,omitempty"`
List []AddressBook `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
}
type ContactCardComparator struct {
// The name of the property on the objects to compare.
Property string `json:"property,omitempty"`
// If true, sort in ascending order.
//
// Optional; default value: true.
//
// If false, reverse the comparator’s results to sort in descending order.
IsAscending bool `json:"isAscending,omitempty"`
// The identifier, as registered in the collation registry defined in [RFC4790],
// for the algorithm to use when comparing the order of strings.
//
// Optional; default is server dependent.
//
// The algorithms the server supports are advertised in the capabilities object returned
// with the Session object.
//
// [RFC4790]: https://www.rfc-editor.org/rfc/rfc4790.html
Collation string `json:"collation,omitempty"`
// ContactCard-specific: The “created” date on the ContactCard.
Created time.Time `json:"created,omitzero"`
// ContactCard-specific: The "updated” date on the ContactCard.
Updated time.Time `json:"updated,omitzero"`
}
type ContactCardFilterElement interface {
_isAContactCardFilterElement() // marker method
IsNotEmpty() bool
}
type ContactCardFilterCondition struct {
// An AddressBook id.
//
// A card must be in this address book to match the condition.
InAddressBook string `json:"inAddressBook,omitempty"`
// A card must have this string exactly as its uid to match.
Uid string `json:"uid,omitempty"`
// A card must have a “members” property that contains this string as one of the uids in the set to match.
HasMember string `json:"hasMember,omitempty"`
// A card must have a type property that equals this string exactly to match.
Kind string `json:"kind,omitempty"`
// The “created” date-time of the ContactCard must be before this date-time to match the condition.
CreatedBefore UTCDate `json:"createdBefore,omitzero"`
// The “created” date-time of the ContactCard must be the same or after this date-time to match the condition.
CreatedAfter UTCDate `json:"createdAfter,omitzero"`
// The “updated” date-time of the ContactCard must be before this date-time to match the condition.
UpdatedBefore UTCDate `json:"updatedBefore,omitzero"`
// The “updated” date-time of the ContactCard must be the same or after this date-time to match the condition.
UpdatedAfter UTCDate `json:"updatedAfter,omitzero"`
// A card matches this condition if the text matches with text in the card.
Text string `json:"text,omitempty"`
// A card matches this condition if the value of any NameComponent in the “name” property, or the
// “full” property in the “name” property of the card matches the value.
Name string `json:"name,omitempty"`
// A card matches this condition if the value of a NameComponent with kind “given” inside the “name” property of
// the card matches the value.
NameGiven string `json:"name/given,omitempty"`
// A card matches this condition if the value of a NameComponent with kind “surname” inside the “name” property
// of the card matches the value.
NameSurname string `json:"name/surname,omitempty"`
// A card matches this condition if the value of a NameComponent with kind “surname2” inside the “name” property
// of the card matches the value.
NameSurname2 string `json:"name/surname2,omitempty"`
// A card matches this condition if the “name” of any NickName in the “nickNames” property of the card matches the value.
NickName string `json:"nickName,omitempty"`
// A card matches this condition if the “name” of any Organization in the “organizations” property of the card
// matches the value.
Organization string `json:"organization,omitempty"`
// A card matches this condition if the “address” or “label” of any EmailAddress in the “emails” property of the
// card matches the value.
Email string `json:"email,omitempty"`
// A card matches this condition if the “number” or “label” of any Phone in the “phones” property of the card
// matches the value.
Phone string `json:"phone,omitempty"`
// A card matches this condition if the “service”, “uri”, “user”, or “label” of any OnlineService in the
// “onlineServices” property of the card matches the value.
OnlineService string `json:"onlineService,omitempty"`
// A card matches this condition if the value of any StreetComponent in the “street” property, or the “locality”,
// “region”, “country”, or “postcode” property in any Address in the “addresses” property of the card matches the value.
Address string `json:"address,omitempty"`
// A card matches this condition if the “note” of any Note in the “notes” property of the card matches the value.
Note string `json:"note,omitempty"`
}
func (f ContactCardFilterCondition) _isAContactCardFilterElement() {
}
func (f ContactCardFilterCondition) IsNotEmpty() bool {
if len(f.InAddressBook) != 0 {
return true
}
if f.Uid != "" {
return true
}
if f.HasMember != "" {
return true
}
if f.Kind != "" {
return true
}
if f.CreatedBefore != "" {
return true
}
if f.CreatedAfter != "" {
return true
}
if f.UpdatedBefore != "" {
return true
}
if f.UpdatedAfter != "" {
return true
}
if f.Text != "" {
return true
}
if f.Name != "" {
return true
}
if f.NameGiven != "" {
return true
}
if f.NameSurname != "" {
return true
}
if f.NameSurname2 != "" {
return true
}
if f.NickName != "" {
return true
}
if f.Organization != "" {
return true
}
if f.Email != "" {
return true
}
if f.Phone != "" {
return true
}
if f.OnlineService != "" {
return true
}
if f.Address != "" {
return true
}
if f.Note != "" {
return true
}
return false
}
var _ ContactCardFilterElement = &ContactCardFilterCondition{}
type ContactCardFilterOperator struct {
Operator FilterOperatorTerm `json:"operator"`
Conditions []ContactCardFilterElement `json:"conditions,omitempty"`
}
func (o ContactCardFilterOperator) _isAContactCardFilterElement() {
}
func (o ContactCardFilterOperator) IsNotEmpty() bool {
return len(o.Conditions) > 0
}
var _ ContactCardFilterElement = &ContactCardFilterOperator{}
type ContactCardQueryCommand struct {
AccountId string `json:"accountId"`
Filter ContactCardFilterElement `json:"filter,omitempty"`
Sort []ContactCardComparator `json:"sort,omitempty"`
// The zero-based index of the first id in the full list of results to return.
//
// If a negative value is given, it is an offset from the end of the list.
// Specifically, the negative value MUST be added to the total number of results given
// the filter, and if still negative, it’s clamped to 0. This is now the zero-based
// index of the first id to return.
//
// If the index is greater than or equal to the total number of objects in the results
// list, then the ids array in the response will be empty, but this is not an error.
Position uint `json:"position,omitempty"`
// An Email id.
//
// If supplied, the position argument is ignored.
// The index of this id in the results will be used in combination with the anchorOffset
// argument to determine the index of the first result to return.
Anchor string `json:"anchor,omitempty"`
// The index of the first result to return relative to the index of the anchor,
// if an anchor is given.
//
// Default: 0.
//
// This MAY be negative.
//
// For example, -1 means the Email immediately preceding the anchor is the first result in
// the list returned.
AnchorOffset int `json:"anchorOffset,omitzero"`
// The maximum number of results to return.
//
// If null, no limit presumed.
// The server MAY choose to enforce a maximum limit argument.
// In this case, if a greater value is given (or if it is null), the limit is clamped
// to the maximum; the new limit is returned with the response so the client is aware.
//
// If a negative value is given, the call MUST be rejected with an invalidArguments error.
Limit uint `json:"limit,omitempty"`
// Does the client wish to know the total number of results in the query?
//
// This may be slow and expensive for servers to calculate, particularly with complex filters,
// so clients should take care to only request the total when needed.
CalculateTotal bool `json:"calculateTotal,omitempty"`
}
type ContactCardQueryResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A string encoding the current state of the query on the server.
//
// This string MUST change if the results of the query (i.e., the matching ids and their sort order) have changed.
// The queryState string MAY change if something has changed on the server, which means the results may have changed
// but the server doesn’t know for sure.
//
// The queryState string only represents the ordered list of ids that match the particular query (including its sort/filter).
// There is no requirement for it to change if a property on an object matching the query changes but the query results are unaffected
// (indeed, it is more efficient if the queryState string does not change in this case).
//
// The queryState string only has meaning when compared to future responses to a query with the same type/sort/filter or when used with
// /queryChanges to fetch changes.
//
// Should a client receive back a response with a different queryState string to a previous call, it MUST either throw away the currently
// cached query and fetch it again (note, this does not require fetching the records again, just the list of ids) or call
// Email/queryChanges to get the difference.
QueryState State `json:"queryState"`
// This is true if the server supports calling ContactCard/queryChanges with these filter/sort parameters.
//
// Note, this does not guarantee that the ContactCard/queryChanges call will succeed, as it may only be possible for a limited time
// afterwards due to server internal implementation details.
CanCalculateChanges bool `json:"canCalculateChanges"`
// The zero-based index of the first result in the ids array within the complete list of query results.
Position uint `json:"position"`
// The list of ids for each ContactCard in the query results, starting at the index given by the position argument of this
// response and continuing until it hits the end of the results or reaches the limit number of ids.
//
// If position is >= total, this MUST be the empty list.
Ids []string `json:"ids"`
// The total number of ContactCards in the results (given the filter).
//
// Only if requested.
//
// This argument MUST be omitted if the calculateTotal request argument is not true.
Total uint `json:"total,omitempty,omitzero"`
// The limit enforced by the server on the maximum number of results to return (if set by the server).
//
// This is only returned if the server set a limit or used a different limit than that given in the request.
Limit uint `json:"limit,omitempty,omitzero"`
}
type ContactCardGetCommand struct {
// The ids of the ContactCard objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that
// data type and the number of records does not exceed the maxObjectsInGet limit.
Ids []string `json:"ids,omitempty"`
// The id of the account to use.
AccountId string `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each ContactCard object.
//
// The id property of the object is always returned, even if not explicitly requested.
//
// If an invalid property is requested, the call MUST be rejected with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
}
type ContactCardGetRefCommand struct {
// The ids of the ContactCard objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that
// data type and the number of records does not exceed the maxObjectsInGet limit.
IdsRef *ResultReference `json:"#ids,omitempty"`
// The id of the account to use.
AccountId string `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each ContactCard object.
//
// The id property of the object is always returned, even if not explicitly requested.
//
// If an invalid property is requested, the call MUST be rejected with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
}
type ContactCardGetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type
// in the account (not just the objects returned in this call).
//
// If the data changes, this string MUST change.
// If the Email data is unchanged, servers SHOULD return the same state string on subsequent requests for this data type.
State State `json:"state"`
// An array of the ContactCard objects requested.
//
// This is the empty array if no objects were found or if the ids argument passed in was also an empty array.
//
// The results MAY be in a different order to the ids in the request arguments.
//
// If an identical id is included more than once in the request, the server MUST only include it once in either
// the list or the notFound argument of the response.
List []jscontact.ContactCard `json:"list"`
// This array contains the ids passed to the method for records that do not exist.
//
// The array is empty if all requested ids were found or if the ids argument passed in was either null or an empty array.
NotFound []any `json:"notFound"`
}
type ContactCardUpdate map[string]any
type ContactCardSetCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// This is a state string as returned by the `ContactCard/get` method.
//
// If supplied, the string must match the current state; otherwise, the method will be aborted and a
// `stateMismatch` error returned.
//
// If null, any changes will be applied to the current state.
IfInState string `json:"ifInState,omitempty"`
// A map of a creation id (a temporary id set by the client) to ContactCard objects,
// or null if no objects are to be created.
//
// The ContactCard object type definition may define default values for properties.
//
// Any such property may be omitted by the client.
//
// The client MUST omit any properties that may only be set by the server.
Create map[string]jscontact.ContactCard `json:"create,omitempty"`
// A map of an id to a `Patch` object to apply to the current Email object with that id,
// or null if no objects are to be updated.
//
// A `PatchObject` is of type `String[*]` and represents an unordered set of patches.
//
// The keys are a path in JSON Pointer Format [@!RFC6901], with an implicit leading `/` (i.e., prefix each key
// with `/` before applying the JSON Pointer evaluation algorithm).
//
// All paths MUST also conform to the following restrictions; if there is any violation, the update
// MUST be rejected with an `invalidPatch` error:
// !- The pointer MUST NOT reference inside an array (i.e., you MUST NOT insert/delete from an array; the array MUST be replaced in its entirety instead).
// !- All parts prior to the last (i.e., the value after the final slash) MUST already exist on the object being patched.
// !- There MUST NOT be two patches in the `PatchObject` where the pointer of one is the prefix of the pointer of the other, e.g., `"alerts/1/offset"` and `"alerts"`.
//
// The value associated with each pointer determines how to apply that patch:
// !- If null, set to the default value if specified for this property; otherwise, remove the property from the patched object. If the key is not present in the parent, this a no-op.
// !- Anything else: The value to set for this property (this may be a replacement or addition to the object being patched).
//
// Any server-set properties MAY be included in the patch if their value is identical to the current server value
// (before applying the patches to the object). Otherwise, the update MUST be rejected with an `invalidProperties` `SetError`.
//
// This patch definition is designed such that an entire Email object is also a valid `PatchObject`.
//
// The client may choose to optimise network usage by just sending the diff or may send the whole object; the server
// processes it the same either way.
Update map[string]ContactCardUpdate `json:"update,omitempty"`
// A list of ids for ContactCard objects to permanently delete, or null if no objects are to be destroyed.
Destroy []string `json:"destroy,omitempty"`
}
type ContactCardSetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// The state string that would have been returned by ContactCard/get before making the
// requested changes, or null if the server doesn’t know what the previous state
// string was.
OldState State `json:"oldState,omitempty"`
// The state string that will now be returned by Email/get.
NewState State `json:"newState"`
// A map of the creation id to an object containing any properties of the created Email object
// that were not sent by the client.
//
// This includes all server-set properties (such as the id in most object types) and any properties
// that were omitted by the client and thus set to a default by the server.
//
// This argument is null if no ContactCard objects were successfully created.
Created map[string]*jscontact.ContactCard `json:"created,omitempty"`
// The keys in this map are the ids of all Emails that were successfully updated.
//
// The value for each id is an ContactCard object containing any property that changed in a way not
// explicitly requested by the PatchObject sent to the server, or null if none.
//
// This lets the client know of any changes to server-set or computed properties.
//
// This argument is null if no ContactCard objects were successfully updated.
Updated map[string]*jscontact.ContactCard `json:"updated,omitempty"`
// A list of ContactCard ids for records that were successfully destroyed, or null if none.
Destroyed []string `json:"destroyed,omitempty"`
// A map of the creation id to a SetError object for each record that failed to be created,
// or null if all successful.
NotCreated map[string]SetError `json:"notCreated,omitempty"`
// A map of the ContactCard id to a SetError object for each record that failed to be updated,
// or null if all successful.
NotUpdated map[string]SetError `json:"notUpdated,omitempty"`
// A map of the ContactCard id to a SetError object for each record that failed to be destroyed,
// or null if all successful.
NotDestroyed map[string]SetError `json:"notDestroyed,omitempty"`
}
type CalendarEventParseCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// The ids of the blobs to parse
BlobIds []string `json:"blobIds,omitempty"`
// If supplied, only the properties listed in the array are returned for each CalendarEvent object.
//
// If omitted, defaults to all the properties.
Properties []string `json:"properties,omitempty"`
}
type CalendarEventParseResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A map of blob ids to parsed CalendarEvent objects representations for each successfully
// parsed blob, or null if none.
Parsed map[string][]CalendarEvent `json:"parsed,omitempty"`
// A list of blob ids given that could not be found, or null if none.
NotFound []string `json:"notFound,omitempty"`
// A list of blob ids given that corresponded to blobs that could not be parsed as
// CalendarEvents, or null if none.
NotParsable []string `json:"notParsable,omitempty"`
}
type CalendarGetCommand struct {
AccountId string `json:"accountId"`
Ids []string `json:"ids,omitempty"`
}
type CalendarGetResponse struct {
AccountId string `json:"accountId"`
State State `json:"state,omitempty"`
List []Calendar `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
}
type CalendarEventComparator struct {
// The name of the property on the objects to compare.
Property string `json:"property,omitempty"`
// If true, sort in ascending order.
//
// Optional; default value: true.
//
// If false, reverse the comparator’s results to sort in descending order.
IsAscending bool `json:"isAscending,omitempty"`
// The identifier, as registered in the collation registry defined in [RFC4790],
// for the algorithm to use when comparing the order of strings.
//
// Optional; default is server dependent.
//
// The algorithms the server supports are advertised in the capabilities object returned
// with the Session object.
//
// [RFC4790]: https://www.rfc-editor.org/rfc/rfc4790.html
Collation string `json:"collation,omitempty"`
// CalendarEvent-specific: If true, the server will expand any recurring event.
//
// If true, the filter MUST be just a FilterCondition (not a FilterOperator) and MUST include both
// a “before” and “after” property. This ensures the server is not asked to return an infinite number of results.
// default: false
ExpandRecurrences bool `json:"expandRecurrences,omitzero"`
// CalendarEvent-specific: The time zone for before/after filter conditions.
// default: “Etc/UTC”
TimeZone string `json:"timeZone,omitempty"`
}
type CalendarEventFilterElement interface {
_isACalendarEventFilterElement() // marker method
IsNotEmpty() bool
}
type CalendarEventFilterCondition struct {
// A calendar id.
// An event must be in this calendar to match the condition.
InCalendar string `json:"inCalendar,omitempty"`
// The end of the event, or any recurrence of the event, in the time zone given as
// the timeZone argument, must be after this date to match the condition.
After LocalDate `json:"after,omitzero"`
// The start of the event, or any recurrence of the event, in the time zone given
// as the timeZone argument, must be before this date to match the condition.
Before LocalDate `json:"before,omitzero"`
// Looks for the text in the title, description, locations (matching name/description),
// participants (matching name/email) and any other textual properties of the event
// or any recurrence of the event.
Text string `json:"text,omitempty"`
// Looks for the text in the title property of the event, or the overridden title
// property of a recurrence.
Title string `json:"title,omitempty"`
// Looks for the text in the description property of the event, or the overridden
// description property of a recurrence.
Description string `json:"description,omitempty"`
// Looks for the text in the locations property of the event (matching name/description
// of a location), or the overridden locations property of a recurrence.
Location string `json:"location,omitempty"`
// Looks for the text in the name or email fields of a participant in the participants
// property of the event, or the overridden participants property of a recurrence,
// where the participant has a role of “owner”.
Owner string `json:"owner,omitempty"`
// Looks for the text in the name or email fields of a participant in the participants
// property of the event, or the overridden participants property of a recurrence,
// where the participant has a role of “attendee”.
Attendee string `json:"attendee,omitempty"`
// Must match. If owner/attendee condition, status must be of that participant. Otherwise any.
ParticipationStatus string `json:"participationStatus,omitempty"`
// The uid of the event is exactly the given string.
Uid string `json:"uid,omitempty"`
}
func (f CalendarEventFilterCondition) _isACalendarEventFilterElement() {
}
func (f CalendarEventFilterCondition) IsNotEmpty() bool {
if f.InCalendar != "" {
return true
}
if f.After != "" {
return true
}
if f.Before != "" {
return true
}
if f.Text != "" {
return true
}
if f.Title != "" {
return true
}
if f.Description != "" {
return true
}
if f.Location != "" {
return true
}
if f.Owner != "" {
return true
}
if f.Attendee != "" {
return true
}
if f.ParticipationStatus != "" {
return true
}
if f.Uid != "" {
return true
}
return false
}
var _ CalendarEventFilterElement = &CalendarEventFilterCondition{}
type CalendarEventFilterOperator struct {
Operator FilterOperatorTerm `json:"operator"`
Conditions []CalendarEventFilterElement `json:"conditions,omitempty"`
}
func (o CalendarEventFilterOperator) _isACalendarEventFilterElement() {
}
func (o CalendarEventFilterOperator) IsNotEmpty() bool {
return len(o.Conditions) > 0
}
var _ CalendarEventFilterElement = &CalendarEventFilterOperator{}
type CalendarEventQueryCommand struct {
AccountId string `json:"accountId"`
Filter CalendarEventFilterElement `json:"filter,omitempty"`
Sort []CalendarEventComparator `json:"sort,omitempty"`
// The zero-based index of the first id in the full list of results to return.
//
// If a negative value is given, it is an offset from the end of the list.
// Specifically, the negative value MUST be added to the total number of results given
// the filter, and if still negative, it’s clamped to 0. This is now the zero-based
// index of the first id to return.
//
// If the index is greater than or equal to the total number of objects in the results
// list, then the ids array in the response will be empty, but this is not an error.
Position uint `json:"position,omitempty"`
// An Email id.
//
// If supplied, the position argument is ignored.
// The index of this id in the results will be used in combination with the anchorOffset
// argument to determine the index of the first result to return.
Anchor string `json:"anchor,omitempty"`
// The index of the first result to return relative to the index of the anchor,
// if an anchor is given.
//
// Default: 0.
//
// This MAY be negative.
//
// For example, -1 means the Email immediately preceding the anchor is the first result in
// the list returned.
AnchorOffset int `json:"anchorOffset,omitzero"`
// The maximum number of results to return.
//
// If null, no limit presumed.
// The server MAY choose to enforce a maximum limit argument.
// In this case, if a greater value is given (or if it is null), the limit is clamped
// to the maximum; the new limit is returned with the response so the client is aware.
//
// If a negative value is given, the call MUST be rejected with an invalidArguments error.
Limit uint `json:"limit,omitempty"`
// Does the client wish to know the total number of results in the query?
//
// This may be slow and expensive for servers to calculate, particularly with complex filters,
// so clients should take care to only request the total when needed.
CalculateTotal bool `json:"calculateTotal,omitempty"`
}
type CalendarEventQueryResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A string encoding the current state of the query on the server.
//
// This string MUST change if the results of the query (i.e., the matching ids and their sort order) have changed.
// The queryState string MAY change if something has changed on the server, which means the results may have changed
// but the server doesn’t know for sure.
//
// The queryState string only represents the ordered list of ids that match the particular query (including its sort/filter).
// There is no requirement for it to change if a property on an object matching the query changes but the query results are unaffected
// (indeed, it is more efficient if the queryState string does not change in this case).
//
// The queryState string only has meaning when compared to future responses to a query with the same type/sort/filter or when used with
// /queryChanges to fetch changes.
//
// Should a client receive back a response with a different queryState string to a previous call, it MUST either throw away the currently
// cached query and fetch it again (note, this does not require fetching the records again, just the list of ids) or call
// CalendarEvent/queryChanges to get the difference.
QueryState State `json:"queryState"`
// This is true if the server supports calling CalendarEvent/queryChanges with these filter/sort parameters.
//
// Note, this does not guarantee that the CalendarEvent/queryChanges call will succeed, as it may only be possible for a limited time
// afterwards due to server internal implementation details.
CanCalculateChanges bool `json:"canCalculateChanges"`
// The zero-based index of the first result in the ids array within the complete list of query results.
Position uint `json:"position"`
// The list of ids for each ContactCard in the query results, starting at the index given by the position argument of this
// response and continuing until it hits the end of the results or reaches the limit number of ids.
//
// If position is >= total, this MUST be the empty list.
Ids []string `json:"ids"`
// The total number of CalendarEvents in the results (given the filter).
//
// Only if requested.
//
// This argument MUST be omitted if the calculateTotal request argument is not true.
Total uint `json:"total,omitempty,omitzero"`
// The limit enforced by the server on the maximum number of results to return (if set by the server).
//
// This is only returned if the server set a limit or used a different limit than that given in the request.
Limit uint `json:"limit,omitempty,omitzero"`
}
type CalendarEventGetCommand struct {
// The ids of the CalendarEvent objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that
// data type and the number of records does not exceed the maxObjectsInGet limit.
Ids []string `json:"ids,omitempty"`
// The id of the account to use.
AccountId string `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each CalendarEvent object.
//
// The id property of the object is always returned, even if not explicitly requested.
//
// If an invalid property is requested, the call MUST be rejected with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
}
type CalendarEventGetRefCommand struct {
// The ids of the CalendarEvent objects to return.
//
// If null, then all records of the data type are returned, if this is supported for that
// data type and the number of records does not exceed the maxObjectsInGet limit.
IdsRef *ResultReference `json:"#ids,omitempty"`
// The id of the account to use.
AccountId string `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each CalendarEvent object.
//
// The id property of the object is always returned, even if not explicitly requested.
//
// If an invalid property is requested, the call MUST be rejected with an invalidArguments error.
Properties []string `json:"properties,omitempty"`
}
type CalendarEventGetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type
// in the account (not just the objects returned in this call).
//
// If the data changes, this string MUST change.
// If the Email data is unchanged, servers SHOULD return the same state string on subsequent requests for this data type.
State State `json:"state"`
// An array of the CalendarEvent objects requested.
//
// This is the empty array if no objects were found or if the ids argument passed in was also an empty array.
//
// The results MAY be in a different order to the ids in the request arguments.
//
// If an identical id is included more than once in the request, the server MUST only include it once in either
// the list or the notFound argument of the response.
List []CalendarEvent `json:"list"`
// This array contains the ids passed to the method for records that do not exist.
//
// The array is empty if all requested ids were found or if the ids argument passed in was either null or an empty array.
NotFound []any `json:"notFound"`
}
type CalendarEventUpdate map[string]any
type CalendarEventSetCommand struct {
// The id of the account to use.
AccountId string `json:"accountId"`
// This is a state string as returned by the `CalendarEvent/get` method.
//
// If supplied, the string must match the current state; otherwise, the method will be aborted and a
// `stateMismatch` error returned.
//
// If null, any changes will be applied to the current state.
IfInState string `json:"ifInState,omitempty"`
// A map of a creation id (a temporary id set by the client) to CalendarEvent objects,
// or null if no objects are to be created.
//
// The CalendarEvent object type definition may define default values for properties.
//
// Any such property may be omitted by the client.
//
// The client MUST omit any properties that may only be set by the server.
Create map[string]CalendarEvent `json:"create,omitempty"`
// A map of an id to a `Patch` object to apply to the current Email object with that id,
// or null if no objects are to be updated.
//
// A `PatchObject` is of type `String[*]` and represents an unordered set of patches.
//
// The keys are a path in JSON Pointer Format [@!RFC6901], with an implicit leading `/` (i.e., prefix each key
// with `/` before applying the JSON Pointer evaluation algorithm).
//
// All paths MUST also conform to the following restrictions; if there is any violation, the update
// MUST be rejected with an `invalidPatch` error:
// !- The pointer MUST NOT reference inside an array (i.e., you MUST NOT insert/delete from an array; the array MUST be replaced in its entirety instead).
// !- All parts prior to the last (i.e., the value after the final slash) MUST already exist on the object being patched.
// !- There MUST NOT be two patches in the `PatchObject` where the pointer of one is the prefix of the pointer of the other, e.g., `"alerts/1/offset"` and `"alerts"`.
//
// The value associated with each pointer determines how to apply that patch:
// !- If null, set to the default value if specified for this property; otherwise, remove the property from the patched object. If the key is not present in the parent, this a no-op.
// !- Anything else: The value to set for this property (this may be a replacement or addition to the object being patched).
//
// Any server-set properties MAY be included in the patch if their value is identical to the current server value
// (before applying the patches to the object). Otherwise, the update MUST be rejected with an `invalidProperties` `SetError`.
//
// This patch definition is designed such that an entire Email object is also a valid `PatchObject`.
//
// The client may choose to optimise network usage by just sending the diff or may send the whole object; the server
// processes it the same either way.
Update map[string]CalendarEventUpdate `json:"update,omitempty"`
// A list of ids for CalendarEvent objects to permanently delete, or null if no objects are to be destroyed.
Destroy []string `json:"destroy,omitempty"`
}
type CalendarEventSetResponse struct {
// The id of the account used for the call.
AccountId string `json:"accountId"`
// The state string that would have been returned by CalendarEvent/get before making the
// requested changes, or null if the server doesn’t know what the previous state
// string was.
OldState State `json:"oldState,omitempty"`
// The state string that will now be returned by Email/get.
NewState State `json:"newState"`
// A map of the creation id to an object containing any properties of the created Email object
// that were not sent by the client.
//
// This includes all server-set properties (such as the id in most object types) and any properties
// that were omitted by the client and thus set to a default by the server.
//
// This argument is null if no CalendarEvent objects were successfully created.
Created map[string]*CalendarEvent `json:"created,omitempty"`
// The keys in this map are the ids of all CalendarEvents that were successfully updated.
//
// The value for each id is an CalendarEvent object containing any property that changed in a way not
// explicitly requested by the PatchObject sent to the server, or null if none.
//
// This lets the client know of any changes to server-set or computed properties.
//
// This argument is null if no CalendarEvent objects were successfully updated.
Updated map[string]*CalendarEvent `json:"updated,omitempty"`
// A list of CalendarEvent ids for records that were successfully destroyed, or null if none.
Destroyed []string `json:"destroyed,omitempty"`
// A map of the creation id to a SetError object for each record that failed to be created,
// or null if all successful.
NotCreated map[string]SetError `json:"notCreated,omitempty"`
// A map of the ContactCard id to a SetError object for each record that failed to be updated,
// or null if all successful.
NotUpdated map[string]SetError `json:"notUpdated,omitempty"`
// A map of the CalendarEvent id to a SetError object for each record that failed to be destroyed,
// or null if all successful.
NotDestroyed map[string]SetError `json:"notDestroyed,omitempty"`
}
type ErrorResponse struct {
Type string `json:"type"`
Description string `json:"description,omitempty"`
}
const (
ErrorCommand Command = "error" // only occurs in responses
CommandBlobGet Command = "Blob/get"
CommandBlobUpload Command = "Blob/upload"
CommandEmailGet Command = "Email/get"
CommandEmailQuery Command = "Email/query"
CommandEmailChanges Command = "Email/changes"
CommandEmailSet Command = "Email/set"
CommandEmailImport Command = "Email/import"
CommandEmailSubmissionGet Command = "EmailSubmission/get"
CommandEmailSubmissionSet Command = "EmailSubmission/set"
CommandThreadGet Command = "Thread/get"
CommandMailboxGet Command = "Mailbox/get"
CommandMailboxSet Command = "Mailbox/set"
CommandMailboxQuery Command = "Mailbox/query"
CommandMailboxChanges Command = "Mailbox/changes"
CommandIdentityGet Command = "Identity/get"
CommandIdentitySet Command = "Identity/set"
CommandVacationResponseGet Command = "VacationResponse/get"
CommandVacationResponseSet Command = "VacationResponse/set"
CommandSearchSnippetGet Command = "SearchSnippet/get"
CommandQuotaGet Command = "Quota/get"
CommandAddressBookGet Command = "AddressBook/get"
CommandContactCardQuery Command = "ContactCard/query"
CommandContactCardGet Command = "ContactCard/get"
CommandContactCardSet Command = "ContactCard/set"
CommandCalendarEventParse Command = "CalendarEvent/parse"
CommandCalendarGet Command = "Calendar/get"
CommandCalendarEventQuery Command = "CalendarEvent/query"
CommandCalendarEventGet Command = "CalendarEvent/get"
CommandCalendarEventSet Command = "CalendarEvent/set"
)
var CommandResponseTypeMap = map[Command]func() any{
ErrorCommand: func() any { return ErrorResponse{} },
CommandBlobGet: func() any { return BlobGetResponse{} },
CommandBlobUpload: func() any { return BlobUploadResponse{} },
CommandMailboxQuery: func() any { return MailboxQueryResponse{} },
CommandMailboxGet: func() any { return MailboxGetResponse{} },
CommandMailboxSet: func() any { return MailboxSetResponse{} },
CommandMailboxChanges: func() any { return MailboxChangesResponse{} },
CommandEmailQuery: func() any { return EmailQueryResponse{} },
CommandEmailChanges: func() any { return EmailChangesResponse{} },
CommandEmailGet: func() any { return EmailGetResponse{} },
CommandEmailSet: func() any { return EmailSetResponse{} },
CommandEmailSubmissionGet: func() any { return EmailSubmissionGetResponse{} },
CommandEmailSubmissionSet: func() any { return EmailSubmissionSetResponse{} },
CommandThreadGet: func() any { return ThreadGetResponse{} },
CommandIdentityGet: func() any { return IdentityGetResponse{} },
CommandIdentitySet: func() any { return IdentitySetResponse{} },
CommandVacationResponseGet: func() any { return VacationResponseGetResponse{} },
CommandVacationResponseSet: func() any { return VacationResponseSetResponse{} },
CommandSearchSnippetGet: func() any { return SearchSnippetGetResponse{} },
CommandQuotaGet: func() any { return QuotaGetResponse{} },
CommandAddressBookGet: func() any { return AddressBookGetResponse{} },
CommandContactCardQuery: func() any { return ContactCardQueryResponse{} },
CommandContactCardGet: func() any { return ContactCardGetResponse{} },
CommandContactCardSet: func() any { return ContactCardSetResponse{} },
CommandCalendarEventParse: func() any { return CalendarEventParseResponse{} },
CommandCalendarGet: func() any { return CalendarGetResponse{} },
CommandCalendarEventQuery: func() any { return CalendarEventQueryResponse{} },
CommandCalendarEventGet: func() any { return CalendarEventGetResponse{} },
CommandCalendarEventSet: func() any { return CalendarEventSetResponse{} },
}