mirror of
https://github.com/root-fr/jmap-webmail.git
synced 2026-09-23 08:01:14 +00:00
A modern, privacy-focused webmail client built with Next.js and the JMAP protocol. Designed for Stalwart Mail Server. Features: - Full email operations (compose, reply, forward, threading) - Real-time push notifications - Dark/light theme support - Mobile responsive design - Keyboard shortcuts - Drag-and-drop organization - i18n (English/French) - Security-first (external content blocked, HTML sanitization)
213 lines
4.6 KiB
TypeScript
213 lines
4.6 KiB
TypeScript
export interface EmailHeader {
|
|
name: string;
|
|
value: string;
|
|
}
|
|
|
|
export interface Email {
|
|
id: string;
|
|
threadId: string;
|
|
mailboxIds: Record<string, boolean>;
|
|
keywords: Record<string, boolean>;
|
|
size: number;
|
|
receivedAt: string;
|
|
from?: EmailAddress[];
|
|
to?: EmailAddress[];
|
|
cc?: EmailAddress[];
|
|
bcc?: EmailAddress[];
|
|
replyTo?: EmailAddress[];
|
|
subject?: string;
|
|
sentAt?: string;
|
|
preview?: string;
|
|
textBody?: EmailBodyPart[];
|
|
htmlBody?: EmailBodyPart[];
|
|
bodyValues?: Record<string, EmailBodyValue>;
|
|
attachments?: Attachment[];
|
|
hasAttachment: boolean;
|
|
// Extended header information
|
|
messageId?: string;
|
|
inReplyTo?: string[];
|
|
references?: string[];
|
|
headers?: Record<string, string | string[]>;
|
|
// Security headers parsed
|
|
authenticationResults?: AuthenticationResults;
|
|
spamScore?: number;
|
|
spamStatus?: string;
|
|
spamLLM?: {
|
|
verdict: string;
|
|
explanation: string;
|
|
};
|
|
}
|
|
|
|
export interface AuthenticationResults {
|
|
spf?: {
|
|
result: 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror';
|
|
domain?: string;
|
|
ip?: string;
|
|
};
|
|
dkim?: {
|
|
result: 'pass' | 'fail' | 'policy' | 'neutral' | 'temperror' | 'permerror';
|
|
domain?: string;
|
|
selector?: string;
|
|
};
|
|
dmarc?: {
|
|
result: 'pass' | 'fail' | 'none';
|
|
policy?: 'reject' | 'quarantine' | 'none';
|
|
domain?: string;
|
|
};
|
|
iprev?: {
|
|
result: 'pass' | 'fail';
|
|
ip?: string;
|
|
};
|
|
}
|
|
|
|
export interface EmailBodyValue {
|
|
value: string;
|
|
isEncodingProblem?: boolean;
|
|
isTruncated?: boolean;
|
|
}
|
|
|
|
export interface EmailAddress {
|
|
name?: string;
|
|
email: string;
|
|
}
|
|
|
|
export interface EmailBodyPart {
|
|
partId: string;
|
|
blobId: string;
|
|
size: number;
|
|
name?: string;
|
|
type: string;
|
|
charset?: string;
|
|
disposition?: string;
|
|
cid?: string;
|
|
language?: string[];
|
|
location?: string;
|
|
subParts?: EmailBodyPart[];
|
|
}
|
|
|
|
export interface Attachment {
|
|
partId: string;
|
|
blobId: string;
|
|
size: number;
|
|
name?: string;
|
|
type: string;
|
|
charset?: string;
|
|
cid?: string;
|
|
disposition?: string;
|
|
}
|
|
|
|
export interface Mailbox {
|
|
id: string;
|
|
originalId?: string; // Original JMAP ID (for shared mailboxes)
|
|
name: string;
|
|
parentId?: string;
|
|
role?: string;
|
|
sortOrder: number;
|
|
totalEmails: number;
|
|
unreadEmails: number;
|
|
totalThreads: number;
|
|
unreadThreads: number;
|
|
myRights: {
|
|
mayReadItems: boolean;
|
|
mayAddItems: boolean;
|
|
mayRemoveItems: boolean;
|
|
maySetSeen: boolean;
|
|
maySetKeywords: boolean;
|
|
mayCreateChild: boolean;
|
|
mayRename: boolean;
|
|
mayDelete: boolean;
|
|
maySubmit: boolean;
|
|
};
|
|
isSubscribed: boolean;
|
|
// Shared folder support
|
|
accountId?: string;
|
|
accountName?: string;
|
|
isShared?: boolean;
|
|
}
|
|
|
|
export interface Thread {
|
|
id: string;
|
|
emailIds: string[];
|
|
}
|
|
|
|
// Thread grouping for UI display
|
|
export interface ThreadGroup {
|
|
threadId: string;
|
|
emails: Email[]; // Emails in this thread (sorted by receivedAt desc)
|
|
latestEmail: Email; // Most recent email
|
|
participantNames: string[];// Unique participant names
|
|
hasUnread: boolean; // Any unread emails in thread
|
|
hasStarred: boolean; // Any starred emails in thread
|
|
hasAttachment: boolean; // Any email has attachment
|
|
emailCount: number; // Total emails in thread
|
|
}
|
|
|
|
export interface Identity {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
replyTo?: EmailAddress[];
|
|
bcc?: EmailAddress[];
|
|
textSignature?: string;
|
|
htmlSignature?: string;
|
|
mayDelete: boolean;
|
|
}
|
|
|
|
export interface EmailSubmission {
|
|
id: string;
|
|
identityId: string;
|
|
emailId: string;
|
|
threadId?: string;
|
|
envelope: {
|
|
mailFrom: EmailAddress;
|
|
rcptTo: EmailAddress[];
|
|
};
|
|
sendAt?: string;
|
|
undoStatus: "pending" | "final" | "canceled";
|
|
deliveryStatus?: Record<string, DeliveryStatus>;
|
|
dsnBlobIds?: string[];
|
|
mdnBlobIds?: string[];
|
|
}
|
|
|
|
export interface DeliveryStatus {
|
|
smtpReply: string;
|
|
delivered: "queued" | "yes" | "no" | "unknown";
|
|
displayed: "unknown" | "yes";
|
|
}
|
|
|
|
// JMAP Push Notification Types (RFC 8620 Section 7)
|
|
|
|
export interface StateChange {
|
|
'@type': 'StateChange';
|
|
changed: {
|
|
[accountId: string]: {
|
|
Email?: string;
|
|
Mailbox?: string;
|
|
Thread?: string;
|
|
EmailDelivery?: string;
|
|
EmailSubmission?: string;
|
|
Identity?: string;
|
|
};
|
|
};
|
|
}
|
|
|
|
export interface PushSubscription {
|
|
id: string;
|
|
deviceClientId: string;
|
|
url: string;
|
|
keys: {
|
|
p256dh: string;
|
|
auth: string;
|
|
} | null;
|
|
expires: string | null;
|
|
types: string[] | null;
|
|
}
|
|
|
|
// For tracking last known states
|
|
export interface AccountStates {
|
|
[accountId: string]: {
|
|
Email?: string;
|
|
Mailbox?: string;
|
|
Thread?: string;
|
|
};
|
|
} |