@bobfrankston/iflow 1.0.27 → 1.0.29

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.
@@ -39,5 +39,6 @@ export declare function createAutoImapConfig(config: {
39
39
  password?: string;
40
40
  verbose?: boolean;
41
41
  rejectUnauthorized?: boolean;
42
+ tokenDirectory?: string;
42
43
  }): ImapClientConfig;
43
44
  //# sourceMappingURL=gmail.d.ts.map
package/imaplib/gmail.js CHANGED
@@ -7,6 +7,8 @@ import fs from 'fs';
7
7
  const GMAIL_SERVER = 'imap.gmail.com';
8
8
  const GMAIL_PORT = 993;
9
9
  const GMAIL_SCOPE = 'https://mail.google.com/';
10
+ // Serialize concurrent OAuth attempts per username to avoid port conflicts (EADDRINUSE)
11
+ const pendingAuth = new Map();
10
12
  // Get the directory where this module is located
11
13
  const DEFAULT_CREDENTIALS_PATH = path.resolve(import.meta.dirname, '..', 'iflow-credentials.json');
12
14
  /**
@@ -45,17 +47,30 @@ export function createImapConfig(config) {
45
47
  const accountDir = username.replace(/[@.]/g, '_');
46
48
  const tokenDir = path.join(tokenDirectory, 'tokens', accountDir);
47
49
  const getToken = async () => {
48
- const token = await authenticateOAuth(credentialsPath, {
49
- scope: GMAIL_SCOPE,
50
- tokenDirectory: tokenDir,
51
- tokenFileName: 'token.json',
52
- credentialsKey: 'installed',
53
- includeOfflineAccess: true,
54
- loginHint: username
55
- });
56
- if (!token)
57
- throw new Error('Failed to get Gmail access token');
58
- return token.access_token;
50
+ // Serialize concurrent OAuth attempts — only one flow at a time per user
51
+ const existing = pendingAuth.get(username);
52
+ if (existing)
53
+ return existing;
54
+ const attempt = (async () => {
55
+ const token = await authenticateOAuth(credentialsPath, {
56
+ scope: GMAIL_SCOPE,
57
+ tokenDirectory: tokenDir,
58
+ tokenFileName: 'token.json',
59
+ credentialsKey: 'installed',
60
+ includeOfflineAccess: true,
61
+ loginHint: username
62
+ });
63
+ if (!token)
64
+ throw new Error('Failed to get Gmail access token');
65
+ return token.access_token;
66
+ })();
67
+ pendingAuth.set(username, attempt);
68
+ try {
69
+ return await attempt;
70
+ }
71
+ finally {
72
+ pendingAuth.delete(username);
73
+ }
59
74
  };
60
75
  return {
61
76
  server: GMAIL_SERVER,
@@ -79,7 +94,8 @@ export function createAutoImapConfig(config) {
79
94
  if (isGmail) {
80
95
  // Use OAuth for Gmail
81
96
  const oauthConfig = createImapConfig({
82
- username: config.username
97
+ username: config.username,
98
+ tokenDirectory: config.tokenDirectory
83
99
  });
84
100
  // Merge in additional options
85
101
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/iflow",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "description": "IMAP client wrapper library",
5
5
  "main": "index.js",
6
6
  "types": "index.ts",