Deputy permissions deprecated

Introduction

Since version v7.10.6 the Open-Xchange Middleware offers the feature to grant deputy permissions to one ore more users from the same context that are supposed to act as representatives (e.g. vacation replacement).

A deputy has configurable access to granting user's primary mail account's Inbox and/or standard Calendar folder. Moreover, a deputy might get the "send on behalf of" permission granted, which allows them to send E-Mails on behalf of the granting user, or - if enabled by the operator - the "send as" permission, which allows them to send E-Mails as the granting user.

A deputy can also be appointed across context boundaries, subject to the deployment-wide trust-zone policy. See Cross-Context Collaboration.

Configuration

To enable the deputy permission feature, the open-xchange-deputy package needs to be enabled in your chart's values.yaml:

core-mw:
  packages:
    status:
      open-xchange-deputy: enabled

Enable deputy permissions

To enable deputy permission management the com.openexchange.deputy.enabled property needs to be set to true, which is false by default. That property is fully config-cascade-aware. After the feature is enabled, the user will gain access to a new deputy permission management menu in the App Suite UI.

Behavior

Deputy permissions do overwrite possibly existent permissions. Moreover, granted deputy permissions cannot be changed/deleted via regular permission dialogue, but only via deputy permission management by the granting user.

The setting com.openexchange.deputy.simplePermissionMode controls whether deputy permissions may only be assigned to users (not groups) and may only contain such permission rights for viewer, editor and author as App Suite UI would grant those permission rights.

Currently, deputy permissions for the following modules can be granted:

  • Mail
  • Calendar

Furthermore for the mail module, the granting user of the deputy permission can decide whether the deputy can sent mails using the granting user's mail account. If granted, mails can be send by the deputy "on behalf of" the granting user. To indicate that a deputy and not the granting user responded, the Sender header filled with the deputy's mail address will be set within the mail. Whereby the From header will be set to granting user's default sender address. E.g.:

From: Granting user <grantinguser@example.org>
Sender: Deputy <deputy@example.org>

In case the deputy has been given write permissions to the granting user's calendar, outgoing notification and/or iTIP mails (see also the iTIP article) will automatically be decorated with the "on behalf" relationship. This applies to the outgoing mails as well as for the generated iCAL files sent along the mails. E.g.:

ORGANIZER;CN=Granting user;SENT-BY="mailto:deputy@example.org";EMAIL=grantinguser@example.org:mailto:grantinguser@example.org

Sending as the granting user

Instead of "on behalf of", the granting user can let the deputy send E-Mails as the granting user through the sendAs attribute of the deputy permission. The E-Mail then carries the granting user as From and no Sender header, so recipients cannot tell that the deputy sent it:

From: Granting user <grantinguser@example.org>

sendOnBehalfOf and sendAs are mutually exclusive:

  • Granting both at once is rejected with DEPUTY-0015.
  • An update that sets one of them to true without passing the other one clears the other one, so clients do not need to know the stored form in order to switch it.
  • Setting sendOnBehalfOf to false does not revoke sendAs; to revoke any sending right, set both to false. Provisioning systems and clients that do not know sendAs should be checked for this.

Apart from the missing Sender header, sendAs behaves like sendOnBehalfOf: it is not affected by com.openexchange.deputy.simplePermissionMode, which only restricts the module permissions, and a deputy permission granted to a group (possible through RMI, gRPC and SCIM) lets every member of the group send as the granting user. If the granting user grants the same deputy both forms through different deputy permissions, e.g. one directly and one through a group, "send as" takes precedence.

Sending as the granting user has to be enabled by the operator through com.openexchange.deputy.sendAsEnabled (default false), which is evaluated for the granting user and announced to clients as capability deputy_send_as:

  • While it is disabled, granting sendAs is rejected with DEPUTY-0016. Passing back an already stored sendAs unchanged still works, so editing an existing deputy keeps working.
  • Disabling it takes effect on existing grants immediately: a grant of sendAs is then effective as sendOnBehalfOf, and the deputy's reverse listing reports it that way. The stored grant is kept and takes effect again once the property is enabled; no database changes are needed.
  • Administrative provisioning (SOAP, RMI, gRPC, SCIM) is not restricted by the property.
  • Grants of sendAs provisioned while the property is disabled take effect as soon as it is enabled, also when it is enabled for the first time. They can be listed beforehand, e.g. with SELECT cid, user, entity FROM deputy WHERE sendAs = 1 in every context database schema.
  • The notification mail to the deputy names the form that is effective when the deputy permission is granted or changed, i.e. "on behalf of" while the property is disabled. Enabling the property later sends no new notification.

When sending, the Middleware only accepts the form the deputy actually holds:

  • A deputy allowed to send as the granting user who adds a Sender header is rejected with MSG-0129, also for a raw message sent through mail?action=new and for mail?action=resend, unless the granting user's address is also the address of one of the deputy's own mail accounts.
  • A deputy only allowed to send on behalf of the granting user who omits the Sender header is rejected with MSG-0134. Previous versions rejected this case with the generic MSG-0056.
  • The granting user's address is accepted as From only. Using it as Sender is rejected with MSG-0056.

