package jmap import ( "context" "fmt" "slices" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/structs" ) var NS_MAILBOX = ns(JmapMail) func (j *Client) GetMailbox(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, ids []string) (MailboxGetResponse, SessionState, State, Language, Error) { /* return get(j, "GetMailbox", NS_MAILBOX, func(accountId string, ids []string) MailboxGetCommand { return MailboxGetCommand{AccountId: accountId, Ids: ids} }, MailboxGetResponse{}, identity1, accountId, session, ctx, logger, acceptLanguage, ids, ) */ return fget[Mailboxes](MAILBOX, j, "GetMailbox", accountId, ids, session, ctx, logger, acceptLanguage) } func (j *Client) GetAllMailboxes(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string) (map[string][]Mailbox, SessionState, State, Language, Error) { /* return getAN(j, "GetAllMailboxes", NS_MAILBOX, func(accountId string, ids []string) MailboxGetCommand { return MailboxGetCommand{AccountId: accountId} }, MailboxGetResponse{}, identity1, accountIds, session, ctx, logger, acceptLanguage, []string{}, ) */ return fgetAN[Mailboxes](MAILBOX, j, "GetAllMailboxes", identity1, accountIds, []string{}, session, ctx, logger, acceptLanguage) } func (j *Client) SearchMailboxes(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, filter MailboxFilterElement) (map[string][]Mailbox, SessionState, State, Language, Error) { logger = j.logger("SearchMailboxes", session, logger) uniqueAccountIds := structs.Uniq(accountIds) invocations := make([]Invocation, len(uniqueAccountIds)*2) for i, accountId := range uniqueAccountIds { invocations[i*2+0] = invocation(MailboxQueryCommand{AccountId: accountId, Filter: filter}, mcid(accountId, "0")) invocations[i*2+1] = invocation(MailboxGetRefCommand{ AccountId: accountId, IdsRef: &ResultReference{ Name: CommandMailboxQuery, Path: "/ids/*", ResultOf: mcid(accountId, "0"), }, }, mcid(accountId, "1")) } cmd, err := j.request(session, logger, NS_MAILBOX, invocations...) if err != nil { return nil, "", "", "", err } return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (map[string][]Mailbox, State, Error) { resp := map[string][]Mailbox{} stateByAccountid := map[string]State{} for _, accountId := range uniqueAccountIds { var response MailboxGetResponse err = retrieveResponseMatchParameters(logger, body, CommandMailboxGet, mcid(accountId, "1"), &response) if err != nil { return nil, "", err } resp[accountId] = response.List stateByAccountid[accountId] = response.State } return resp, squashState(stateByAccountid), nil }) } func (j *Client) SearchMailboxIdsPerRole(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, roles []string) (map[string]map[string]string, SessionState, State, Language, Error) { //NOSONAR logger = j.logger("SearchMailboxIdsPerRole", session, logger) uniqueAccountIds := structs.Uniq(accountIds) invocations := make([]Invocation, len(uniqueAccountIds)*len(roles)) for i, accountId := range uniqueAccountIds { for j, role := range roles { invocations[i*len(roles)+j] = invocation(MailboxQueryCommand{AccountId: accountId, Filter: MailboxFilterCondition{Role: role}}, mcid(accountId, role)) } } cmd, err := j.request(session, logger, NS_MAILBOX, invocations...) if err != nil { return nil, "", "", "", err } return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (map[string]map[string]string, State, Error) { resp := map[string]map[string]string{} stateByAccountid := map[string]State{} for _, accountId := range uniqueAccountIds { mailboxIdsByRole := map[string]string{} for _, role := range roles { var response MailboxQueryResponse err = retrieveResponseMatchParameters(logger, body, CommandMailboxQuery, mcid(accountId, role), &response) if err != nil { return nil, "", err } if len(response.Ids) == 1 { mailboxIdsByRole[role] = response.Ids[0] } if _, ok := stateByAccountid[accountId]; !ok { stateByAccountid[accountId] = response.QueryState } } resp[accountId] = mailboxIdsByRole } return resp, squashState(stateByAccountid), nil }) } type MailboxChanges = ChangesTemplate[Mailbox] func newMailboxChanges(oldState, newState State, hasMoreChanges bool, created, updated []Mailbox, destroyed []string) MailboxChanges { return MailboxChanges{ OldState: oldState, NewState: newState, HasMoreChanges: hasMoreChanges, Created: created, Updated: updated, Destroyed: destroyed, } } // Retrieve Mailbox changes since a given state. // @apidoc mailboxes,changes func (j *Client) GetMailboxChanges(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, sinceState State, maxChanges uint) (MailboxChanges, SessionState, State, Language, Error) { return changesA(j, "GetMailboxChanges", NS_MAILBOX, func() MailboxChangesCommand { return MailboxChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: posUIntPtr(maxChanges)} }, MailboxChangesResponse{}, MailboxGetResponse{}, func(path string, rof string) MailboxGetRefCommand { return MailboxGetRefCommand{ AccountId: accountId, IdsRef: &ResultReference{ Name: CommandMailboxChanges, Path: path, ResultOf: rof, }, } }, newMailboxChanges, session, ctx, logger, acceptLanguage, ) } // Retrieve Mailbox changes of multiple Accounts. // @api:tags email,changes func (j *Client) GetMailboxChangesForMultipleAccounts(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, sinceStateMap map[string]State, maxChanges uint) (map[string]MailboxChanges, SessionState, State, Language, Error) { //NOSONAR return changesN(j, "GetMailboxChangesForMultipleAccounts", NS_MAILBOX, accountIds, sinceStateMap, func(accountId string, state State) MailboxChangesCommand { return MailboxChangesCommand{AccountId: accountId, SinceState: state, MaxChanges: posUIntPtr(maxChanges)} }, MailboxChangesResponse{}, func(accountId string, path string, ref string) MailboxGetRefCommand { return MailboxGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: CommandMailboxChanges, Path: path, ResultOf: ref}} }, func(resp MailboxGetResponse) []Mailbox { return resp.List }, newMailboxChanges, identity1, func(resp MailboxGetResponse) State { return resp.State }, session, ctx, logger, acceptLanguage, ) } func (j *Client) GetMailboxRolesForMultipleAccounts(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string) (map[string][]string, SessionState, State, Language, Error) { logger = j.logger("GetMailboxRolesForMultipleAccounts", session, logger) uniqueAccountIds := structs.Uniq(accountIds) n := len(uniqueAccountIds) if n < 1 { return nil, "", "", "", nil } t := true invocations := make([]Invocation, n*2) for i, accountId := range uniqueAccountIds { invocations[i*2+0] = invocation(MailboxQueryCommand{ AccountId: accountId, Filter: MailboxFilterCondition{ HasAnyRole: &t, }, }, mcid(accountId, "0")) invocations[i*2+1] = invocation(MailboxGetRefCommand{ AccountId: accountId, IdsRef: &ResultReference{ ResultOf: mcid(accountId, "0"), Name: CommandMailboxQuery, Path: "/ids", }, }, mcid(accountId, "1")) } cmd, err := j.request(session, logger, NS_MAILBOX, invocations...) if err != nil { return nil, "", "", "", err } return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (map[string][]string, State, Error) { resp := make(map[string][]string, n) stateByAccountId := make(map[string]State, n) for _, accountId := range uniqueAccountIds { var getResponse MailboxGetResponse err = retrieveResponseMatchParameters(logger, body, CommandMailboxGet, mcid(accountId, "1"), &getResponse) if err != nil { return nil, "", err } roles := make([]string, len(getResponse.List)) for i, mailbox := range getResponse.List { roles[i] = mailbox.Role } slices.Sort(roles) resp[accountId] = roles stateByAccountId[accountId] = getResponse.State } return resp, squashState(stateByAccountId), nil }) } func (j *Client) GetInboxNameForMultipleAccounts(accountIds []string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string) (map[string]string, SessionState, State, Language, Error) { logger = j.logger("GetInboxNameForMultipleAccounts", session, logger) uniqueAccountIds := structs.Uniq(accountIds) n := len(uniqueAccountIds) if n < 1 { return nil, "", "", "", nil } invocations := make([]Invocation, n*2) for i, accountId := range uniqueAccountIds { invocations[i*2+0] = invocation(MailboxQueryCommand{ AccountId: accountId, Filter: MailboxFilterCondition{ Role: JmapMailboxRoleInbox, }, }, mcid(accountId, "0")) } cmd, err := j.request(session, logger, NS_MAILBOX, invocations...) if err != nil { return nil, "", "", "", err } return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (map[string]string, State, Error) { resp := make(map[string]string, n) stateByAccountId := make(map[string]State, n) for _, accountId := range uniqueAccountIds { var r MailboxQueryResponse err = retrieveResponseMatchParameters(logger, body, CommandMailboxGet, mcid(accountId, "0"), &r) if err != nil { return nil, "", err } switch len(r.Ids) { case 0: // skip: account has no inbox? case 1: resp[accountId] = r.Ids[0] stateByAccountId[accountId] = r.QueryState default: logger.Warn().Msgf("multiple ids for mailbox role='%v' for accountId='%v'", JmapMailboxRoleInbox, accountId) resp[accountId] = r.Ids[0] stateByAccountId[accountId] = r.QueryState } } return resp, squashState(stateByAccountId), nil }) } func (j *Client) UpdateMailbox(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, mailboxId string, ifInState string, update MailboxChange) (Mailbox, SessionState, State, Language, Error) { //NOSONAR logger = j.logger("UpdateMailbox", session, logger) cmd, err := j.request(session, logger, NS_MAILBOX, invocation(MailboxSetCommand{ AccountId: accountId, IfInState: ifInState, Update: map[string]PatchObject{ mailboxId: update.AsPatch(), }, }, "0")) if err != nil { return Mailbox{}, "", "", "", err } return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (Mailbox, State, Error) { var setResp MailboxSetResponse err = retrieveResponseMatchParameters(logger, body, CommandMailboxSet, "0", &setResp) if err != nil { return Mailbox{}, "", err } setErr, notok := setResp.NotUpdated["u"] if notok { logger.Error().Msgf("%T.NotUpdated returned an error %v", setResp, setErr) return Mailbox{}, "", setErrorError(setErr, MailboxType) } return setResp.Updated["c"], setResp.NewState, nil }) } func (j *Client) CreateMailbox(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, ifInState string, create MailboxChange) (Mailbox, SessionState, State, Language, Error) { logger = j.logger("CreateMailbox", session, logger) cmd, err := j.request(session, logger, NS_MAILBOX, invocation(MailboxSetCommand{ AccountId: accountId, IfInState: ifInState, Create: map[string]MailboxChange{ "c": create, }, }, "0")) if err != nil { return Mailbox{}, "", "", "", err } return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (Mailbox, State, Error) { var setResp MailboxSetResponse err = retrieveResponseMatchParameters(logger, body, CommandMailboxSet, "0", &setResp) if err != nil { return Mailbox{}, "", err } setErr, notok := setResp.NotCreated["c"] if notok { logger.Error().Msgf("%T.NotCreated returned an error %v", setResp, setErr) return Mailbox{}, "", setErrorError(setErr, MailboxType) } if mailbox, ok := setResp.Created["c"]; ok { return mailbox, setResp.NewState, nil } else { return Mailbox{}, "", jmapError(fmt.Errorf("failed to find created %T in response", Mailbox{}), JmapErrorMissingCreatedObject) } }) } func (j *Client) DeleteMailboxes(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, ifInState string, mailboxIds []string) ([]string, SessionState, State, Language, Error) { logger = j.logger("DeleteMailbox", session, logger) set := MailboxSetCommand{ AccountId: accountId, IfInState: ifInState, Destroy: mailboxIds, } cmd, err := j.request(session, logger, NS_MAILBOX, invocation(set, "0")) if err != nil { return nil, "", "", "", err } return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) ([]string, State, Error) { var setResp MailboxSetResponse err = retrieveSet(logger, body, set, "0", &setResp) if err != nil { return nil, "", err } setErr, notok := setResp.NotDestroyed["u"] if notok { logger.Error().Msgf("%T.NotDestroyed returned an error %v", setResp, setErr) return nil, "", setErrorError(setErr, MailboxType) } return setResp.Destroyed, setResp.NewState, nil }) }