Shared Mailboxes (Microsoft 365)
Microsoft 365 shared mailboxes are mailboxes not bound to a specific user. Multiple users can access them using their own credentials. EmailEngine supports two approaches for accessing shared mailboxes.
Two Approaches to Shared Mailboxes
Option 1: Direct Access (Simpler)
Add the shared mailbox directly with its own OAuth2 credentials and mark it as shared.
Best for:
- Single shared mailbox setups
- Testing and evaluation
- Simple use cases
How it works:
- User authenticates with the shared mailbox through OAuth2
- EmailEngine marks the account as shared
- Account appears as a regular account in EmailEngine
Option 2: Delegated Access (Recommended)
Add a main account normally, then add shared mailboxes that reference the main account's credentials.
Best for:
- Multiple shared mailboxes accessed by the same user
- Production environments
- Better credential management
How it works:
- Add the main user account with OAuth2
- Add shared mailbox accounts that reference the main account
- EmailEngine uses the main account's credentials to access shared mailboxes
Use delegated access for production. It's more flexible and allows one user to access multiple shared mailboxes without re-authenticating.
Prerequisites
Before setting up shared mailboxes in EmailEngine:
- Azure AD OAuth2 Application configured for Microsoft 365
- See the Outlook OAuth2 Setup Guide for detailed instructions
- Shared Mailbox Permissions - User must have access to the shared mailbox in Microsoft 365
- EmailEngine OAuth2 Configuration - Your Outlook OAuth2 app must be configured in EmailEngine
Both IMAP/SMTP and Microsoft Graph API backends support shared mailboxes, but Graph API provides better native support.
Microsoft Graph API Scopes
If using the Microsoft Graph API backend, you must add additional scopes to your OAuth2 application.
Step 1: Add scopes in Azure Portal
- Log in to Azure Portal and navigate to your app registration
- Go to API Permissions > Add a permission > Microsoft Graph > Delegated permissions
- Add these scopes:
| Scope | Purpose |
|---|---|
User.ReadBasic.All | Read basic profile information of users in the organization. Required to resolve the shared mailbox identity. |
Mail.ReadWrite.Shared | Read and write mail in shared mailboxes the user has access to. Without this, only the user's own mailbox is accessible. |
Mail.Send.Shared | Send mail from shared mailboxes. Required to send emails on behalf of the shared mailbox. |
Step 2: Add scopes in EmailEngine
- In EmailEngine, navigate to your OAuth2 application settings
- Find the Additional Scopes field
- Add the same scopes:
User.ReadBasic.All
Mail.ReadWrite.Shared
Mail.Send.Shared - Save the changes
Step 3: Refresh OAuth2 grant
Existing accounts need to re-authenticate to get the new permissions. Either:
- Re-add the account - Delete and re-add the main account in EmailEngine
- Generate new auth link - Use the Authentication Form API with the existing account ID to generate a new authentication URL. The user must open this link and grant the new permissions.
Option 1: Direct Access Setup
Via Hosted Authentication Form
Use the hosted authentication form with the delegated flag:
curl -X POST https://your-ee.com/v1/authentication/form \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-support",
"name": "Support Mailbox",
"email": "support@company.com",
"delegated": true,
"redirectUrl": "https://myapp.com/settings",
"type": "AAABiCtT7XUAAAAF"
}'
Fields:
account: Account ID you want to use in EmailEnginename: Display name for the shared mailboxemail: Email address of the shared mailbox (e.g.,support@company.com)delegated: Must betrue- indicates the authenticating user is not the mailbox ownerredirectUrl: Where to redirect after authenticationtype: OAuth2 application ID from EmailEngine
Authentication Flow:
- User visits the generated authentication URL
- User signs in with their own Microsoft 365 account (not the shared mailbox)
- This account must have access to the shared mailbox in Microsoft 365
- EmailEngine stores the credentials associated with the shared mailbox email
- The shared mailbox appears in EmailEngine with the shared mailbox address
The authenticating user must already have permissions to access the shared mailbox in Microsoft 365. Otherwise, authentication will succeed but EmailEngine won't be able to access the mailbox.
Via Direct API
If you're managing OAuth2 tokens externally:
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-support",
"name": "Support Mailbox",
"email": "support@company.com",
"oauth2": {
"provider": "AAABlf_0iLgAAAAQ",
"auth": {
"user": "admin@company.com",
"delegatedUser": "support@company.com"
},
"accessToken": "EwBIA8l6...",
"refreshToken": "M.R3_BAY..."
}
}'
Key fields:
oauth2.auth.user: Email address of the user whose credentials are being used (the user with access)oauth2.auth.delegatedUser: Email address or Microsoft 365 user ID of the shared mailbox being accessed
With direct access, if you authenticate shared@company.com using user@company.com, then you cannot use user@company.com to authenticate any other accounts, including their own primary account. This is a known limitation.
Use delegated access to work around this limitation.
Option 2: Delegated Access Setup (Recommended)
Delegated access allows you to add a main account once, then reference it when adding shared mailboxes.
Step 1: Add the Main User Account
First, add the main user account normally:
curl -X POST https://your-ee.com/v1/authentication/form \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "my-account",
"name": "John Doe",
"email": "john@company.com",
"redirectUrl": "https://myapp.com/settings",
"type": "AAABiCtT7XUAAAAF"
}'
The user completes OAuth2 authentication, and the account is added to EmailEngine.
Step 2: Add Shared Mailboxes Using Delegation
Now add shared mailboxes that reference the main account:
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-support",
"name": "Support Mailbox",
"email": "support@company.com",
"oauth2": {
"auth": {
"delegatedUser": "support@company.com",
"delegatedAccount": "my-account"
}
}
}'
Key fields:
oauth2.auth.delegatedUser: Email address or Microsoft 365 user ID of the shared mailboxoauth2.auth.delegatedAccount: EmailEngine account ID of the main user (from Step 1)
What happens:
- EmailEngine connects to Microsoft 365 as
support@company.com - Uses OAuth2 tokens from the main account
my-account - No additional authentication required
- Can add multiple shared mailboxes using the same main account
Adding Multiple Shared Mailboxes
With delegated access, you can easily add multiple shared mailboxes:
# Add support mailbox
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-support",
"name": "Support",
"email": "support@company.com",
"oauth2": {
"auth": {
"delegatedUser": "support@company.com",
"delegatedAccount": "my-account"
}
}
}'
# Add sales mailbox
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-sales",
"name": "Sales",
"email": "sales@company.com",
"oauth2": {
"auth": {
"delegatedUser": "sales@company.com",
"delegatedAccount": "my-account"
}
}
}'
# Add info mailbox
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-info",
"name": "Info",
"email": "info@company.com",
"oauth2": {
"auth": {
"delegatedUser": "info@company.com",
"delegatedAccount": "my-account"
}
}
}'
All three shared mailboxes use the same main account credentials (my-account).
Email Address vs UPN Mismatch
In Microsoft 365, a shared mailbox may have a public email address that differs from its User Principal Name (UPN). This commonly happens when:
- The organization uses a custom domain for email (e.g.,
shared@contoso.com) - The UPN uses the default Microsoft domain (e.g.,
sharedmailbox@contoso.onmicrosoft.com)
In this case, set the email field to the public address and use delegatedUser to specify the actual UPN.
With Direct Access
The hosted authentication form (/v1/authentication/form) does not support this scenario. Use the /v1/account endpoint instead.
Using OAuth2 authorization flow:
Request an authorization URL, then redirect the user to complete OAuth2:
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-support",
"name": "Support Mailbox",
"email": "shared@contoso.com",
"oauth2": {
"authorize": true,
"provider": "AAABlf_0iLgAAAAQ",
"redirectUrl": "https://myapp.com/settings",
"auth": {
"delegatedUser": "sharedmailbox@contoso.onmicrosoft.com"
}
}
}'
Response:
{
"redirect": "https://login.microsoftonline.com/..."
}
Redirect the user to the redirect URL. After they authenticate with their Microsoft account, they'll be redirected to your redirectUrl with the account created.
Using existing OAuth2 tokens:
If you manage OAuth2 tokens externally:
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-support",
"name": "Support Mailbox",
"email": "shared@contoso.com",
"oauth2": {
"provider": "AAABlf_0iLgAAAAQ",
"auth": {
"user": "admin@contoso.com",
"delegatedUser": "sharedmailbox@contoso.onmicrosoft.com"
},
"accessToken": "EwBIA8l6...",
"refreshToken": "M.R3_BAY..."
}
}'
With Delegated Access
When referencing another EmailEngine account for credentials:
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "shared-support",
"name": "Support Mailbox",
"email": "shared@contoso.com",
"oauth2": {
"auth": {
"delegatedUser": "sharedmailbox@contoso.onmicrosoft.com",
"delegatedAccount": "my-account"
}
}
}'
How It Works
email: The public email address (shared@contoso.com) - used in EmailEngine for display and as the From address when sendingdelegatedUser: The UPN (sharedmailbox@contoso.onmicrosoft.com) - used internally to access the mailbox via Microsoft Graph or IMAPdelegatedAccount: (optional) The main account whose OAuth2 credentials are used for authentication
This configuration ensures EmailEngine uses the correct public email address externally while accessing the mailbox through the proper Microsoft 365 UPN.
Backend-Specific Considerations
IMAP/SMTP Backend
IMAP Access:
- Works out of the box
- EmailEngine accesses shared mailbox emails via IMAP
SMTP Limitations:
- Shared mailboxes cannot authenticate directly via SMTP
- EmailEngine authenticates as the main user but sets the "From" address to the shared mailbox email
- Outlook SMTP automatically saves sent emails to the main account's "Sent Items" folder
- To ensure sent emails also appear in the shared mailbox, EmailEngine uploads a copy via IMAP to the shared mailbox's "Sent Items" folder
Microsoft Graph API Backend
Better Native Support:
- Shared mailboxes fully supported
- No SMTP authentication workarounds needed
- Emails are sent and managed directly as the shared mailbox
- Sent emails saved only in the shared mailbox's "Sent Items" (no duplicates)
Recommendation: Use Microsoft Graph API backend for shared mailboxes when possible.
Verifying Shared Mailbox Access
After adding a shared mailbox, verify it's working correctly:
- Check account state - Should be "connected" in EmailEngine
- Verify folders are loading - Check mailbox list API
- Test sending an email - Send a message from the shared mailbox
- Check webhooks - Ensure new message webhooks fire correctly
Check Account Status
curl https://your-ee.com/v1/account/shared-support \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Expected response:
{
"account": "shared-support",
"name": "Support Mailbox",
"email": "support@company.com",
"type": "delegated",
"state": "connected",
"oauth2": {
"auth": {
"delegatedUser": "support@company.com",
"delegatedAccount": "my-account"
}
}
}
Test Sending Email
curl -X POST https://your-ee.com/v1/account/shared-support/submit \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": [{"address": "test@example.com"}],
"subject": "Test from shared mailbox",
"text": "This is a test email"
}'
Comparison: Direct vs Delegated Access
| Feature | Direct Access | Delegated Access |
|---|---|---|
| Setup Complexity | Simpler | Slightly more complex |
| Multiple Shared Mailboxes | Requires re-auth for each | Reuses main account |
| Credential Management | Separate for each | Centralized |
| Main Account Access | Cannot be accessed | Fully accessible |
| Best For | Single mailbox, testing | Production, multiple mailboxes |
Delegated Send Access
Beyond shared mailboxes, delegated accounts can be used for scenarios where one account needs to send emails through another account's SMTP credentials. This is useful for:
- Transactional email accounts that share SMTP credentials
- Service accounts where multiple identities send through a common relay
- Organizations with centralized email sending infrastructure
How Delegation Works Internally
When you configure a delegated account, EmailEngine:
- Resolves the delegation chain - Follows
delegatedAccountreferences up to 20 hops (detecting loops) - Loads credentials from the parent account - Uses the OAuth2 tokens or IMAP/SMTP credentials from the referenced account
- Sets the identity from the delegated account - Uses the
emailanddelegatedUserfields to set the From address and IMAP user
Delegation Chain Resolution
EmailEngine supports chained delegation where account A references account B, which references account C. The resolution follows the chain until it finds an account with actual credentials:
Limits and safeguards:
- Maximum 20 hops in the delegation chain
- Loop detection prevents circular references
- Clear error messages when resolution fails
Configuring Delegated Send Access
Step 1: Create the parent account with credentials
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "smtp-relay",
"name": "SMTP Relay Account",
"email": "relay@company.com",
"smtp": {
"host": "smtp.company.com",
"port": 587,
"secure": false,
"auth": {
"user": "relay@company.com",
"pass": "smtp-password"
}
}
}'
Step 2: Create delegated accounts that use the parent's SMTP
# Sales team sends through the relay
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "sales-sender",
"name": "Sales Team",
"email": "sales@company.com",
"oauth2": {
"auth": {
"delegatedUser": "sales@company.com",
"delegatedAccount": "smtp-relay"
}
}
}'
# Support team sends through the same relay
curl -X POST https://your-ee.com/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "support-sender",
"name": "Support Team",
"email": "support@company.com",
"oauth2": {
"auth": {
"delegatedUser": "support@company.com",
"delegatedAccount": "smtp-relay"
}
}
}'
Step 3: Send emails from delegated accounts
# This uses smtp-relay credentials but sends from sales@company.com
curl -X POST https://your-ee.com/v1/account/sales-sender/submit \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": [{"address": "customer@example.com"}],
"subject": "Sales Inquiry",
"text": "Thank you for your interest..."
}'
Account Type and State
Delegated accounts show as type delegated in the API:
curl https://your-ee.com/v1/account/sales-sender \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response:
{
"account": "sales-sender",
"name": "Sales Team",
"email": "sales@company.com",
"type": "delegated",
"state": "connected",
"oauth2": {
"auth": {
"delegatedUser": "sales@company.com",
"delegatedAccount": "smtp-relay"
}
}
}
Troubleshooting Delegation Issues
"Missing account data for delegated account"
The referenced delegatedAccount doesn't exist:
# Verify the parent account exists
curl https://your-ee.com/v1/account/smtp-relay \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
"Delegation looping detected"
Circular reference in the delegation chain. For example:
- Account A references B
- Account B references C
- Account C references A (loop!)
Fix by breaking the loop - ensure one account has actual credentials without referencing another.
"Too many delegation hops"
The delegation chain exceeds 20 hops. Simplify your delegation structure.
Parent account authentication errors
If the parent account has authentication issues (expired tokens, changed password), all delegated accounts will fail. Monitor the parent account's state and fix authentication promptly.
Best Practices for Delegated Access
- Keep delegation chains short - Prefer direct references to the credential-holding account
- Monitor parent accounts - Authentication failures cascade to all delegated accounts
- Use descriptive names - Make it clear which accounts are parents vs. delegated
- Document relationships - Track which accounts depend on which credentials
- Test after credential changes - When rotating parent account credentials, verify delegated accounts still work
See Also
- Outlook OAuth2 Setup Guide - Setting up Azure AD OAuth2
- Account Management - Managing accounts in EmailEngine
- Microsoft Graph API - Using MS Graph backend
- Send-Only Accounts - SMTP-only configurations