If mail?action=transport cannot resolve the account for a mail with a Sender header, e.g. because the deputy permissions cannot be looked up, it keeps falling back to the default account's transport as in previous versions, except for a deputy allowed to send as the granting user: then, or if the deputy permissions cannot be looked up at all, the mail is rejected instead of being sent on behalf of the granting user.

Saving a draft through the mail compose API is not blocked if the deputy permissions cannot be looked up: the draft is saved to the deputy's primary account, and sending it checks the granting user's address again. A draft saved through the legacy mail?action=new is checked like a mail being sent, so it is rejected if the deputy permissions cannot be looked up.

Replying to or forwarding a mail from the granting user's shared Inbox pre-fills the form the deputy holds, i.e. without a Sender for "send as". The reverse listings (action=reverse and action=reverseIds) report sendAs next to sendOnBehalfOf and disclose the granting user's addresses (grantorAddresses) for both forms. A mail sent as the granting user through the Mobile API carries that user's display name, not the deputy's.

Note that the SMTP server has to accept the granting user's address as From for the deputy's login without a Sender header, just as it has to accept it with one for "on behalf of".

The flag is stored in the new column sendAs of table deputy. During a rolling upgrade, nodes of an older version do not know this column: they treat a deputy permission that grants neither a module nor "send on behalf of" as empty and delete it as soon as they read it. A deputy who opens App Suite on such a node is enough to lose a grant of "send as" without any module. Editing a deputy through such a node changes sendOnBehalfOf only and leaves a stored sendAs untouched, so the result may not be what the granting user chose. If com.openexchange.deputy.preferRecreateInsteadOfUpdate is enabled, such a node re-creates the deputy permission instead and resets sendAs: the deputy may then send E-Mails on behalf of the granting user at most. If such a node sets sendOnBehalfOf on a deputy permission that grants "send as", both flags are stored and the permission acts as "send as"; an updated node that re-creates it rejects the update with DEPUTY-0015 until the granting user chooses one of the two forms. A SCIM PUT or PATCH that turns on neither form resolves such a permission to "send as". Such deputy permissions can be found with SELECT cid, user, entity FROM deputy WHERE sendAs = 1 AND sendOnBehalfOf = 1 in every context database schema; any update that sets one of the two forms to true resolves them. Therefore, enable com.openexchange.deputy.sendAsEnabled and provision sendAs (SOAP, RMI, gRPC, SCIM) only once all nodes run a version that knows sendAs. The same applies after a rollback to a version that does not know sendAs: the column is then ignored, deputies granted only "send as" can no longer send E-Mails for the granting user, and such deputy permissions without any module are deleted. To prevent that, run UPDATE deputy SET sendOnBehalfOf = 1, sendAs = 0 WHERE sendAs = 1 in every context database schema before rolling back: the deputies then send E-Mails on behalf of the granting user, no deputy permission looks empty to a node of the previous version, and "send as" has to be granted anew after upgrading again.

A deputy allowed to send as the granting user may also bounce one of that user's mails (mail?action=bounce), which sends the stored mail once more to its recipients. The mail then keeps its Reply-To, while a bounce of an own mail or one sent on behalf of the granting user sets the bouncing user's primary address there as before; if the deputy permissions cannot be looked up, the bounce is rejected.

"Send as" applies to E-Mails only. Notification and iTIP mails a deputy triggers in the granting user's calendar are always decorated with the "on behalf" relationship as described above, also if the deputy permission grants sendAs.

Known limitations

Sending as the granting user only omits what the Middleware itself writes into the mail. Technical traces of the deputy remain possible:

  • The deputy authenticates at the mail transport server, which may record that in its own headers.
  • The envelope sender (Return-Path) is the deputy's primary address if com.openexchange.smtp.setSMTPEnvelopeFrom is enabled (default false).
  • The X-Originating-IP and X-Originating-Client headers, if configured, describe the deputy's client.

Access to classified appointments

By default, a deputy sees the granting user's appointments that are marked as confidential or private like any other user the calendar is shared with: confidential appointments are anonymized to opaque blocks titled "Private", private ones are not shown at all (see the classification section of the calendar implementation details). The granting user can additionally allow the deputy to see confidential appointments with all details through the optional classifiedAccess attribute of the deputy permission. Like sendOnBehalfOf, it is an attribute of the deputy permission as a whole, but it exclusively concerns the calendar: it controls the visibility of classified appointments in the covered calendar folders and has no meaning for any other module:

  • none (default) - classified appointments are anonymized or hidden as for any other sharee
  • confidential - appointments marked as confidential are shown with all details

Appointments marked as private always stay hidden from deputies, so users keep a way to have appointments nobody else gets to see.

The attribute is set next to sendOnBehalfOf when granting or updating a deputy permission through the HTTP API (PUT /ajax/deputy?action=new respectively action=update), and is reported back by the listing actions. When updating, the attribute is only changed if it is present in the request, so the right is revoked by sending none explicitly. A level that cannot be granted is rejected with DEPUTY-0014, an unknown value with SVL-0010. E.g.:

