Back to API Reference

Email Authentication API (Microsoft Graph)

Connect Microsoft 365 / Outlook accounts to send emails through DataPublisher using Microsoft Graph API.

---

Base URL

https://app.datapublisher.io/api/email/auth

---

Authentication

All endpoints require JWT authentication via Authorization: Bearer header.

---

Overview

The Email Authentication API allows you to:

-Store and refresh access tokens securely

Supported Providers:

Required Scopes:

---

OAuth2 Flow

Step 1: Initiate Connection

Start the OAuth2 authorization flow.

Endpoint: GET /microsoft/connect

Headers:

Authorization: Bearer 

Response (200 OK):

{

"authUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=...&redirect_uri=...&response_type=code&scope=Mail.Send%20offline_access%20User.Read&state=abc123def456"

}

Usage:

  • Call this endpoint from your application
  • Open authUrl in browser or Office dialog
  • User logs into Microsoft
  • User grants permissions
  • Microsoft redirects to callback URL
  • ---

    Step 2: OAuth2 Callback (Automatic)

    Microsoft redirects to this endpoint after authorization. This is called automatically by Microsoft - you don't need to call it directly.

    Endpoint: GET /microsoft/callback

    Query Parameters (from Microsoft):

    Response (200 OK):

    Process:

  • Validates state parameter (CSRF protection)
  • Exchanges authorization code for tokens
  • Retrieves user's email address from Graph API
  • Stores access_token and refresh_token encrypted in database
  • Calculates token expiration time
  • Returns success page that auto-closes
  • Database Storage:

    email_providers table:
    
    • user_id: User UUID
    • provider: 'microsoft'
    • email_address: User's email
    • access_token: Encrypted access token
    • refresh_token: Encrypted refresh token (for auto-renewal)
    • token_expires_at: Token expiration timestamp
    • scopes: JSON array of granted scopes
    • is_active: Connection status

    ---

    Email Provider Management

    Get Connected Email Accounts

    List all connected email accounts for the user.

    Endpoint: GET /providers

    Headers:

    Authorization: Bearer 

    Response (200 OK):

    {
    

    "success": true,

    "providers": [

    {

    "id": "uuid",

    "provider": "microsoft",

    "emailAddress": "user@company.com",

    "isActive": true,

    "tokenExpiresAt": "2026-02-13T10:00:00Z",

    "scopes": ["Mail.Send", "offline_access", "User.Read"],

    "connectedAt": "2026-02-01T09:00:00Z",

    "lastUsedAt": "2026-02-12T08:30:00Z"

    }

    ],

    "count": 1

    }

    ---

    Disconnect Email Account

    Remove email account connection and revoke tokens.

    Endpoint: DELETE /providers/:providerId

    Headers:

    Authorization: Bearer 

    Response (200 OK):

    {
    

    "success": true,

    "message": "Email account disconnected successfully"

    }

    Notes:

    ---

    Refresh Access Token (Automatic)

    Access tokens automatically refresh when expired. This happens invisibly when sending emails.

    Process:

  • Before sending email, check if token expired
  • If expired, use refresh_token to request new access_token
  • Update database with new tokens
  • Proceed with email sending
  • Token Lifetimes:

    ---

    Sending Emails

    Send Email via Connected Account

    Endpoint: POST /send

    Headers:

    Authorization: Bearer 
    

    Content-Type: application/json

    Request Body:

    {
    

    "providerId": "uuid",

    "to": ["recipient@example.com"],

    "cc": ["cc@example.com"],

    "bcc": ["bcc@example.com"],

    "subject": "Email Subject",

    "bodyHtml": "

    Hello

    Email content

    ",

    "bodyText": "Hello\n\nEmail content (plain text fallback)",

    "attachments": [

    {

    "name": "document.pdf",

    "contentBytes": "base64-encoded-file-content",

    "contentType": "application/pdf"

    }

    ],

    "importance": "normal",

    "trackingId": "optional-tracking-uuid"

    }

    Response (200 OK):

    {
    

    "success": true,

    "messageId": "microsoft-message-id",

    "sentAt": "2026-02-12T10:30:00Z"

    }

    Error Responses:

    401 Unauthorized - Token expired or invalid:
    {
    

    "success": false,

    "error": "Email account not connected or token expired"

    }

    400 Bad Request - Missing required fields:
    {
    

    "success": false,

    "error": "Missing required fields: to, subject, bodyHtml"

    }

    ---

    Security Features

    Token Encryption

    CSRF Protection

    Scope Minimization

    Only requests necessary scopes:

    Does NOT request:

    ---

    Office Add-in Integration

    Connect Email in Task Pane

    // In Office Add-in task pane
    

    async function connectEmailAccount() {

    try {

    // Get auth URL from API

    const response = await fetch('https://app.datapublisher.io/api/email/auth/microsoft/connect', {

    headers: {

    'Authorization': Bearer ${jwtToken}

    }

    });

    const { authUrl } = await response.json();

    // Open auth dialog (Office.js)

    Office.context.ui.displayDialogAsync(authUrl, { height: 60, width: 30 }, (result) => {

    const dialog = result.value;

    // Listen for success message from dialog

    dialog.addEventHandler(Office.EventType.DialogMessageReceived, (arg) => {

    const message = JSON.parse(arg.message);

    if (message.status === 'success') {

    console.log('Email connected:', message.email);

    dialog.close();

    // Refresh email provider list

    loadEmailProviders();

    }

    });

    });

    } catch (error) {

    console.error('Error connecting email:', error);

    }

    }

    ---

    Microsoft Graph API Details

    Token Endpoint

    POST https://login.microsoftonline.com/common/oauth2/v2.0/token

    Authorization Endpoint

    GET https://login.microsoftonline.com/common/oauth2/v2.0/authorize

    Send Mail Endpoint (used internally)

    POST https://graph.microsoft.com/v1.0/me/sendMail

    ---

    Troubleshooting

    "Refresh token not found"

    Cause: Using MSAL.js client library (doesn't expose refresh tokens)

    Solution: Direct OAuth2 token endpoint call to get refresh token

    "Admin consent required"

    Cause: Organization requires admin approval for Mail.Send scope

    Solution: IT admin must pre-approve the app in Azure portal

    "Token expired" after 90 days

    Cause: User hasn't used email for 90+ days, refresh token expired

    Solution: User must re-connect email account

    ---

    Environment Configuration

    Required environment variables:

    Azure App Registration

    EMAIL_CLIENT_ID=your-client-id

    EMAIL_CLIENT_SECRET=your-client-secret

    EMAIL_TENANT_ID=common # Or specific tenant ID

    Redirect URI (must match Azure app registration)

    SERVER_URL=https://app.datapublisher.io

    Token encryption

    ENCRYPTION_KEY=32-byte-hex-string

    ---

    Rate Limiting

    ---

    Common Error Codes

    | Status Code | Description |

    |-------------|-------------|

    | 400 | Missing required parameters or invalid request |

    | 401 | Unauthorized - invalid JWT or expired email token |

    | 403 | Insufficient Microsoft permissions |

    | 404 | Email provider not found |

    | 429 | Too many requests (Microsoft throttling) |

    | 500 | Internal server error or Microsoft API error |

    ---

    Best Practices

  • Token Refresh: Access tokens refresh automatically - no action needed
  • Error Handling: Handle 401 errors by prompting user to reconnect
  • Multiple Accounts: Allow users to connect multiple email accounts
  • Scope Requests: Only request minimum necessary scopes
  • Testing: Test with both personal Outlook.com and Office 365 accounts
  • Revocation: Provide clear UI for users to disconnect accounts
  • Privacy: Don't store email content, only metadata and tracking
  • ---

    Related Documentation