feat(email): round-trip test — send via SMTP to the IMAP mailbox and confirm arrival
- emailIntakeService.roundTripTest(): sends a uniquely-tagged email through the
saved SMTP config to the IMAP mailbox (imap_user), then polls IMAP up to 30s
for that subject token; deletes the test message on arrival so it never hits
the accounting inbox. Returns {ok, seconds, recipient} or a typed reason.
- route POST /admin/email/incoming-config/roundtrip (email.send)
- IMAP card: 'Round-trip test' button beside 'Test connection' + Save; toast
reports recipient + delivery time. Distinct reasons mapped (smtp/imap
unconfigured, send_failed, not_received→504).
- en/de strings
This commit is contained in:
@@ -102,6 +102,12 @@ export interface ImapTestResult {
|
||||
unseen: number;
|
||||
}
|
||||
|
||||
export interface ImapRoundTripResult {
|
||||
ok: boolean;
|
||||
seconds?: number;
|
||||
recipient?: string;
|
||||
}
|
||||
|
||||
export interface ReceivedEmail {
|
||||
id: number;
|
||||
message_id: string | null;
|
||||
@@ -150,6 +156,12 @@ export const emailService = {
|
||||
const response = await api.post<ImapTestResult>('/admin/email/incoming-config/test', config || {});
|
||||
return response.data;
|
||||
},
|
||||
// End-to-end: send via SMTP to the IMAP mailbox and confirm it arrives.
|
||||
// Uses saved config for both sides — no body. May take up to ~30s.
|
||||
async roundTripIncoming(): Promise<ImapRoundTripResult> {
|
||||
const response = await api.post<ImapRoundTripResult>('/admin/email/incoming-config/roundtrip', {});
|
||||
return response.data;
|
||||
},
|
||||
async listReceived(params: { page?: number; pageSize?: number } = {}): Promise<ReceivedEmailsResponse> {
|
||||
const response = await api.get<ReceivedEmailsResponse>('/admin/email/received', { params });
|
||||
return response.data;
|
||||
|
||||
Reference in New Issue
Block a user