first commit

This commit is contained in:
AyrisAI
2026-05-14 01:57:52 +03:00
parent 863a32cd35
commit 4a9196f483
47 changed files with 12043 additions and 102 deletions

211
lib/mailcow.ts Normal file
View File

@@ -0,0 +1,211 @@
/**
* lib/mailcow.ts
* Mailcow API client — server-side only.
* Uses the single super-admin API key from .env.
*/
const BASE = process.env.MAILCOW_API_URL?.replace(/\/$/, "") ?? "";
const KEY = process.env.MAILCOW_API_KEY ?? "";
async function mfetch(path: string, options: RequestInit = {}) {
const url = `${BASE}/api/v1${path}`;
const res = await fetch(url, {
...options,
headers: {
"Content-Type": "application/json",
"X-API-Key": KEY,
...options.headers,
},
// Don't cache — always fresh
cache: "no-store",
});
return res;
}
// ─── Types ─────────────────────────────────────────────────
export interface MailcowDomain {
domain_name: string;
description: string;
active: string; // "1" | "0"
mboxes_in_domain: number;
mboxes_left: number;
max_num_mboxes_for_domain: number;
quota_used_in_domain: string;
max_quota_for_domain: number;
max_quota_for_mbox: number;
aliases_in_domain: number;
aliases_left: number;
}
export interface MailcowMailbox {
username: string; // full email e.g. info@domain.com
name: string; // display name
local_part: string;
domain: string;
quota: number; // bytes
quota_used: number; // bytes
active: string; // "1" | "0"
created: string;
modified: string;
}
export interface MailcowDomainAdmin {
username: string;
active: string;
domains: string[];
created: string;
modified: string;
}
// ─── Domains ────────────────────────────────────────────────
export async function getDomains(): Promise<MailcowDomain[]> {
const res = await mfetch("/get/domain/all");
if (!res.ok) return [];
const data = await res.json();
return Array.isArray(data) ? data : [];
}
export async function getDomain(domain: string): Promise<MailcowDomain | null> {
const res = await mfetch(`/get/domain/${domain}`);
if (!res.ok) return null;
const data = await res.json();
return Array.isArray(data) ? data[0] ?? null : data ?? null;
}
export async function createDomain(payload: {
domain: string;
description?: string;
aliases?: number;
mailboxes?: number;
defquota?: number;
maxquota?: number;
quota?: number;
active?: number;
}) {
const body = {
active: 1,
aliases: 400,
mailboxes: 10,
defquota: 3072,
maxquota: 10240,
quota: 10240,
...payload,
};
const res = await mfetch("/add/domain", { method: "POST", body: JSON.stringify(body) });
const data = await res.json();
return { ok: res.ok, data };
}
export async function deleteDomain(domain: string) {
const res = await mfetch("/delete/domain", {
method: "POST",
body: JSON.stringify([domain]),
});
const data = await res.json();
return { ok: res.ok, data };
}
// ─── Domain Admins ──────────────────────────────────────────
export async function getDomainAdmins(): Promise<MailcowDomainAdmin[]> {
const res = await mfetch("/get/domain-admin/all");
if (!res.ok) return [];
const data = await res.json();
return Array.isArray(data) ? data : Object.values(data);
}
export async function createDomainAdmin(payload: {
username: string;
password: string;
domains: string; // comma-separated or single domain
active?: number;
}) {
const body = {
active: 1,
password2: payload.password,
...payload,
};
const res = await mfetch("/add/domain-admin", { method: "POST", body: JSON.stringify(body) });
const data = await res.json();
return { ok: res.ok, data };
}
export async function deleteDomainAdmin(username: string) {
const res = await mfetch("/delete/domain-admin", {
method: "POST",
body: JSON.stringify([username]),
});
const data = await res.json();
return { ok: res.ok, data };
}
// ─── Mailboxes ──────────────────────────────────────────────
export async function getMailboxes(domain: string): Promise<MailcowMailbox[]> {
const res = await mfetch(`/get/mailbox/all/${domain}`);
if (!res.ok) return [];
const data = await res.json();
return Array.isArray(data) ? data : [];
}
export async function createMailbox(payload: {
local_part: string;
domain: string;
name: string;
password: string;
quota?: number;
active?: number;
}) {
const body = {
quota: 3072,
active: 1,
password2: payload.password,
...payload,
};
const res = await mfetch("/add/mailbox", { method: "POST", body: JSON.stringify(body) });
const data = await res.json();
return { ok: res.ok, data };
}
export async function deleteMailbox(emails: string[]) {
const res = await mfetch("/delete/mailbox", {
method: "POST",
body: JSON.stringify(emails),
});
const data = await res.json();
return { ok: res.ok, data };
}
export async function editMailbox(
emails: string[],
attr: {
password?: string;
password2?: string;
active?: number;
quota?: number;
name?: string;
}
) {
const body = { items: emails, attr };
const res = await mfetch("/edit/mailbox", { method: "POST", body: JSON.stringify(body) });
const data = await res.json();
return { ok: res.ok, data };
}
// ─── Status ─────────────────────────────────────────────────
export async function getVersionStatus() {
const res = await mfetch("/get/status/version");
if (!res.ok) return null;
return res.json();
}
// ─── DKIM ────────────────────────────────────────────────────
export async function getDKIM(domain: string) {
const res = await mfetch(`/get/dkim/${domain}`);
if (!res.ok) return null;
return res.json();
}