# DigitalData.MessagingService A .NET 8 messaging service for sending and receiving emails via SMTP, IMAP, POP3 and OAuth2, with RabbitMQ-based async delivery. --- ## Email Account Configuration Each account is configured under `EmailAccounts.Accounts` in `appsettings.Secrets.json`. > Different providers require different configuration fields. See provider-specific sections below. ### Common fields (all providers) ```json { "Id": 1, "Username": "user@example.com", "Password": "your_password", "SmtpServer": "smtp.example.com", "SmtpPort": 465, "SmtpUseSsl": true, "UseOAuth2": false, "ImapServer": "imap.example.com", "ImapPort": 993, "ImapUseSsl": true, "Pop3Server": "pop.example.com", "Pop3Port": 995, "Pop3UseSsl": true, "IncomingProtocol": 1 } ``` > `Password` is always retained. When `UseOAuth2 = true`, SMTP/IMAP/POP3 connections use OAuth2 tokens > instead of the password. When `UseOAuth2 = false`, the password is used directly. > The `IncomingProtocol` field independently controls which protocol is used for receiving emails. #### `IncomingProtocol` values | Value | Meaning | |-------|---------| | `0` | None — send-only account, skipped by sync worker | | `1` | IMAP with username/password | | `2` | POP3 with username/password | | `3` | IMAP with OAuth2 | | `4` | POP3 with OAuth2 | #### `OAuth2Provider` values | Value | Meaning | |-------|---------| | `0` | None | | `1` | Microsoft (Azure AD / Microsoft 365) | | `2` | Google (Gmail / Google Workspace) | --- ## Provider-specific OAuth2 Configuration ### Google (Gmail / Google Workspace) Google uses **user-delegated OAuth2** (authorization code flow). A one-time interactive authorization is required to obtain a refresh token. The refresh token is then stored in the database and reused automatically for all subsequent operations. > The refresh token survives application restarts. It will not be overwritten by the seed process > unless `OAuth2RefreshToken` is explicitly set to a non-empty value in `appsettings.Secrets.json`. #### Required fields ```json { "UseOAuth2": true, "OAuth2ClientId": "YOUR_CLIENT_ID.apps.googleusercontent.com", "OAuth2ClientSecret": "GOCSPX-YOUR_CLIENT_SECRET", "OAuth2RefreshToken": "", "OAuth2TenantId": "", "OAuth2Provider": 2 } ``` #### Google Cloud Console setup (one-time) 1. Go to [console.cloud.google.com](https://console.cloud.google.com) and create or select a project. 2. Enable the **Gmail API** under *APIs & Services ? Library*. 3. Go to *APIs & Services ? Credentials* ? **+ Create Credentials** ? **OAuth 2.0 Client ID**: - Application type: **Web application** - **Authorized redirect URIs**: add `https://YOUR_HOST/api/oauth2/google/callback` (e.g. `https://localhost:7261/api/oauth2/google/callback` for local development) 4. Go to *APIs & Services ? OAuth consent screen*: - Add the Gmail account under **Test users** (required while app is in Testing mode). #### Obtaining the refresh token via the built-in authorization endpoint The application provides a built-in OAuth2 flow — no external tools needed. 1. Open a browser and navigate to: ``` GET /api/oauth2/google/authorize/{accountId} ``` Example: `https://localhost:7261/api/oauth2/google/authorize/3` 2. You will be redirected to Google's consent screen. If you see **"Google hasn't verified this app"**, click **Continue** — this is expected while the app is in Testing mode. 3. Sign in with the Gmail account and grant access. 4. Google redirects back to `/api/oauth2/google/callback` automatically. The application exchanges the authorization code for a refresh token and saves it to the database. 5. A success response is returned: ```json { "success": true, "username": "user@gmail.com", "message": "..." } ``` 6. The sync worker and all IMAP/SMTP operations will now work automatically. > ?? The refresh token must be re-obtained if `invalid_grant` is returned. > This happens if the token is unused for 6 months or if the user revokes access. --- ### Microsoft 365 / Exchange Online (Azure AD) Microsoft uses **application-level OAuth2** (client credentials flow — no user interaction required). Tokens are acquired automatically using the client ID, secret and tenant ID. No authorization endpoint needs to be visited. #### Required fields ```json { "UseOAuth2": true, "OAuth2ClientId": "YOUR_APP_CLIENT_ID", "OAuth2ClientSecret": "YOUR_APP_CLIENT_SECRET_VALUE", "OAuth2TenantId": "yourorg.onmicrosoft.com", "OAuth2Provider": 1 } ``` #### Azure Portal setup (one-time) 1. Go to [portal.azure.com](https://portal.azure.com) ? **Azure Active Directory** ? **App registrations** ? **+ New registration**. 2. Go to **Certificates & secrets** ? **+ New client secret** ? copy the **Value** (not the ID). - Set this as `OAuth2ClientSecret`. 3. Go to **API permissions** ? **+ Add a permission** ? **APIs my organization uses** ? **Office 365 Exchange Online**: - Add **Application permissions**: `IMAP.AccessAsApp`, `SMTP.SendAsApp`, `POP.AccessAsApp` - Click **Grant admin consent** 4. In Exchange Online PowerShell, register the service principal for the mailbox: ```powershell New-ServicePrincipal -AppId -ServiceId -DisplayName "MessagingService" Add-MailboxPermission -Identity "user@yourorg.onmicrosoft.com" -User -AccessRights FullAccess ``` 5. Set `OAuth2TenantId` to the full domain (e.g. `yourorg.onmicrosoft.com`) or tenant GUID. > ?? `OAuth2ClientSecret` must be the **Value** shown at secret creation time, not the Secret ID (GUID). > The value is only visible once — if lost, create a new secret. > ?? `OAuth2TenantId` must be a full domain (`yourorg.onmicrosoft.com`), a tenant GUID, > or `common`. Short names like `yourorg` are not valid and will cause `AADSTS900023`. > No browser-based authorization is required for Microsoft — the application acquires tokens > automatically on first use and caches them in memory until 5 minutes before expiry. --- ## Email Account Configuration Each account is configured under `EmailAccounts.Accounts` in `appsettings.Secrets.json`. > Different providers require different configuration fields. See provider-specific sections below. ### Common fields (all providers) ```json { "Id": 1, "Username": "user@example.com", "Password": "your_password", "SmtpServer": "smtp.example.com", "SmtpPort": 465, "SmtpUseSsl": true, "UseOAuth2": false, "ImapServer": "imap.example.com", "ImapPort": 993, "ImapUseSsl": true, "Pop3Server": "pop.example.com", "Pop3Port": 995, "Pop3UseSsl": true, "IncomingProtocol": 1 } ``` > `Password` is always retained. When `UseOAuth2 = true`, SMTP/IMAP/POP3 connections use OAuth2 tokens > instead of the password. When `UseOAuth2 = false`, the password is used directly. > The `IncomingProtocol` field independently controls which protocol is used for receiving emails. #### `IncomingProtocol` values | Value | Meaning | |-------|---------| | `0` | None — send-only account, skipped by sync worker | | `1` | IMAP with username/password | | `2` | POP3 with username/password | | `3` | IMAP with OAuth2 | | `4` | POP3 with OAuth2 | #### `OAuth2Provider` values | Value | Meaning | |-------|---------| | `0` | None | | `1` | Microsoft (Azure AD / Microsoft 365) | | `2` | Google (Gmail / Google Workspace) | --- ## Provider-specific OAuth2 Configuration ### Google (Gmail / Google Workspace) Google uses **user-delegated OAuth2** (not client credentials). A one-time authorization flow is required to obtain a refresh token. #### Required fields ```json { "UseOAuth2": true, "OAuth2ClientId": "YOUR_CLIENT_ID.apps.googleusercontent.com", "OAuth2ClientSecret": "GOCSPX-YOUR_CLIENT_SECRET", "OAuth2RefreshToken": "1//04YOUR_REFRESH_TOKEN", "OAuth2TenantId": "", "OAuth2Provider": 2 } ``` #### Setup — obtaining the refresh token (one-time) 1. Go to [console.cloud.google.com](https://console.cloud.google.com) and create or select a project. 2. Enable the **Gmail API** under *APIs & Services ? Library*. 3. Go to *APIs & Services ? Credentials* ? **+ Create Credentials** ? **OAuth 2.0 Client ID**. - Application type: **Web application** - Authorized redirect URIs: `https://developers.google.com/oauthplayground` 4. Go to *APIs & Services ? OAuth consent screen*: - Add the Gmail account under **Test users** (required while app is in Testing mode). 5. Go to [developers.google.com/oauthplayground](https://developers.google.com/oauthplayground): - Click **?? Settings** ? enable **"Use your own OAuth credentials"** - Enter your **Client ID** and **Client Secret** (from step 3) - Close settings 6. In the scope input (Step 1), enter `https://mail.google.com/` ? **Authorize APIs** 7. Sign in with the Gmail account ? grant access 8. Click **Exchange authorization code for tokens** (Step 2) 9. Copy the `refresh_token` value from the response 10. Set `OAuth2RefreshToken` in `appsettings.Secrets.json` > ?? The refresh token must be obtained using **your own client credentials** in Playground settings. > If obtained with Playground's default credentials, it will not work with your client secret. > ?? Google refresh tokens expire if unused for 6 months, or if the user revokes access. > The token must be re-obtained if `invalid_grant` is returned. --- ### Microsoft 365 / Exchange Online (Azure AD) Microsoft uses **application-level OAuth2** (client credentials flow — no user interaction required). #### Required fields ```json { "UseOAuth2": true, "OAuth2ClientId": "YOUR_APP_CLIENT_ID", "OAuth2ClientSecret": "YOUR_APP_CLIENT_SECRET_VALUE", "OAuth2TenantId": "yourorg.onmicrosoft.com", "OAuth2Provider": 1 } ``` #### Setup 1. Go to [portal.azure.com](https://portal.azure.com) ? **Azure Active Directory** ? **App registrations** ? **+ New registration**. 2. Go to **Certificates & secrets** ? **+ New client secret** ? copy the **Value** (not the ID). - Set this as `OAuth2ClientSecret`. 3. Go to **API permissions** ? **+ Add a permission** ? **APIs my organization uses** ? **Office 365 Exchange Online**: - Add **Application permissions**: `IMAP.AccessAsApp`, `SMTP.SendAsApp`, `POP.AccessAsApp` - Click **Grant admin consent** 4. In Exchange Online PowerShell, register the service principal for the mailbox: ```powershell New-ServicePrincipal -AppId -ServiceId -DisplayName "MessagingService" Add-MailboxPermission -Identity "user@yourorg.onmicrosoft.com" -User -AccessRights FullAccess ``` 5. Set `OAuth2TenantId` to the full domain (e.g. `yourorg.onmicrosoft.com`) or tenant GUID. > ?? `OAuth2ClientSecret` must be the **Value** shown at secret creation time, not the Secret ID (GUID). > The value is only visible once — if lost, create a new secret. > ?? `OAuth2TenantId` must be a full domain (`yourorg.onmicrosoft.com`), a tenant GUID, > or `common`. Short names like `yourorg` are not valid and will cause `AADSTS900023`.