docs: add full OAuth2 setup guide for Google and Microsoft to README; exclude Google OAuth2 token JSON from version control
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -373,3 +373,4 @@ FodyWeavers.xsd
|
||||
/src/DigitalData.MessagingService.API/appsettings.Secrets.json
|
||||
/src/presentation/DigitalData.MessagingService.API/appsettings.Secrets.json
|
||||
/src/presentation/DigitalData.MessagingService.API/appsettings.Secrets.json
|
||||
/src/presentation/DigitalData.MessagingService.API/oauth.htek0100@gmail.com.json
|
||||
|
||||
300
README.md
300
README.md
@@ -1,2 +1,302 @@
|
||||
# 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 <ClientId> -ServiceId <ObjectId> -DisplayName "MessagingService"
|
||||
Add-MailboxPermission -Identity "user@yourorg.onmicrosoft.com" -User <ObjectId> -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 <ClientId> -ServiceId <ObjectId> -DisplayName "MessagingService"
|
||||
Add-MailboxPermission -Identity "user@yourorg.onmicrosoft.com" -User <ObjectId> -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`.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user