{
  "userId": 4,
  "folderMode": "default",
  "classifiedAccess": "confidential",
  "modulePermissions": {
    "calendar": {
      "permission": 257
    }
  }
}

The right applies to the calendar folders covered by the deputy permission (according to its folder mode) and does not extend to calendars the granting user shared through the regular permission dialog. Together with the granted folder permission, the deputy can then also edit and delete confidential appointments, mark appointments as confidential or back as public, and create confidential appointments in those folders. Attachments of confidential appointments follow the same rule, as do their details in free/busy results and conflict checks performed by the deputy. The appointments keep their private / confidential event flags, so clients can still indicate their classification.

Note that granting, changing or revoking this right does not modify the appointments themselves. Clients synchronizing the shared calendar incrementally (CalDAV, Exchange ActiveSync) therefore only pick up appointments that became visible or invisible through such a change with their next full synchronization.

Incoming scheduling mails from the shared inbox can be managed by the deputy as well in case author permissions are available for the granting user's default calendar folder. However, in order to analyze them properly, full iMIP emails are required - the context-internally used notification mails are not sufficient to discover the "on behalf" relationship correctly. Therefore, it is recommended to configure the property com.openexchange.calendar.useIMipForInternalUsers to true if this delegation feature is being used.

Copy of sent mails in the granting user's Sent folder

A mail the deputy sends for the granting user, on their behalf or as them, is kept in the deputy's own Sent folder as usual. With the optional sentCopyToGranter attribute of the deputy permission, the granting user additionally gets a copy of these mails in their own standard Sent folder. Like sendOnBehalfOf and sendAs, it is an attribute of the deputy permission as a whole, and it requires one of them:

  • Granting sentCopyToGranter without sendOnBehalfOf or sendAs is rejected with DEPUTY-0017.
  • Switching between sendOnBehalfOf and sendAs keeps the copy. Withdrawing both withdraws sentCopyToGranter as well, also if the request passes sentCopyToGranter back unchanged as true, as SCIM does. Granting a right to send again later does not bring the copy back; it has to be granted again.
  • A SCIM PATCH that removes sentCopyToGranter withdraws the copy.
  • A granted sendAs keeps the copy while com.openexchange.deputy.sendAsEnabled is disabled for the granting user: the deputy still sends, on their behalf for the time being.
  • If the granting user grants the same deputy several deputy permissions, the copy is made as soon as one of them grants sentCopyToGranter together with a right to send.
  • When updating, the attribute is only changed if it is present in the request, apart from withdrawing both rights to send (see above).

Clients detect whether a user may ask for the copy through the capability deputy_sent_copy. It is granted while deputy permissions are available to the user, the copy is enabled for the user through com.openexchange.deputy.sentCopyToGranterEnabled (default true) and the user's offline grant (see Through the granting user's offline grant), an acting user login of the deputy (see Through an acting user login of the deputy) or administrative mail access to the user's mailbox applies (see below); it is never granted to guests. While com.openexchange.deputy.sentCopyToGranterEnabled is false for the granting user, granting sentCopyToGranter is rejected with DEPUTY-0019, except through administrative provisioning, and no copy is made, also none still to be made at that time. Passing back an already stored sentCopyToGranter unchanged still works. Stored grants of sentCopyToGranter are kept and take effect again once it is true; until then, the deputy's reverse listing reports them without the copy, while the granting user's own listing (deputy?action=all, ?action=get) keeps reporting them. With the strategy token, the capability only checks that a token is kept for the user, not that it can still be used. Whether administrative mail access applies is looked up for the capability at most once a minute per user; switching the copy off takes effect at once. If neither the offline grant nor administrative mail access applies to the granting user, granting sentCopyToGranter is rejected with DEPUTY-0018, which SCIM answers with HTTP status 400. Neither the capability nor a successful grant means that every mail gets a copy: whether it does is decided each time the deputy sends, see When the copy is made.

The middleware puts the copy into the granting user's mailbox itself, through administrative mail access (see below). The copy gives the deputy no additional permission, in particular none on the granting user's Sent folder. The granting user's standard Sent folder is determined anew for every mail: the Sent folder full name stored with the granting user's primary mail account, or, if none is stored, the Sent folder name below the personal namespace: the one stored with the account, otherwise the one from the granting user's mail settings, otherwise Sent. If that folder does not exist and exactly one folder whose name differs from it in case only does, that one is taken; otherwise an existing folder of the personal namespace marked \Sent; otherwise the folder is created and subscribed. Hence a changed Sent folder is picked up as soon as it is the granting user's standard Sent folder.

The copy is the mail as it is kept in a Sent folder, so it contains the Bcc recipients of the mail: the granting user sees whom the deputy sent a blind copy to. A mail encrypted or signed through OX Guard gets the copy all the same, as kept in the deputy's Sent folder; the granting user can read an encrypted copy only if the mail was encrypted for them as well.

