@accounter/gmail-listener 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/SETUP.md +128 -0
- package/dist/index.js +11774 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Gmail Listener
|
|
2
|
+
|
|
3
|
+
A service that watches a Gmail inbox, extracts financial documents from matching emails, and sends
|
|
4
|
+
them to the Accounter server through GraphQL.
|
|
5
|
+
|
|
6
|
+
## What It Does
|
|
7
|
+
|
|
8
|
+
- Connects to Gmail using OAuth2.
|
|
9
|
+
- Ensures the processing label tree exists (default: `accounter/documents` with `processed`,
|
|
10
|
+
`errors`, and `debug` sub-labels).
|
|
11
|
+
- Processes pending emails already under the target label on startup.
|
|
12
|
+
- Subscribes to Gmail push notifications through Google Pub/Sub for new inbox events.
|
|
13
|
+
- Extracts documents from:
|
|
14
|
+
- PDF/image attachments
|
|
15
|
+
- HTML email body (converted to PDF)
|
|
16
|
+
- Internal links configured per business
|
|
17
|
+
- Uploads documents to the Accounter server using GraphQL multipart requests.
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
- Node.js 20+ (project standard)
|
|
22
|
+
- Yarn
|
|
23
|
+
- A Google account/mailbox to monitor
|
|
24
|
+
- Access to an Accounter server with:
|
|
25
|
+
- A valid `GMAIL_LISTENER_API_KEY`
|
|
26
|
+
- `businessEmailConfig` and `insertEmailDocuments` GraphQL operations enabled
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
1. Copy env template and fill values:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cp .env.template .env
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. Follow full setup instructions in [SETUP.md](./SETUP.md).
|
|
37
|
+
|
|
38
|
+
3. Run locally:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
yarn
|
|
42
|
+
yarn dev
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Runtime Behavior
|
|
46
|
+
|
|
47
|
+
- Startup flow:
|
|
48
|
+
- validates environment variables
|
|
49
|
+
- validates OAuth and Gmail API access
|
|
50
|
+
- creates missing labels
|
|
51
|
+
- processes existing labeled emails
|
|
52
|
+
- starts Pub/Sub listener and Gmail watch
|
|
53
|
+
- Email labeling:
|
|
54
|
+
- success -> `<label>/processed`
|
|
55
|
+
- processing error -> `<label>/errors`
|
|
56
|
+
- no relevant documents -> `<label>/debug`
|
|
57
|
+
- Health checks run every 10 minutes and the listener auto-restarts on failures.
|
|
58
|
+
|
|
59
|
+
## Environment Variables
|
|
60
|
+
|
|
61
|
+
See [SETUP.md](./SETUP.md) for how to obtain each value.
|
|
62
|
+
|
|
63
|
+
- `SERVER_URL` (required): GraphQL endpoint URL of Accounter server.
|
|
64
|
+
- `GMAIL_LISTENER_API_KEY` (required): API key sent as `X-API-Key`.
|
|
65
|
+
- `GMAIL_CLIENT_ID` (required for Gmail mode): Google OAuth client ID.
|
|
66
|
+
- `GMAIL_CLIENT_SECRET` (required for Gmail mode): Google OAuth client secret.
|
|
67
|
+
- `GMAIL_REFRESH_TOKEN` (required for Gmail mode): offline refresh token for the monitored mailbox.
|
|
68
|
+
- `GMAIL_LABEL_PATH` (optional): base Gmail label to process. Default: `accounter/documents`.
|
|
69
|
+
- `GOOGLE_CLOUD_PROJECT_ID` (required for Gmail mode): GCP project ID used by Pub/Sub.
|
|
70
|
+
- `GOOGLE_APPLICATION_CREDENTIALS` (required for Gmail mode): path to service account JSON key file.
|
|
71
|
+
- `PUBSUB_TOPIC` (optional): Pub/Sub topic name. Default: `gmail-notifications`.
|
|
72
|
+
- `PUBSUB_SUBSCRIPTION` (optional): Pub/Sub subscription name. Default: `gmail-notifications-sub`.
|
|
73
|
+
|
|
74
|
+
Important: Gmail integration variables are validated as a set. Provide all Gmail-related variables
|
|
75
|
+
together, or none.
|
|
76
|
+
|
|
77
|
+
## Scripts
|
|
78
|
+
|
|
79
|
+
- `yarn dev` - build in watch mode and run listener
|
|
80
|
+
- `yarn build` - typecheck + build
|
|
81
|
+
- `yarn start` - run built output
|
|
82
|
+
- `yarn typecheck` - TypeScript check only
|
|
83
|
+
|
|
84
|
+
## Security Notes
|
|
85
|
+
|
|
86
|
+
- Never commit `.env` or Google service-account JSON keys.
|
|
87
|
+
- Root `.gitignore` already excludes `**/accounter-gmail-service-key.json`.
|
|
88
|
+
- Keep the OAuth client and refresh token restricted to the monitored mailbox use case.
|
package/SETUP.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
## Setup Instructions
|
|
2
|
+
|
|
3
|
+
These instructions are specific to this repository package: `packages/gmail-listener`.
|
|
4
|
+
|
|
5
|
+
### 1. Google Cloud Project Setup
|
|
6
|
+
|
|
7
|
+
1. Create or select a Google Cloud project in <https://console.cloud.google.com/>.
|
|
8
|
+
2. Enable these APIs in that project:
|
|
9
|
+
|
|
10
|
+
- Gmail API
|
|
11
|
+
- Cloud Pub/Sub API
|
|
12
|
+
|
|
13
|
+
3. Create a service account for Pub/Sub access:
|
|
14
|
+
|
|
15
|
+
- IAM & Admin -> Service Accounts -> Create Service Account
|
|
16
|
+
- Grant least-privilege Pub/Sub permissions required by your org policy (Editor is not required)
|
|
17
|
+
- Create and download a JSON key
|
|
18
|
+
|
|
19
|
+
4. Save the downloaded JSON key in this package directory as:
|
|
20
|
+
|
|
21
|
+
- `packages/gmail-listener/accounter-gmail-service-key.json`
|
|
22
|
+
|
|
23
|
+
5. Ensure Gmail can publish to Pub/Sub topic:
|
|
24
|
+
|
|
25
|
+
- In Pub/Sub topic permissions, add principal `gmail-api-push@system.gserviceaccount.com`
|
|
26
|
+
- Grant role `Pub/Sub Publisher`
|
|
27
|
+
|
|
28
|
+
Note: this repository already ignores `**/accounter-gmail-service-key.json` in root `.gitignore`.
|
|
29
|
+
|
|
30
|
+
### 2. Pub/Sub Resources
|
|
31
|
+
|
|
32
|
+
Create:
|
|
33
|
+
|
|
34
|
+
- Topic: `gmail-notifications` (or your custom name)
|
|
35
|
+
- Subscription: `gmail-notifications-sub` (or your custom name)
|
|
36
|
+
|
|
37
|
+
You can use custom names, but they must match `PUBSUB_TOPIC` and `PUBSUB_SUBSCRIPTION` in `.env`.
|
|
38
|
+
|
|
39
|
+
### 3. Gmail OAuth App Setup
|
|
40
|
+
|
|
41
|
+
1. In Google Cloud Console, go to APIs & Services -> Credentials.
|
|
42
|
+
2. Create OAuth 2.0 Client ID credentials.
|
|
43
|
+
3. Configure the consent screen according to your organization policy.
|
|
44
|
+
4. Keep client ID and client secret for `.env`.
|
|
45
|
+
|
|
46
|
+
### 4. Generate Refresh Token
|
|
47
|
+
|
|
48
|
+
Use OAuth Playground:
|
|
49
|
+
|
|
50
|
+
1. Open <https://developers.google.com/oauthplayground>
|
|
51
|
+
2. Click the settings gear and enable "Use your own OAuth credentials"
|
|
52
|
+
3. Paste your OAuth client ID and client secret
|
|
53
|
+
4. Select scope `https://mail.google.com/`
|
|
54
|
+
5. Authorize with the mailbox you want the listener to monitor
|
|
55
|
+
6. Exchange authorization code for tokens and copy the refresh token
|
|
56
|
+
|
|
57
|
+
### 5. Environment Configuration
|
|
58
|
+
|
|
59
|
+
Create `.env` in `packages/gmail-listener` (or copy from `.env.template`):
|
|
60
|
+
|
|
61
|
+
```env
|
|
62
|
+
# Accounter server GraphQL endpoint
|
|
63
|
+
SERVER_URL=https://your-accounter-server/graphql
|
|
64
|
+
|
|
65
|
+
# API key for X-API-Key header when calling Accounter server
|
|
66
|
+
GMAIL_LISTENER_API_KEY=your_api_key
|
|
67
|
+
|
|
68
|
+
# Gmail OAuth2
|
|
69
|
+
GMAIL_CLIENT_ID=your_client_id
|
|
70
|
+
GMAIL_CLIENT_SECRET=your_client_secret
|
|
71
|
+
GMAIL_REFRESH_TOKEN=your_refresh_token
|
|
72
|
+
GMAIL_LABEL_PATH=accounter/documents
|
|
73
|
+
|
|
74
|
+
# Google Cloud / PubSub
|
|
75
|
+
GOOGLE_CLOUD_PROJECT_ID=your_project_id
|
|
76
|
+
PUBSUB_TOPIC=gmail-notifications
|
|
77
|
+
PUBSUB_SUBSCRIPTION=gmail-notifications-sub
|
|
78
|
+
|
|
79
|
+
# Absolute or package-relative path to the service account key JSON
|
|
80
|
+
GOOGLE_APPLICATION_CREDENTIALS=./accounter-gmail-service-key.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Important:
|
|
84
|
+
|
|
85
|
+
- `GMAIL_CLIENT_ID`, `GMAIL_CLIENT_SECRET`, `GMAIL_REFRESH_TOKEN`, `GOOGLE_CLOUD_PROJECT_ID`, and
|
|
86
|
+
`GOOGLE_APPLICATION_CREDENTIALS` are validated together. Set all of them or none.
|
|
87
|
+
- If the process is not started from `packages/gmail-listener`, prefer an absolute path for
|
|
88
|
+
`GOOGLE_APPLICATION_CREDENTIALS`.
|
|
89
|
+
|
|
90
|
+
### 6. Run the Service
|
|
91
|
+
|
|
92
|
+
From `packages/gmail-listener`:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
yarn
|
|
96
|
+
yarn dev
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
On startup, the listener:
|
|
100
|
+
|
|
101
|
+
1. validates env
|
|
102
|
+
2. validates OAuth access
|
|
103
|
+
3. ensures labels exist
|
|
104
|
+
4. processes pending labeled messages
|
|
105
|
+
5. starts Pub/Sub listening and Gmail watch renewal
|
|
106
|
+
|
|
107
|
+
### 7. Validate End-to-End
|
|
108
|
+
|
|
109
|
+
1. Send a test invoice email to the monitored mailbox.
|
|
110
|
+
2. Apply/confirm the target label (default `accounter/documents`).
|
|
111
|
+
3. Verify logs show processing.
|
|
112
|
+
4. Check resulting labels:
|
|
113
|
+
|
|
114
|
+
- success -> `.../processed`
|
|
115
|
+
- failure -> `.../errors`
|
|
116
|
+
- no relevant docs -> `.../debug`
|
|
117
|
+
|
|
118
|
+
## Troubleshooting Notes
|
|
119
|
+
|
|
120
|
+
- `invalid_grant`: refresh token is invalid/expired or consent screen configuration is incomplete.
|
|
121
|
+
- Gmail watch setup errors: verify topic exists and Gmail publisher principal is granted.
|
|
122
|
+
- No documents extracted: inspect email attachments/type filters and business email config on server
|
|
123
|
+
side.
|
|
124
|
+
|
|
125
|
+
## About Polling
|
|
126
|
+
|
|
127
|
+
This package is implemented with Gmail push notifications + Pub/Sub, not polling. Keep polling as a
|
|
128
|
+
fallback design only if infrastructure constraints prevent Pub/Sub usage.
|