Files
govoplan-mail/webui/src/api/mail.ts
2026-07-14 13:22:11 +02:00

325 lines
11 KiB
TypeScript

import type {
ApiSettings,
DeltaDeletedItem,
MailConnectionTestResponse,
MailImapFolderListResponse,
MailImapTestPayload,
MailProfilePolicy,
MailProfilePolicyResponse,
MailProfileScope,
MailSecurity,
MailServerProfile,
MailServerProfilePayload,
MailSmtpTestPayload,
MockMailboxMessage,
MockMailboxMessageResponse
} from "@govoplan/core-webui";
import { apiFetch, apiGetList, apiPath, apiPost, apiPostJson } from "./client";
export { mailProfilePatternKeys, mailProfilePolicyLimitKeys } from "@govoplan/core-webui";
export type {
MailConnectionTestResponse,
MailCredentialPolicy,
MailImapFolderListResponse,
MailImapFolderResponse,
MailImapTestPayload,
MailProfilePatternKey,
MailProfilePatternRules,
MailProfilePolicy,
MailProfilePolicyLimitKey,
MailProfilePolicyLimitPermissions,
MailProfilePolicyResponse,
MailProfileScope,
MailSecurity,
MailServerProfile,
MailServerProfileCredentialsPayload,
MailServerProfileListResponse,
MailServerProfilePayload,
MailSmtpTestPayload,
MailTransportCredentialsPayload,
MockMailboxMessage,
MockMailboxMessageResponse
} from "@govoplan/core-webui";
export type { MailPolicySourceStep as PolicySourceStep } from "@govoplan/core-webui";
export type MailAddressLookupCandidate = {
contact_id: string;
address_book_id: string;
display_name: string;
email?: string | null;
email_label?: string | null;
organization?: string | null;
role_title?: string | null;
tags: string[];
source_kind: string;
source_ref?: string | null;
source_revision?: string | null;
provenance: Record<string, unknown>;
};
export type MailAddressLookupResponse = {
available: boolean;
candidates: MailAddressLookupCandidate[];
};
export type MailMailboxAttachment = {
filename?: string | null;
content_type: string;
size_bytes: number;
};
export type MailMailboxMessageSummary = {
uid: string;
folder: string;
subject?: string | null;
from_header?: string | null;
to_header?: string | null;
cc_header?: string | null;
bcc_header?: string | null;
date?: string | null;
message_id?: string | null;
flags?: string[];
size_bytes?: number | null;
body_preview?: string | null;
attachment_count?: number;
};
export type MailMailboxMessageDetail = MailMailboxMessageSummary & {
body_text?: string | null;
body_html?: string | null;
headers?: Record<string, string>;
attachments?: MailMailboxAttachment[];
};
export type MailMailboxMessageListResponse = {
profile_id: string;
folder: string;
host?: string | null;
port?: number | null;
security?: MailSecurity | string | null;
total_count?: number;
offset?: number;
limit?: number;
cursor?: string | null;
next_cursor?: string | null;
cursor_stable?: boolean;
full?: boolean;
from_cache?: boolean;
refreshing?: boolean;
indexed_at?: string | null;
messages: MailMailboxMessageSummary[];
};
export type MailMailboxBootstrapResponse = {
profile_id: string;
folder: string;
folders: MailImapFolderListResponse;
messages: MailMailboxMessageListResponse;
};
export type MailMailboxMessageResponse = {
profile_id: string;
folder: string;
host?: string | null;
port?: number | null;
security?: MailSecurity | string | null;
message: MailMailboxMessageDetail;
};
export type MailSettingsDeltaResponse = {
profiles: MailServerProfile[];
policy?: MailProfilePolicyResponse | null;
changed_sections?: string[];
deleted: DeltaDeletedItem[];
watermark?: string | null;
has_more: boolean;
full: boolean;
};
export async function lookupMailAddresses(settings: ApiSettings, query: string, limit = 25): Promise<MailAddressLookupResponse> {
return apiFetch<MailAddressLookupResponse>(settings, apiPath("/api/v1/mail/address-lookup", { query, limit }));
}
export async function listMailServerProfiles(settings: ApiSettings, includeInactive = false, campaignId?: string): Promise<MailServerProfile[]> {
return apiGetList<MailServerProfile, "profiles">(settings, "/api/v1/mail/profiles", "profiles", {
include_inactive: includeInactive ? true : undefined,
campaign_id: campaignId
});
}
export async function fetchMailSettingsDelta(
settings: ApiSettings,
params: {
scope_type?: MailProfileScope;
scope_id?: string | null;
include_inactive?: boolean;
campaign_id?: string | null;
since?: string | null;
limit?: number;
} = {}
): Promise<MailSettingsDeltaResponse> {
return apiFetch<MailSettingsDeltaResponse>(settings, apiPath("/api/v1/mail/settings/delta", {
scope_type: params.scope_type,
scope_id: params.scope_id,
include_inactive: params.include_inactive ? true : undefined,
campaign_id: params.campaign_id,
since: params.since,
limit: params.limit
}));
}
export async function createMailServerProfile(settings: ApiSettings, payload: MailServerProfilePayload): Promise<MailServerProfile> {
return apiFetch<MailServerProfile>(settings, "/api/v1/mail/profiles", {
method: "POST",
body: JSON.stringify(payload)
});
}
export type MailServerProfileUpdatePayload = Partial<MailServerProfilePayload> & { clear_imap?: boolean };
export async function updateMailServerProfile(settings: ApiSettings, profileId: string, payload: MailServerProfileUpdatePayload): Promise<MailServerProfile> {
return apiFetch<MailServerProfile>(settings, `/api/v1/mail/profiles/${encodeURIComponent(profileId)}`, {
method: "PATCH",
body: JSON.stringify(payload)
});
}
export async function deactivateMailServerProfile(settings: ApiSettings, profileId: string): Promise<MailServerProfile> {
return apiFetch<MailServerProfile>(settings, `/api/v1/mail/profiles/${encodeURIComponent(profileId)}`, { method: "DELETE" });
}
export async function getMailProfilePolicy(
settings: ApiSettings,
scopeType: MailProfileScope,
scopeId?: string | null,
campaignId?: string | null
): Promise<MailProfilePolicyResponse> {
return apiFetch<MailProfilePolicyResponse>(settings, apiPath(`/api/v1/mail/policies/${encodeURIComponent(scopeType)}`, {
scope_id: scopeId,
campaign_id: campaignId
}));
}
export async function updateMailProfilePolicy(
settings: ApiSettings,
scopeType: MailProfileScope,
policy: MailProfilePolicy,
scopeId?: string | null
): Promise<MailProfilePolicyResponse> {
return apiFetch<MailProfilePolicyResponse>(settings, apiPath(`/api/v1/mail/policies/${encodeURIComponent(scopeType)}`, { scope_id: scopeId }), {
method: "PUT",
body: JSON.stringify({ policy })
});
}
export async function testMailProfileSmtp(settings: ApiSettings, profileId: string): Promise<MailConnectionTestResponse> {
return apiPost<MailConnectionTestResponse>(settings, `/api/v1/mail/profiles/${encodeURIComponent(profileId)}/test-smtp`);
}
export async function testMailProfileImap(settings: ApiSettings, profileId: string): Promise<MailConnectionTestResponse> {
return apiPost<MailConnectionTestResponse>(settings, `/api/v1/mail/profiles/${encodeURIComponent(profileId)}/test-imap`);
}
export async function listMailProfileImapFolders(settings: ApiSettings, profileId: string): Promise<MailImapFolderListResponse> {
return apiPost<MailImapFolderListResponse>(settings, `/api/v1/mail/profiles/${encodeURIComponent(profileId)}/list-imap-folders`);
}
export async function listMailboxFolders(settings: ApiSettings, profileId: string, includeStatus = false, refresh = false): Promise<MailImapFolderListResponse> {
return apiFetch<MailImapFolderListResponse>(settings, apiPath(`/api/v1/mail/profiles/${encodeURIComponent(profileId)}/mailbox/folders`, {
include_status: includeStatus ? true : undefined,
refresh: refresh ? true : undefined
}));
}
export async function bootstrapMailbox(
settings: ApiSettings,
profileId: string,
folder = "INBOX",
limit = 50,
offset = 0,
refresh = false
): Promise<MailMailboxBootstrapResponse> {
return apiFetch<MailMailboxBootstrapResponse>(settings, apiPath(`/api/v1/mail/profiles/${encodeURIComponent(profileId)}/mailbox/bootstrap`, {
folder,
limit,
offset,
refresh: refresh ? true : undefined
}));
}
export async function listMailboxMessages(
settings: ApiSettings,
profileId: string,
folder = "INBOX",
limit = 50,
offset = 0,
cursor?: string | null,
refresh = false
): Promise<MailMailboxMessageListResponse> {
return apiFetch<MailMailboxMessageListResponse>(settings, apiPath(`/api/v1/mail/profiles/${encodeURIComponent(profileId)}/mailbox/messages`, {
folder,
limit,
offset,
cursor,
refresh: refresh ? true : undefined
}));
}
export async function getMailboxMessage(
settings: ApiSettings,
profileId: string,
folder: string,
uid: string
): Promise<MailMailboxMessageResponse> {
return apiFetch<MailMailboxMessageResponse>(settings, apiPath(`/api/v1/mail/profiles/${encodeURIComponent(profileId)}/mailbox/messages/${encodeURIComponent(uid)}`, { folder }));
}
export async function testSmtpSettings(
settings: ApiSettings,
payload: MailSmtpTestPayload
): Promise<MailConnectionTestResponse> {
return apiPostJson<MailConnectionTestResponse>(settings, "/api/v1/mail/test-smtp", payload);
}
export async function testImapSettings(
settings: ApiSettings,
payload: MailImapTestPayload
): Promise<MailConnectionTestResponse> {
return apiPostJson<MailConnectionTestResponse>(settings, "/api/v1/mail/test-imap", payload);
}
export async function listImapFolders(
settings: ApiSettings,
payload: MailImapTestPayload
): Promise<MailImapFolderListResponse> {
return apiPostJson<MailImapFolderListResponse>(settings, "/api/v1/mail/list-imap-folders", payload);
}
export type MockMailboxListResponse = {
messages: MockMailboxMessage[];
};
export type MockMailboxFailureConfig = {
fail_next_smtp?: boolean | null;
fail_next_imap?: boolean | null;
smtp_reject_recipients_containing?: string | null;
};
export async function listMockMailboxMessages(settings: ApiSettings, kind?: string): Promise<MockMailboxListResponse> {
return apiFetch<MockMailboxListResponse>(settings, apiPath("/api/v1/dev/mailbox/messages", { kind }));
}
export async function getMockMailboxMessage(settings: ApiSettings, id: string): Promise<MockMailboxMessageResponse> {
return apiFetch<MockMailboxMessageResponse>(settings, `/api/v1/dev/mailbox/messages/${encodeURIComponent(id)}`);
}
export async function clearMockMailboxMessages(settings: ApiSettings): Promise<{ deleted_count: number }> {
return apiFetch<{ deleted_count: number }>(settings, "/api/v1/dev/mailbox/messages", { method: "DELETE" });
}
export async function updateMockMailboxFailures(settings: ApiSettings, payload: MockMailboxFailureConfig): Promise<{ config: MockMailboxFailureConfig }> {
return apiFetch<{ config: MockMailboxFailureConfig }>(settings, "/api/v1/dev/mailbox/failures", {
method: "POST",
body: JSON.stringify(payload)
});
}