Files
crm-ai/scripts/configure-email.js
T
2026-10-23 10:35:28 +08:00

116 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
'use strict';
/**
* 配置 LibreDesk 通知邮件(SMTP)。默认使用旧项目的 163 授权码。
* 修改后 LibreDesk 需要重启才能生效(脚本最后会重启容器)。
*
* 用法:node scripts/configure-email.js
*/
const fs = require('fs');
const path = require('path');
const { execFileSync } = require('child_process');
const ROOT = path.resolve(__dirname, '..');
const OLD_MAIL_CFG = '/home/dev/code/crm/crm-ai-demo/bridge/mail.config.json';
function loadEnv(file) {
const out = {};
for (const line of fs.readFileSync(file, 'utf8').split('\n')) {
const t = line.trim();
if (!t || t.startsWith('#')) continue;
const eq = t.indexOf('=');
if (eq < 0) continue;
let v = t.slice(eq + 1).trim();
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1);
out[t.slice(0, eq).trim()] = v;
}
return out;
}
function createClient(baseURL) {
const cookies = new Map();
let csrf = '';
const cookieHeader = () => [...cookies.entries()].map(([k, v]) => `${k}=${v}`).join('; ');
function store(res) {
const list = typeof res.headers.getSetCookie === 'function' ? res.headers.getSetCookie() : [res.headers.get('set-cookie')].filter(Boolean);
for (const c of list) {
const [pair] = c.split(';');
const eq = pair.indexOf('=');
if (eq > 0) {
const k = pair.slice(0, eq).trim();
const v = pair.slice(eq + 1).trim();
cookies.set(k, v);
if (k === 'csrf_token') csrf = v;
}
}
}
async function req(method, p, body) {
const headers = { Accept: 'application/json' };
if (cookies.size) headers.Cookie = cookieHeader();
if (body !== undefined) headers['Content-Type'] = 'application/json';
if (csrf && method !== 'GET') headers['X-CSRFTOKEN'] = csrf;
const res = await fetch(baseURL + p, { method, headers, body: body === undefined ? undefined : JSON.stringify(body) });
store(res);
const text = await res.text();
let json = null;
try { json = text ? JSON.parse(text) : null; } catch { /* ignore */ }
if (!res.ok) throw new Error(`${method} ${p} -> HTTP ${res.status}: ${(json && json.message) || text.slice(0, 300)}`);
return json;
}
return { post: (p, b) => req('POST', p, b), get: (p) => req('GET', p), put: (p, b) => req('PUT', p, b) };
}
async function main() {
const env = loadEnv(path.join(ROOT, '.env'));
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
// 163 凭据:优先 .env 覆盖,否则读旧项目 mail.config.json
let user = env.SMTP_USER;
let pass = env.SMTP_PASS;
let host = env.SMTP_HOST || 'smtp.163.com';
let port = Number(env.SMTP_PORT || 465);
let from = env.SMTP_FROM;
if ((!user || !pass) && fs.existsSync(OLD_MAIL_CFG)) {
const old = JSON.parse(fs.readFileSync(OLD_MAIL_CFG, 'utf8'));
user = user || old.smtp?.auth?.user;
pass = pass || old.smtp?.auth?.pass;
host = host || old.smtp?.host;
port = port || old.smtp?.port;
from = from || old.smtp?.from;
}
if (!user || !pass) throw new Error('缺少 SMTP 凭据:设置 SMTP_USER/SMTP_PASS 或确认旧 mail.config.json 存在');
const c = createClient(base);
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
console.log('登录成功');
const payload = {
'notification.email.username': user,
'notification.email.host': host,
'notification.email.port': port,
'notification.email.password': pass,
'notification.email.email_address': from,
'notification.email.enabled': true,
'notification.email.tls_type': 'tls',
'notification.email.auth_protocol': 'plain',
'notification.email.max_conns': 5,
'notification.email.idle_timeout': '30s',
'notification.email.wait_timeout': '10s',
'notification.email.max_msg_retries': 3,
'notification.email.tls_skip_verify': false,
'notification.email.hello_hostname': '',
};
await c.put('/api/v1/settings/notifications/email', payload);
console.log(`已保存 SMTP:${host}:${port} user=${user} from=${from}`);
console.log('重启 LibreDesk 使配置生效…');
execFileSync('docker', ['compose', 'restart', 'libredesk'], { cwd: ROOT, stdio: 'inherit' });
console.log('完成。');
}
main().catch((err) => {
console.error('[configure-email]', err.message);
process.exit(1);
});