Portal Community
Best For Low-volume transactional email, testing, development, organizations using Google Workspace.

Gmail OAuth2 Parameters

ParameterTypeRequiredExample
providerstringgmail
fromEmailstringuser@gmail.com
fromNamestringYour App

OAuth2 Setup

1. Create Google Cloud Project

1. Go to Google Cloud Console (console.cloud.google.com)
2. Create new project: "BizFirst Email"
3. Enable Gmail API
4. Create OAuth2 credentials (Desktop app type)
5. Download JSON credentials

2. Get Authorization Code

// First-time only: Get user consent
GET https://accounts.google.com/o/oauth2/v2/auth?
  client_id=YOUR_CLIENT_ID
  scope=https://www.googleapis.com/auth/gmail.send
  redirect_uri=http://localhost:8080/callback
  response_type=code

3. Exchange Code for Tokens

POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded

code=AUTH_CODE
client_id=YOUR_CLIENT_ID
client_secret=YOUR_CLIENT_SECRET
redirect_uri=http://localhost:8080/callback
grant_type=authorization_code

Response:
{
  "access_token": "ya29.xxx",
  "expires_in": 3600,
  "refresh_token": "1//xxx",
  "scope": "https://www.googleapis.com/auth/gmail.send",
  "token_type": "Bearer"
}

4. Create Credential in Database

Choose a credential name (e.g., "email-primary", "email-gmail", etc.). Configure which name each tenant uses via TenantSettings with Key='EmailCredentialName'.

INSERT INTO AIExt_Credentials (
  Name, DisplayMetadata, EncryptedData, TenantID, CredentialTypeID
) VALUES (
  'email-primary',  -- Or any name you configure in TenantSettings
  '{
    "provider": "gmail",
    "fromEmail": "user@gmail.com",
    "fromName": "Your Company"
  }',
  0x...,  -- Encrypted: {accessToken, refreshToken, expiresAt}
  1, 3    -- OAuth2Record type
);

Automatic Token Refresh

The system automatically refreshes expired tokens. Store refresh_token securely:

// Stored in encrypted credential
{
  "accessToken": "ya29.current_token",
  "refreshToken": "1//refresh_token_here",
  "expiresAt": "2026-05-28T14:30:00Z"
}

When access token expires, the system uses refresh_token to obtain a new one.

Quota Limitations

Testing

// Resolve credential name from TenantSettings (defaults to "email-primary")
var credentialName = await _tenantSettingsService.GetAsync<string>(
    1, "EmailCredentialName", "email-primary", CancellationToken.None);

var result = await _emailService.SendAsync(
    tenantID: 1,
    to: "test@example.com",
    subject: "Gmail Test",
    html: "<p>Gmail OAuth2 working!</p>",
    credentialName: credentialName,
    ct: CancellationToken.None);

Next Steps