Initial commit

This commit is contained in:
root
2025-12-21 09:55:58 -05:00
committed by Sebastian Krupinski
commit 169b7b4c91
57 changed files with 10105 additions and 0 deletions

376
src/models/message.ts Normal file
View File

@@ -0,0 +1,376 @@
/**
* Message and MessagePart model classes
*/
import type { MessageInterface, MessagePartInterface } from "@/types/message";
/**
* MessagePart class for working with message body parts
*/
export class MessagePartObject {
_data: MessagePartInterface;
constructor(data?: Partial<MessagePartInterface>) {
this._data = {
partId: data?.partId ?? null,
blobId: data?.blobId ?? null,
size: data?.size ?? null,
name: data?.name ?? null,
type: data?.type ?? undefined,
charset: data?.charset ?? null,
disposition: data?.disposition ?? null,
cid: data?.cid ?? null,
language: data?.language ?? null,
location: data?.location ?? null,
content: data?.content ?? undefined,
subParts: data?.subParts ?? undefined,
};
}
fromJson(data: MessagePartInterface): MessagePartObject {
this._data = data;
return this;
}
toJson(): MessagePartInterface {
return this._data;
}
clone(): MessagePartObject {
return new MessagePartObject(JSON.parse(JSON.stringify(this._data)));
}
/** Properties */
get partId(): string | null | undefined {
return this._data.partId;
}
get blobId(): string | null | undefined {
return this._data.blobId;
}
get size(): number | null | undefined {
return this._data.size;
}
get name(): string | null | undefined {
return this._data.name;
}
get type(): string | undefined {
return this._data.type;
}
get charset(): string | null | undefined {
return this._data.charset;
}
get disposition(): string | null | undefined {
return this._data.disposition;
}
get cid(): string | null | undefined {
return this._data.cid;
}
get language(): string | null | undefined {
return this._data.language;
}
get location(): string | null | undefined {
return this._data.location;
}
get content(): string | undefined {
return this._data.content;
}
get subParts(): MessagePartInterface[] | undefined {
return this._data.subParts;
}
/** Helper methods */
hasContent(): boolean {
return !!this._data.content;
}
hasSubParts(): boolean {
return !!this._data.subParts && this._data.subParts.length > 0;
}
isMultipart(): boolean {
return this._data.type?.startsWith('multipart/') ?? false;
}
isText(): boolean {
return this._data.type === 'text/plain';
}
isHtml(): boolean {
return this._data.type === 'text/html';
}
isAttachment(): boolean {
return this._data.disposition === 'attachment';
}
isInline(): boolean {
return this._data.disposition === 'inline';
}
/**
* Find a part by partId (recursive search)
*/
findPartById(partId: string): MessagePartInterface | null {
if (this._data.partId === partId) {
return this._data;
}
if (this._data.subParts) {
for (const subPart of this._data.subParts) {
const part = new MessagePartObject(subPart);
const found = part.findPartById(partId);
if (found) {
return found;
}
}
}
return null;
}
/**
* Find all parts of a specific type (recursive search)
*/
findPartsByType(type: string): MessagePartInterface[] {
const parts: MessagePartInterface[] = [];
if (this._data.type === type) {
parts.push(this._data);
}
if (this._data.subParts) {
for (const subPart of this._data.subParts) {
const part = new MessagePartObject(subPart);
parts.push(...part.findPartsByType(type));
}
}
return parts;
}
/**
* Extract text content from body structure
*/
extractTextContent(): string | null {
if (this._data.type === 'text/plain' && this._data.content) {
return this._data.content;
}
if (this._data.subParts) {
for (const subPart of this._data.subParts) {
const part = new MessagePartObject(subPart);
const content = part.extractTextContent();
if (content) {
return content;
}
}
}
return null;
}
/**
* Extract HTML content from body structure
*/
extractHtmlContent(): string | null {
if (this._data.type === 'text/html' && this._data.content) {
return this._data.content;
}
if (this._data.subParts) {
for (const subPart of this._data.subParts) {
const part = new MessagePartObject(subPart);
const content = part.extractHtmlContent();
if (content) {
return content;
}
}
}
return null;
}
}
/**
* Message class for working with message objects
*/
export class MessageObject {
_data: MessageInterface;
_body: MessagePartObject | null = null;
constructor(data?: Partial<MessageInterface>) {
this._data = {
urid: data?.urid ?? undefined,
size: data?.size ?? undefined,
receivedDate: data?.receivedDate ?? undefined,
date: data?.date ?? undefined,
subject: data?.subject ?? undefined,
snippet: data?.snippet ?? undefined,
from: data?.from ?? undefined,
to: data?.to ?? [],
cc: data?.cc ?? [],
bcc: data?.bcc ?? [],
replyTo: data?.replyTo ?? [],
flags: data?.flags ?? {},
body: data?.body ?? undefined,
attachments: data?.attachments ?? [],
};
}
fromJson(data: MessageInterface): MessageObject {
this._data = data;
return this;
}
toJson(): MessageInterface {
return this._data;
}
clone(): MessageObject {
return new MessageObject(JSON.parse(JSON.stringify(this._data)));
}
/** Properties */
get urid(): string | undefined {
return this._data.urid;
}
get size(): number | undefined {
return this._data.size;
}
get receivedDate(): string | undefined {
return this._data.receivedDate;
}
get date(): string | undefined {
return this._data.date;
}
get subject(): string | undefined {
return this._data.subject;
}
get snippet(): string | undefined {
return this._data.snippet;
}
get from(): { address: string; label?: string } | undefined {
return this._data.from;
}
get to(): Array<{ address: string; label?: string }> | undefined {
return this._data.to;
}
get cc(): Array<{ address: string; label?: string }> | undefined {
return this._data.cc;
}
get bcc(): Array<{ address: string; label?: string }> | undefined {
return this._data.bcc;
}
get replyTo(): Array<{ address: string; label?: string }> | undefined {
return this._data.replyTo;
}
get flags(): { read?: boolean; flagged?: boolean; answered?: boolean; draft?: boolean } | undefined {
return this._data.flags;
}
get body(): MessagePartInterface | undefined {
return this._data.body;
}
get attachments(): MessageInterface['attachments'] {
return this._data.attachments;
}
/** Helper methods */
get isRead(): boolean {
return this._data.flags?.read ?? false;
}
get isFlagged(): boolean {
return this._data.flags?.flagged ?? false;
}
get isAnswered(): boolean {
return this._data.flags?.answered ?? false;
}
get isDraft(): boolean {
return this._data.flags?.draft ?? false;
}
get hasAttachments(): boolean {
return (this._data.attachments?.length ?? 0) > 0;
}
hasRecipients(): boolean {
return (this._data.to?.length ?? 0) > 0
|| (this._data.cc?.length ?? 0) > 0
|| (this._data.bcc?.length ?? 0) > 0;
}
/** Body content helpers */
getBody(): MessagePartObject | null {
if (!this._body && this._data.body) {
this._body = new MessagePartObject(this._data.body);
}
return this._body;
}
hasContent(): boolean {
return !!this.getTextContent() || !!this.getHtmlContent();
}
hasTextContent(): boolean {
return !!this.getTextContent();
}
getTextContent(): string | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.extractTextContent() : null;
}
hasHtmlContent(): boolean {
return !!this.getHtmlContent();
}
getHtmlContent(): string | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.extractHtmlContent() : null;
}
findPartById(partId: string): MessagePartInterface | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.findPartById(partId) : null;
}
findPartsByType(type: string): MessagePartInterface[] {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.findPartsByType(type) : [];
}
}