feat(mail): add governed POP3 legacy import
Module Package Release / publish-packages (push) Successful in 11s

This commit is contained in:
2026-08-22 04:52:25 +02:00
parent 93ecedf607
commit 218fef11f1
27 changed files with 3291 additions and 88 deletions
+129 -1
View File
@@ -296,7 +296,7 @@ export async function createMailServerProfile(settings: ApiSettings, payload: Ma
export type MailServerProfileUpdatePayload = Partial<MailServerProfilePayload> & { clear_imap?: boolean };
export type MailServerEndpointPayload = {
protocol: "smtp" | "imap";
protocol: "smtp" | "imap" | "pop3";
name: string;
config: Record<string, unknown>;
inherit_to_lower_scopes?: boolean | null;
@@ -304,6 +304,77 @@ export type MailServerEndpointPayload = {
is_active?: boolean;
};
export type MailPop3ServerConfig = {
host?: string | null;
port?: number | null;
security?: MailSecurity | string;
timeout_seconds?: number;
max_message_bytes?: number;
max_batch_bytes?: number;
preview_body_lines?: number;
legacy_import_enabled?: boolean;
allow_delete_after_import?: boolean;
};
export type MailPop3ServerEndpoint = Omit<MailServerEndpoint, "protocol" | "config"> & {
protocol: "pop3";
config: MailPop3ServerConfig;
};
export type MailPop3MessagePreview = {
message_number: number;
uidl: string;
subject?: string | null;
from_header?: string | null;
to_header?: string | null;
date?: string | null;
message_id?: string | null;
size_bytes: number;
body_preview?: string | null;
already_imported: boolean;
};
export type MailPop3PreviewResponse = {
profile_id: string;
server_id: string;
transport_revision: string;
host: string;
port: number;
security: string;
message_count: number;
mailbox_size_bytes: number;
delete_after_import_allowed: boolean;
messages: MailPop3MessagePreview[];
};
export type MailPop3ImportRecord = {
id: string;
profile_id: string;
pop3_server_id: string;
transport_revision: string;
provider_uidl: string;
message_id?: string | null;
subject?: string | null;
from_header?: string | null;
to_header?: string | null;
date?: string | null;
body_preview?: string | null;
size_bytes: number;
raw_sha256: string;
status: string;
imported_at: string;
deletion_requested: boolean;
deletion_status: string;
deletion_attempted_at?: string | null;
deletion_error?: string | null;
};
export type MailPop3ImportResponse = {
imports: MailPop3ImportRecord[];
duplicate_uidls: string[];
deletion_status: string;
};
export type MailCredentialCreatePayload = {
name: string;
description?: string | null;
@@ -503,6 +574,63 @@ export async function testMailProfileImap(
);
}
export async function testMailProfilePop3(
settings: ApiSettings,
profileId: string,
serverId: string,
credentialId?: string | null
): Promise<MailConnectionTestResponse> {
return apiPost<MailConnectionTestResponse>(
settings,
apiPath(`/api/v1/mail/profiles/${encodeURIComponent(profileId)}/test-pop3`, {
server_id: serverId,
credential_id: credentialId
})
);
}
export async function previewMailProfilePop3(
settings: ApiSettings,
profileId: string,
payload: { server_id: string; credential_id?: string | null; limit?: number }
): Promise<MailPop3PreviewResponse> {
return apiPostJson<MailPop3PreviewResponse>(
settings,
`/api/v1/mail/profiles/${encodeURIComponent(profileId)}/pop3/preview`,
payload
);
}
export async function importMailProfilePop3(
settings: ApiSettings,
profileId: string,
payload: {
server_id: string;
credential_id?: string | null;
expected_transport_revision: string;
uidls: string[];
delete_after_import?: boolean;
}
): Promise<MailPop3ImportResponse> {
return apiPostJson<MailPop3ImportResponse>(
settings,
`/api/v1/mail/profiles/${encodeURIComponent(profileId)}/pop3/import`,
payload
);
}
export async function listMailPop3Imports(
settings: ApiSettings,
profileId?: string | null,
limit = 100
): Promise<MailPop3ImportRecord[]> {
const response = await apiFetch<{ imports: MailPop3ImportRecord[] }>(
settings,
apiPath("/api/v1/mail/pop3/imports", { profile_id: profileId, limit })
);
return response.imports;
}
export async function listMailProfileImapFolders(
settings: ApiSettings,
profileId: string,