chore: CRM-NEW baseline
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#!/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);
|
||||
});
|
||||
Reference in New Issue
Block a user