How the copy gets there depends on the strategy (see below). With token and master, the mail is appended to the granting user's Sent folder as the deputy's Sent folder would keep it; the deputy's Sent folder is not involved, so a deputy who chose not to keep copies of sent mails finds none there. This also holds for a mail with a version of its own for the Sent folder, such as a Drive Mail, even if putting that version into the deputy's Sent folder fails. With doveadm, the copy is taken from the deputy's Sent folder once the mail has been sent. If the deputy chose not to keep copies of sent mails, the mail is put into the deputy's Sent folder anyway, but only for the copy: it is removed there again for good (not moved to the trash folder) as soon as the copy is found in the granting user's Sent folder. Until then it is visible in the deputy's Sent folder. If the copy fails for good, the mail stays in the deputy's Sent folder, so that it is not lost from both. It stays there as well if no copy is made when it is due (see When the copy is made), if removing it fails, or if the deputy's session has ended by then, e.g. after logging out. A scheduled mail is always such a case: it is sent when due without a session of the deputy that the removal could rely on. A mail that stays is logged with level WARN; if it stays since too many copies are pending, at most once a minute (see below).

The copy is made in the background: it appears in the granting user's Sent folder shortly after sending, marked as read, and only once. If it appears there more than once nevertheless, e.g. since a try that timed out had made the copy after all, this is logged with level WARN. If the copy fails, e.g. since the connection to the mail server breaks, it is tried up to three more times, after about 15 seconds, 1 minute and 5 minutes. It is not tried again if none of the strategies applies any more, if the strategy does not support the copy, if the mail login belongs to another user, if personalNamespace is needed but not set (see below), if the granting user's mailbox is over quota (token, master), or if the copy is not permitted there, the deputy's Sent folder no longer exists or a folder name contains * or % (doveadm). An unexpected failure is not tried again either; other failures are tried again even if they are bound to recur. A mail server that cannot be reached for longer than these tries take is not bridged. If the mail server refuses the copy, no copy is made. Each copy put into the granting user's Sent folder, and each Sent folder created for it, is logged with level INFO. The copy is a convenience for the granting user, not a tamper-proof record: a mail that the deputy sends past the middleware, e.g. directly over SMTP, gets no copy, and neither does a mail whose Message-ID a mail in the granting user's Sent folder already has. A copy that fails for good does not affect the sent mail; it is logged with level WARN. Copies yet to be made are not persisted: if the middleware node that sent the mail stops before, the copy is not made.

When the copy is made

The copy is made if all of the following applies:

Requirement Details
The copy is enabled com.openexchange.deputy.sentCopyToGranterEnabled is not set to false for the granting user, neither when the deputy sends nor when the copy is due.
Access to the granting user's mailbox The primary mail account of the granting user is an IMAP account, and the granting user's offline grant, an acting user login of the deputy or one of the strategies in com.openexchange.mail.admin.strategies applies to the granting user, see Through the granting user's offline grant, Through an acting user login of the deputy and the table below. Granting sentCopyToGranter is rejected with DEPUTY-0018 if none applies at that time.
Send through the deputy's primary mail account The deputy sends through their primary mail account, with the granting user's address as From, based on a deputy permission that grants sendOnBehalfOf or sendAs, and sentCopyToGranter. The granting user is the one the check of the From address before the send finds. If that user belongs to another context, the copy is only made if no other user who appointed the deputy carries the address; otherwise no copy is made, and this is logged with level WARN.
Copies of sent mails are not switched off by configuration com.openexchange.mail.noCopyIntoStandardSentFolder is not set to true for the deputy. Granting sentCopyToGranter is not rejected if it is: the check on granting looks at the granting user only. The deputy's own setting not to keep copies does not prevent the copy, see above.
Personal namespace If no Sent folder full name is stored with the granting user's primary mail account, com.openexchange.deputy.provider.imap.doveadm.personalNamespace needs to be set for the granting user, whatever strategy applies.
Sent folder of the granting user's own The Sent folder stored with the granting user's primary mail account is not below com.openexchange.deputy.provider.imap.doveadm.sharedNamespace or com.openexchange.deputy.provider.imap.doveadm.publicNamespace, where these are set, i.e. not a folder of another user or a public one, whatever strategy applies. The middleware does not put copies there. Both are empty by default; without them, such a folder is not recognized.

A mail that goes out to some of its recipients only, as com.openexchange.smtp.sendPartial allows when the mail server refuses others, is copied as well.

If a requirement is not met, no copy is made. This is logged as follows:

Case Log level
Sent through another than the deputy's primary mail account; the other mails listed below as getting no copy, unless named in this table none
com.openexchange.mail.noCopyIntoStandardSentFolder set for the deputy DEBUG
com.openexchange.deputy.sentCopyToGranterEnabled set to false for the granting user none; INFO for a copy still to be made
Neither the offline grant nor any of the strategies applies to the granting user WARN, at most once a minute
The Sent folder stored with the granting user's primary mail account is a folder of another user or a public one WARN
An address that several users who appointed the deputy carry, with the one found for it in another context WARN
A mail without Message-ID; with doveadm, a mail that did not get into the deputy's Sent folder WARN
personalNamespace is needed, but not set WARN
With doveadm, the name of the granting user's or the deputy's Sent folder contains * or % WARN
200 copies are being made or wait for a further try on the middleware node already WARN, at most once a minute
20 copies for the same granting user are being made or wait for a further try on the middleware node already WARN, at most once a minute
The thread pool of the middleware node does not take the copy or a further try WARN

