Files

142 lines
4.4 KiB
JavaScript

#!/usr/bin/env node
const path = require('path');
const os = require('os');
const fs = require('fs');
const dotenv = require('dotenv');
// Config file locations
const PRIMARY_ENV_PATH = path.join(os.homedir(), '.config', 'imap-smtp-email', '.env');
const FALLBACK_ENV_PATH = path.resolve(__dirname, '../.env');
// Find the .env file: primary location first, then fallback
function findEnvPath() {
if (fs.existsSync(PRIMARY_ENV_PATH)) return PRIMARY_ENV_PATH;
if (fs.existsSync(FALLBACK_ENV_PATH)) return FALLBACK_ENV_PATH;
return null;
}
// Parse and strip --account <name> from process.argv
// After this, process.argv[2] is always the command
function parseAccountFromArgv(argv) {
const args = argv.slice(2);
const idx = args.indexOf('--account');
if (idx !== -1 && idx + 1 < args.length) {
const name = args[idx + 1];
args.splice(idx, 2);
return { accountName: name, remainingArgs: args };
}
return { accountName: null, remainingArgs: args };
}
// Build config object from environment variables
// prefix: uppercase account name (e.g., 'WORK') or null for default
function buildConfig(env, prefix) {
const p = prefix ? `${prefix}_` : '';
// Account existence check for named accounts
if (prefix && !env[`${p}IMAP_HOST`]) {
console.error(`Error: Account "${prefix.toLowerCase()}" not found in config. Check ~/.config/imap-smtp-email/.env`);
process.exit(1);
}
return {
imap: {
host: env[`${p}IMAP_HOST`] || '127.0.0.1',
port: parseInt(env[`${p}IMAP_PORT`]) || 1143,
user: env[`${p}IMAP_USER`],
pass: env[`${p}IMAP_PASS`],
tls: env[`${p}IMAP_TLS`] === 'true',
rejectUnauthorized: env[`${p}IMAP_REJECT_UNAUTHORIZED`] !== 'false',
mailbox: env[`${p}IMAP_MAILBOX`] || 'INBOX',
},
smtp: {
host: env[`${p}SMTP_HOST`],
port: parseInt(env[`${p}SMTP_PORT`]) || 587,
user: env[`${p}SMTP_USER`],
pass: env[`${p}SMTP_PASS`],
secure: env[`${p}SMTP_SECURE`] === 'true',
from: env[`${p}SMTP_FROM`] || env[`${p}SMTP_USER`],
rejectUnauthorized: env[`${p}SMTP_REJECT_UNAUTHORIZED`] !== 'false',
},
allowedReadDirs: (env.ALLOWED_READ_DIRS || '').split(',').map(d => d.trim()).filter(Boolean),
allowedWriteDirs: (env.ALLOWED_WRITE_DIRS || '').split(',').map(d => d.trim()).filter(Boolean),
};
}
// List all configured accounts from .env file
// Returns { accounts: Array, configPath: String|null }
function listAccounts() {
const envPath = findEnvPath();
if (!envPath) {
return { accounts: [], configPath: null };
}
// Parse the env file fresh to get all account prefixes
const dotenvResult = dotenv.config({ path: envPath });
const env = dotenvResult.parsed || {};
const accounts = [];
const seen = new Set();
// Check for default account (no prefix)
if (env.IMAP_HOST) {
accounts.push(createAccountObject(env, '', 'default'));
seen.add('default');
}
// Scan for named accounts (pattern: XXX_IMAP_HOST)
for (const key of Object.keys(env)) {
const match = key.match(/^([A-Z0-9]+)_IMAP_HOST$/);
if (match) {
const prefix = match[1];
const name = prefix.toLowerCase();
if (!seen.has(name)) {
accounts.push(createAccountObject(env, prefix + '_', name));
seen.add(name);
}
}
}
return { accounts, configPath: envPath };
}
// Create an account object from env variables
function createAccountObject(env, prefix, name) {
const p = prefix;
return {
name,
email: env[`${p}IMAP_USER`] || env[`${p}SMTP_FROM`] || '-',
imapHost: env[`${p}IMAP_HOST`] || '-',
smtpHost: env[`${p}SMTP_HOST`] || '-',
isComplete: isAccountComplete(env, prefix)
};
}
// Check if an account has all required configuration
function isAccountComplete(env, prefix) {
const p = prefix;
return !!(
env[`${p}IMAP_HOST`] &&
env[`${p}IMAP_USER`] &&
env[`${p}IMAP_PASS`] &&
env[`${p}SMTP_HOST`]
);
}
// --- Module initialization ---
const envPath = findEnvPath();
if (envPath) {
dotenv.config({ path: envPath });
}
const { accountName, remainingArgs } = parseAccountFromArgv(process.argv);
const prefix = accountName ? accountName.toUpperCase() : null;
// Strip --account from process.argv so callers see command at argv[2]
process.argv = [process.argv[0], process.argv[1], ...remainingArgs];
const config = buildConfig(process.env, prefix);
module.exports = config;
module.exports.listAccounts = listAccounts;