@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 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.