The first strategy in the order of com.openexchange.mail.admin.strategies that applies to the granting user is used; by default the order is token,doveadm,master. doveadm only counts where com.openexchange.deputy.sentCopyToGranterDoveAdmEnabled is set for the granting user (default false); otherwise the next strategy in the order is used. If the copy fails with that strategy, the middleware does not fall back to the next one; a further try uses the strategy that applies at that time. Neither the capability nor the check on granting looks at whether that strategy can make the copy, e.g. whether DoveAdm reaches the deputy's mailbox. The strategies that apply to the deputy are not looked at: with doveadm, reading the mail from the deputy's Sent folder relies on the strategy of the granting user alone.

Strategy Applies if How the copy is made
token The mail credential vault keeps an OAuth token for the granting user, see com.openexchange.mail.admin.token.vaultFeatures (empty by default). A token that a provisioning request brings along does not count: it is gone by the time the deputy sends. If no token is kept any more, e.g. since its refresh is rejected, the next strategy in the order applies; if none does, no copy is made while the deputy permission still asks for it, which is logged with level WARN. The middleware appends the mail to the granting user's Sent folder over IMAP. The deputy's Sent folder is not needed.
doveadm DoveAdm is enabled, see com.openexchange.dovecot.doveadm.enabled, and com.openexchange.deputy.sentCopyToGranterDoveAdmEnabled is set for the granting user. Dovecot copies the mail from the deputy's Sent folder; the copy is marked as read. Both mailboxes need to be on the same Dovecot instance.
master com.openexchange.mail.passwordSource is global, and mail access does not use OAuth. The middleware then logs in with com.openexchange.mail.masterPassword. Like token.

A deputy of another context gets the copy made the same way; with doveadm, both mailboxes need to be on the same Dovecot instance as well.

Through the granting user's offline grant

Where the granting user logs in through OpenID Connect and reaches mail by OAuth, the copy can go through the granting user's offline grant instead of administrative mail access (see Background mail access). It is mode grant of com.openexchange.deputy.sentCopyToGranterModes (default grant,acting; for acting, see Through an acting user login of the deputy). The modes are tried in their order ahead of the strategies of com.openexchange.mail.admin.strategies; the first that copies the mail wins, one that does not apply or is refused leaves the copy to the next.

Step What happens
Capability deputy_sent_copy is granted where the granting user's OpenID Connect back-end offers the offline grant (com.openexchange.oidc.offlineGrantEnabled), even before it is authorized.
Granting When the granting user switches sentCopyToGranter on in their own session, the mail credential vault keeps a credential of feature deputy-sent-copy that refers to the grant: one per granting user, for all deputies. Without a grant, the request fails with MCRED-0014, and the client asks the user to authorize it (popup offline_grant?flow=authorize) and repeats the request. If a strategy applies, the copy is granted all the same and goes through that strategy until the user authorizes. A grant authorized before, e.g. for scheduled mail, serves without asking again. Administrative provisioning (SOAP, SCIM, gRPC) keeps no credential; the strategies make the copy then.
Copy The copy is appended to the granting user's standard Sent folder, marked as read, through a mail access of the granting user's own made from that credential. The folder is determined from the stored account and settings alone, as for the strategies, but nothing is looked up in the mailbox and no folder is created: the grant's token may be narrowed by the mail server to looking up and inserting. For the same reason nothing is read: the copy is appended once, without looking for it in the Sent folder before or after, so a mail whose Message-ID is there already gets a copy all the same, and the copy carries no user flags. A failure before the mail is handed to the mail server is tried again as above. After a failure with unknown outcome, e.g. a connection lost while the mail is being appended, it is not tried again, as a second copy could be the result; this is logged with level WARN.
Fall-through If the grant is gone, rejected or revoked, the credential cannot be used any more (e.g. after the encryption key changed), the login is refused, the mailbox is over quota, the mail server refuses the copy for the grant's rights, or the granting user's standard Sent folder does not exist (no folder is created), the copy goes through the strategies; this is logged with level INFO, as is a failure that kept recurring until the attempts above were exhausted, which falls through the same way. Where doveadm stands by for the granting user, the mail is kept in the deputy's Sent folder as for a copy through DoveAdm, so that the fall-through can copy it from there.
Withdrawing Once no deputy permission of the granting user asks for the copy any more, the credential is released: when the granting user withdraws the copy or the right to send, when the last permission asking for it is removed, also administratively or because the deputy was deleted, and, where one was left behind, e.g. by a withdrawal on a node of the previous version, when the granting user's own listing of their deputy permissions runs next. While the credential is kept, the grant does not expire; once it is released, the grant expires when unused again (com.openexchange.mail.credential.oauth.offlineGrantIdleTime).

With the narrowing of the grant's tokens at Dovecot, the Sent folder falls under the entry for mailbox *, which gives lisw; a deployment that narrows further needs an entry that grants is on the Sent folder.

Nodes of the previous version do not know the property and copy through the strategies as before. The credential is a row like those of scheduled mail, which they read as such. A withdrawal that runs on such a node does not release the credential; the granting user's next change to a deputy permission or their next listing of them on a node of this version does.

Through an acting user login of the deputy

The deputy is the one sending, so the deputy's own credentials are at hand when the copy is due. With mode acting of com.openexchange.deputy.sentCopyToGranterModes, the middleware logs in to the granting user's mailbox as the deputy, with an acting user login as shared accounts use it (see Acting User Login), and appends the copy there. It needs neither a token nor a password of the granting user and no master password, and covers what the offline grant cannot: password logins, deputy permissions granted over SCIM, SOAP or by an administrator, and granting users who do not authorize the grant.

Step What happens
Configuration An acting user login has to be configured: com.openexchange.mail.actingUser.masterUserSeparator, or com.openexchange.mail.actingUser.authorizationId.enabled for password logins. The mode applies only then. It needs credentials of the deputy's own: where the deputy's mail access uses the master password (com.openexchange.mail.passwordSource=global), no acting user login is tried and the copy goes through the strategies.
Capability and granting deputy_sent_copy is granted where the mode is configured for the granting user and an acting user login is configured. Granting sentCopyToGranter is not rejected with DEPUTY-0018 then, and MCRED-0014 is not required either: there is no session of a deputy to try the login with at that time, so a login the mail server refuses shows only when a copy is due.
Sending When a deputy sends a mail that gets the copy, the mail credential vault keeps a copy of the deputy's credential of feature deputy-acting-copy for at most 10 minutes, so that the copy can be made after the deputy logged out. It holds the session password, or the OAuth access token alone: the copy is never refreshed, as that would rotate the refresh token the deputy's session still uses. It is released as soon as the copy is done with. Where a token exchange is configured for the feature (see Mail credential vault), the exchanged tokens are kept in full.
Copy The middleware logs in to the granting user's mailbox as <granting user's login><separator><deputy's login>, or as the deputy with the granting user's login as authorization identity, and appends the copy to the granting user's standard Sent folder, marked as read. As with the offline grant, the folder is determined from the stored account and settings alone, nothing is read or searched in the mailbox and no folder is created, since the mail server may narrow the login to inserting: the copy is appended once, a mail whose Message-ID is there already gets a copy all the same, and after a failure with unknown outcome it is not tried again (level WARN).
Fall-through If the mail server refuses the login, e.g. since it admits no deputies or the deputy's access token has expired by the time of a further try, if nothing could be kept of the deputy's session, the mailbox is over quota, or the granting user's standard Sent folder does not exist, the copy goes through the strategies; this is logged with level INFO. A failure that may pass, e.g. a mail server that cannot be reached, leaves the copy to the next mode as well; if none copies the mail, it is tried again later, starting with the first mode.

The mail server decides whether a deputy may log in to the granting user's mailbox. A static master passdb that admits acting user logins from the middleware nodes only, as described for shared accounts, lets the deputy's login through without further configuration. A master passdb that asks the middleware (GET /preliminary/mail/acting/v1/grant) is told of deputies only if com.openexchange.deputy.sentCopyToGranterActingAclGroup names an ACL group, which the grant then carries with source deputy: such a passdb admits acting user logins with any IMAP client, and a group the mail server has no ACL entries for would leave the deputy the rights of the mailbox's owner. Set the property only once the mail server withholds everything but inserting from that group, on all folders of the granting user. The grant is for the middleware alone ("middlewareOnly": true), so that a deputy cannot insert mails into the granting user's folders with an IMAP client of their own, and the middleware sees to that itself: right before it connects, it issues a ticket for that one login and sends it in the IMAP ID field x-ox-acting-ticket. The passdb has to hand it back as ticket when it asks for the grant; without the ticket issued for that deputy and granting user the end-point answers 204. A ticket is a random value kept for 60 seconds and redeemed once. With Dovecot, imap_id_retain = yes makes the ID available to the passdb as %{client_id}, which also has to be part of the passdb's cache key, so that a cached grant is not reused for a login without the ticket; within auth_cache_ttl a login repeating the same ticket is admitted from the cache, so keep that time short and the connection between middleware and mail server encrypted. Narrowing such logins to the addresses of the middleware nodes on top is optional; it has to go by the address the connection really comes from (Dovecot: allow_real_nets), since the middleware passes the address of its client on to a mail server that trusts it. The grant is given to deputies whose permission grants sentCopyToGranter together with a right to send, while the copy is enabled and mode acting is configured for the granting user; a grant that gives real access to the mailbox, such as a shared account permission, takes precedence over it.

The group needs the rights to look up (l), to insert (i) and to keep the \Seen flag (s), and nothing else: the middleware lists the folders when it connects, which shows their names only, while opening a folder, reading and creating stay refused. With Dovecot 2.4 and a group named deputy-sent-copy:

namespace private {
  mailbox * {
    acl "group=deputy-sent-copy" {
      rights = -rwtpekxa
    }
  }
}
namespace shared {
  acl "group=deputy-sent-copy" {
    rights = -lrwstipekxa
  }
}

The entry for the shared namespace keeps the deputy out of the folders other users share with the granting user. The entries cover all folders rather than the Sent folder alone, since its name differs from user to user.

A mail a deputy schedules is sent with a credential the vault keeps for the scheduled send and releases right afterwards. The copy of that credential goes with it, so for scheduled mails the acting user login may be refused by the time the copy is made; the copy then goes through the strategies.

Nodes of the previous version ignore acting in the property and copy through the offline grant or the strategies as before. Nothing shared changes format.

No copy is made for mails sent through a secondary or shared mail account, for mails sent as raw MIME (mail?action=new with PUT), resent (mail?action=resend) or bounced (mail?action=bounce), for mails the calendar sends for the granting user, such as invitations, changes and cancellations a deputy sends on their behalf, for mails from an address that several users who appointed the deputy carry if the one found for it belongs to another context (see above), and, with doveadm, if the mail did not get into the deputy's Sent folder.

The attribute is set next to sendOnBehalfOf and sendAs through the HTTP API, the SOAP end-point (element sentCopyToGranter, appended after sendAs), gRPC (sent_copy_to_granter when granting, sentCopyToGranter with SentCopyToGranterSet when updating) and SCIM, and is reported back by the listing actions. E.g.:

{
  "userId": 4,
  "sendOnBehalfOf": true,
  "sentCopyToGranter": true,
  "modulePermissions": {
    "mail": {
      "permission": 257
    }
  }
}

The attribute is stored in the new column sentCopyToGranter of table deputy. The previous version does not know the column, so during a rolling upgrade nodes of that version make no copy of the mails sent through them, a deputy permission they re-create (com.openexchange.deputy.preferRecreateInsteadOfUpdate) loses it, and a right to send they withdraw leaves sentCopyToGranter stored. Nodes of this version treat such a stored copy as withdrawn: they neither make nor list it, and a right to send granted again through them does not bring it back; one granted again through a node of the previous version does, without that node showing it. Grant sentCopyToGranter only once all nodes run this version.

Requirements

To grant deputy permission to the primary mail account's Inbox folder, the mail account is required to be an IMAP account that supports the RFC 2086 ACL and RFC 5464 METADATA extensions, and supports the /shared/vendor/vendor.open-xchange/deputy METADATA key.

For further reading on METADATA and METADATA keys, read for example the Dovecot IMAP METADATA documentation

To grant deputy permission for the Calendar, Contacts or Tasks module, the granting user additionally needs the readcreatesharedfolders module access (capability read_create_shared_folders) besides the access for the module itself. These grants are applied to the granting user's own private folders through the regular folder update path, which rejects sharing a private folder by a user lacking that access. A module the granting user cannot share is not offered for a deputy permission; requesting it anyway is answered with DEPUTY-0006 ("Deputy provider disabled for module ..."). This does not apply to Drive.

Access combinations tailored to functional mailboxes frequently omit readcreatesharedfolders - if a deputy permission for Calendar, Contacts or Tasks is expected but unavailable, check the granting user's access combination first.

Provisioning

With v8.29 of the Open-Xchange Server, deputy permissions can also be managed through the "http://soap.admin.openexchange.com/OXDeputyPermissionsService" SOAP end-point.

To set module permissions of the calendar module, the module id calendar can be used within respective modulePermissions element. For the mail module, this would be identifier mail. The optional sendAs element (next to sendOnBehalfOf, appended at the end of the element sequence) lets the deputy send E-Mails as the granting user as described above. The optional sentCopyToGranter element, appended after sendAs, gives the granting user a copy of the mails sent for them as described above. The optional classifiedAccess element of the deputy permission (none or confidential, next to sendOnBehalfOf) grants the deputy access to the granting user's confidential appointments in the covered calendar folders as described above; it has no effect on other modules. Like through the HTTP API, an unknown value is rejected (as invalid data) rather than being interpreted as none, and a level that cannot be granted fails with DEPUTY-0014.

However, using that SOAP API requires that primary mail server is a Dovecot IMAP server with DoveAdm REST API enabled. Hence, the Middleware's connector for that DoveAdm REST API needs to be enabled.

Example doveadm.properties file:

# Enable
com.openexchange.dovecot.doveadm.enabled=true

# Connection settings
com.openexchange.dovecot.doveadm.endpoints=https://127.0.0.1:8080/doveadm/v1
com.openexchange.dovecot.doveadm.endpoints.totalConnections=100
com.openexchange.dovecot.doveadm.endpoints.maxConnectionsPerRoute=0 (max. connections per route is then determined automatically by specified end-points)
com.openexchange.dovecot.doveadm.endpoints.readTimeout=20000
com.openexchange.dovecot.doveadm.endpoints.connectTimeout=5000

# Secret
com.openexchange.dovecot.doveadm.apiSecret=secret

Since DoveAdm REST API does not provide querying the namespace information for the folder prefixes for personal, shared/user and public namespaces, those prefixes need to be manually specified through following properties to leverage additional features such as auto-subscription/auto-unsubscription of shared/unshared folders for the target user:

  • com.openexchange.deputy.provider.imap.doveadm.personalNamespace
  • com.openexchange.deputy.provider.imap.doveadm.sharedNamespace
  • com.openexchange.deputy.provider.imap.doveadm.publicNamespace

Example for such a section in deputy.properties file:

com.openexchange.deputy.provider.imap.doveadm.personalNamespace=/
com.openexchange.deputy.provider.imap.doveadm.sharedNamespace=shared/
com.openexchange.deputy.provider.imap.doveadm.publicNamespace=public/

Granting a Cross-Context Deputy via SOAP

A deputy can also be appointed when the deputy resides in a different context than the granting user, subject to the deployment-wide trust-zone policy. This uses the very same grant operation of the OXDeputyPermissionsService as a regular deputy - the only difference is that the deputy's context is supplied explicitly:

  • the context and user elements identify the granting user, whose calendar and/or inbox is delegated;
  • the deputyPermission identifies the deputy by userId, and - for a cross-context deputy - additionally by contextId, the context the deputy resides in.

A positive contextId that differs from the granting user's context marks the deputy as cross-context; omitting it (or supplying 0) keeps the regular same-context behavior. Such a grant is admitted only if the trust zones of the granting user's context and the deputy's context intersect, otherwise it is rejected by the cross-context authority.

The following request lets user 4 in context 1 appoint user 7 from context 5 as a deputy, with read-write access to the calendar and read access to the inbox plus "send on behalf of". The per-module values are the standard App Suite folder/object permission bits (e.g. 2 = read, 4 = read/write/delete all, 8 = create subfolders, 128 = admin):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://soap.admin.openexchange.com" xmlns:xsd="http://dataobjects.soap.admin.openexchange.com/xsd" xmlns:xsd1="http://dataobjects.rmi.admin.openexchange.com/xsd">
  <soapenv:Header/>
  <soapenv:Body>
    <soap:grant>
      <soap:deputyPermission>
        <xsd:userId>7</xsd:userId>
        <xsd:contextId>5</xsd:contextId>
        <xsd:sendOnBehalfOf>true</xsd:sendOnBehalfOf>
        <xsd:classifiedAccess>confidential</xsd:classifiedAccess>
        <xsd:modulePermissions>
          <xsd:moduleId>calendar</xsd:moduleId>
          <xsd:folderPermission>4</xsd:folderPermission>
          <xsd:readPermission>4</xsd:readPermission>
          <xsd:writePermission>4</xsd:writePermission>
          <xsd:deletePermission>4</xsd:deletePermission>
          <xsd:admin>false</xsd:admin>
        </xsd:modulePermissions>
        <xsd:modulePermissions>
          <xsd:moduleId>mail</xsd:moduleId>
          <xsd:folderPermission>2</xsd:folderPermission>
          <xsd:readPermission>4</xsd:readPermission>
          <xsd:writePermission>0</xsd:writePermission>
          <xsd:deletePermission>0</xsd:deletePermission>
          <xsd:admin>false</xsd:admin>
        </xsd:modulePermissions>
      </soap:deputyPermission>
      <soap:context>
        <xsd:id>1</xsd:id>
      </soap:context>
      <soap:user>
        <xsd:id>4</xsd:id>
      </soap:user>
      <soap:auth>
        <xsd1:login>oxadmin</xsd1:login>
        <xsd1:password>secret</xsd1:password>
      </soap:auth>
    </soap:grant>
  </soapenv:Body>
</soapenv:Envelope>

The call returns the identifier of the newly granted deputy permission. The auth credentials are the administrative credentials for the granting user's context (or the master admin). A regular, same-context deputy is granted with the identical request, simply leaving out the contextId element.

Entity information in deputy listings

The deputy HTTP API listing endpoints enrich every returned permission with an entityInfo block — the same server-resolved display information (identifier, type, display_name, contact.email1, …) that the Shared Accounts API provides — so a client can render a deputy (and, in the reverse listing, the grantor) without resolving the user itself.

This is primarily aimed at cross-context entities: when a deputy or grantor lives in a different context, its bare numeric user id (userId / grantorId, reported as 0) is meaningless in the requesting user's context and the client has no directory to resolve it against. For such a foreign entity the qualified identifier (<id>@<contextId>) is the stable key, and the bare numeric entity is omitted from entityInfo. For a group deputy no entityInfo is emitted, as a group is always context-local and thus resolvable by the client itself.

  • GET /deputy?action=all (the deputies granted by the session user) — each entry carries an entityInfo block describing the deputy entity (the user appointed as deputy).
  • GET /deputy?action=reverse (who appointed the session user as a deputy) — each entry additionally carries a grantorEntityInfo block describing the granting user; the entry's own entityInfo continues to describe the deputy entity (here: the requesting user).

Example action=reverse entry for a cross-context grantor — the bare grantorId is masked to 0, and the grantor is identified and rendered solely from the qualified grantorIdentifier and the resolved grantorEntityInfo:

{
  "deputyId": "d3a1b2c4-…",
  "grantorId": 0,
  "grantorIdentifier": "4@1",
  "grantorEntityInfo": {
    "identifier": "4@1",
    "type": "user",
    "display_name": "Granting User",
    "contact": { "email1": "grantinguser@example.org" }
  },
  "sendOnBehalfOf": true
}