courrier multi account
This commit is contained in:
parent
cf1509540e
commit
b66081643f
115
app/api/courrier/account/route.ts
Normal file
115
app/api/courrier/account/route.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { getServerSession } from 'next-auth';
|
||||||
|
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
||||||
|
import { saveUserEmailCredentials, testEmailConnection } from '@/lib/services/email-service';
|
||||||
|
|
||||||
|
// Define EmailCredentials interface inline since we're having import issues
|
||||||
|
interface EmailCredentials {
|
||||||
|
email: string;
|
||||||
|
password?: string;
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
secure?: boolean;
|
||||||
|
smtp_host?: string;
|
||||||
|
smtp_port?: number;
|
||||||
|
smtp_secure?: boolean;
|
||||||
|
display_name?: string;
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: Request) {
|
||||||
|
try {
|
||||||
|
// Authenticate user
|
||||||
|
const session = await getServerSession(authOptions);
|
||||||
|
if (!session?.user?.id) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse request body
|
||||||
|
const body = await request.json();
|
||||||
|
const {
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
secure,
|
||||||
|
smtp_host,
|
||||||
|
smtp_port,
|
||||||
|
smtp_secure,
|
||||||
|
display_name,
|
||||||
|
color
|
||||||
|
} = body;
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (!email || !password || !host || !port) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Required fields missing: email, password, host, port' },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create credentials object
|
||||||
|
const credentials: EmailCredentials = {
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
host,
|
||||||
|
port: typeof port === 'string' ? parseInt(port) : port,
|
||||||
|
secure: secure ?? true,
|
||||||
|
// Optional SMTP settings
|
||||||
|
...(smtp_host && { smtp_host }),
|
||||||
|
...(smtp_port && { smtp_port: typeof smtp_port === 'string' ? parseInt(smtp_port) : smtp_port }),
|
||||||
|
...(smtp_secure !== undefined && { smtp_secure }),
|
||||||
|
// Optional display settings
|
||||||
|
...(display_name && { display_name }),
|
||||||
|
...(color && { color })
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test connection before saving
|
||||||
|
const connectionTest = await testEmailConnection(credentials);
|
||||||
|
|
||||||
|
if (!connectionTest.imap) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: 'Failed to connect to IMAP server with provided credentials',
|
||||||
|
details: connectionTest.error
|
||||||
|
},
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If SMTP details provided but connection failed
|
||||||
|
if (smtp_host && smtp_port && !connectionTest.smtp) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: 'IMAP connection successful, but SMTP connection failed',
|
||||||
|
details: connectionTest.error
|
||||||
|
},
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save credentials to database and cache
|
||||||
|
await saveUserEmailCredentials(session.user.id, credentials);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: 'Email account added successfully',
|
||||||
|
connectionStatus: {
|
||||||
|
imap: connectionTest.imap,
|
||||||
|
smtp: connectionTest.smtp
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error adding email account:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: 'Failed to add email account',
|
||||||
|
details: error instanceof Error ? error.message : 'Unknown error'
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -27,6 +27,10 @@ import { ScrollArea } from '@/components/ui/scroll-area';
|
|||||||
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
|
||||||
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { toast } from '@/components/ui/use-toast';
|
||||||
|
|
||||||
// Import components
|
// Import components
|
||||||
import EmailSidebar from '@/components/email/EmailSidebar';
|
import EmailSidebar from '@/components/email/EmailSidebar';
|
||||||
@ -449,38 +453,141 @@ export default function CourrierPage() {
|
|||||||
{showAddAccountForm && (
|
{showAddAccountForm && (
|
||||||
<div className="mb-3 p-2 border border-gray-200 rounded-md bg-gray-50">
|
<div className="mb-3 p-2 border border-gray-200 rounded-md bg-gray-50">
|
||||||
<h4 className="text-xs font-medium mb-2 text-gray-700">Add IMAP Account</h4>
|
<h4 className="text-xs font-medium mb-2 text-gray-700">Add IMAP Account</h4>
|
||||||
<form onSubmit={(e) => {
|
<form onSubmit={async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// We'll implement this function later
|
setLoading(true);
|
||||||
alert('This feature will be implemented next');
|
|
||||||
|
const formData = new FormData(e.currentTarget);
|
||||||
|
const newAccount = {
|
||||||
|
email: formData.get('email'),
|
||||||
|
password: formData.get('password'),
|
||||||
|
host: formData.get('host'),
|
||||||
|
port: parseInt(formData.get('port') as string),
|
||||||
|
secure: formData.get('secure') === 'on',
|
||||||
|
display_name: formData.get('display_name') || formData.get('email'),
|
||||||
|
color: formData.get('color') || '#0082c9',
|
||||||
|
smtp_host: formData.get('smtp_host'),
|
||||||
|
smtp_port: formData.get('smtp_port') ? parseInt(formData.get('smtp_port') as string) : undefined,
|
||||||
|
smtp_secure: formData.get('smtp_secure') === 'on'
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/courrier/account', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(newAccount)
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(result.error || 'Failed to add account');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update accounts list
|
||||||
|
const newAccountObj = {
|
||||||
|
id: Date.now(), // temporary ID
|
||||||
|
name: newAccount.display_name as string,
|
||||||
|
email: newAccount.email as string,
|
||||||
|
color: `bg-blue-500`, // Default color class
|
||||||
|
folders: ['INBOX', 'Sent', 'Drafts', 'Trash'] // Default folders
|
||||||
|
};
|
||||||
|
|
||||||
|
setAccounts(prev => [...prev, newAccountObj]);
|
||||||
setShowAddAccountForm(false);
|
setShowAddAccountForm(false);
|
||||||
|
toast({
|
||||||
|
title: "Account added successfully",
|
||||||
|
description: `Your email account ${newAccount.email} has been added.`,
|
||||||
|
duration: 5000
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error adding account:', error);
|
||||||
|
toast({
|
||||||
|
title: "Failed to add account",
|
||||||
|
description: error instanceof Error ? error.message : 'Unknown error',
|
||||||
|
variant: "destructive",
|
||||||
|
duration: 5000
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
}}>
|
}}>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
<Tabs defaultValue="imap" className="w-full">
|
||||||
|
<TabsList className="grid w-full grid-cols-2 h-7">
|
||||||
|
<TabsTrigger value="imap" className="text-xs">IMAP Settings</TabsTrigger>
|
||||||
|
<TabsTrigger value="smtp" className="text-xs">SMTP Settings</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="imap" className="space-y-2 pt-2">
|
||||||
<Input
|
<Input
|
||||||
type="email"
|
type="email"
|
||||||
|
name="email"
|
||||||
placeholder="Email address"
|
placeholder="Email address"
|
||||||
className="h-8 text-xs"
|
className="h-8 text-xs"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
type="password"
|
type="password"
|
||||||
|
name="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
className="h-8 text-xs"
|
className="h-8 text-xs"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
|
name="display_name"
|
||||||
|
placeholder="Display name (optional)"
|
||||||
|
className="h-8 text-xs"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
name="host"
|
||||||
placeholder="IMAP server"
|
placeholder="IMAP server"
|
||||||
className="h-8 text-xs"
|
className="h-8 text-xs"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<div className="flex space-x-2">
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="Port (usually 993)"
|
name="port"
|
||||||
className="h-8 text-xs"
|
placeholder="Port"
|
||||||
|
className="h-8 text-xs w-1/2"
|
||||||
defaultValue="993"
|
defaultValue="993"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<div className="flex items-center space-x-2 w-1/2">
|
||||||
|
<Checkbox id="secure" name="secure" defaultChecked />
|
||||||
|
<Label htmlFor="secure" className="text-xs">SSL/TLS</Label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="smtp" className="space-y-2 pt-2">
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
name="smtp_host"
|
||||||
|
placeholder="SMTP server (optional)"
|
||||||
|
className="h-8 text-xs"
|
||||||
|
/>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
name="smtp_port"
|
||||||
|
placeholder="Port"
|
||||||
|
className="h-8 text-xs w-1/2"
|
||||||
|
defaultValue="587"
|
||||||
|
/>
|
||||||
|
<div className="flex items-center space-x-2 w-1/2">
|
||||||
|
<Checkbox id="smtp_secure" name="smtp_secure" />
|
||||||
|
<Label htmlFor="smtp_secure" className="text-xs">SSL/TLS</Label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
<div className="flex justify-end space-x-2 pt-1">
|
<div className="flex justify-end space-x-2 pt-1">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
@ -495,8 +602,14 @@ export default function CourrierPage() {
|
|||||||
type="submit"
|
type="submit"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="h-7 text-xs"
|
className="h-7 text-xs"
|
||||||
|
disabled={loading}
|
||||||
>
|
>
|
||||||
Add Account
|
{loading ? (
|
||||||
|
<>
|
||||||
|
<Loader2 className="mr-1 h-3 w-3 animate-spin" />
|
||||||
|
Adding...
|
||||||
|
</>
|
||||||
|
) : "Add Account"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -17,56 +17,9 @@ import {
|
|||||||
invalidateFolderCache,
|
invalidateFolderCache,
|
||||||
invalidateEmailContentCache
|
invalidateEmailContentCache
|
||||||
} from '@/lib/redis';
|
} from '@/lib/redis';
|
||||||
|
import { EmailCredentials, EmailMessage, EmailAddress, EmailAttachment } from '@/lib/types';
|
||||||
|
|
||||||
// Types for the email service
|
// Types specific to this service
|
||||||
export interface EmailCredentials {
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
host: string;
|
|
||||||
port: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EmailMessage {
|
|
||||||
id: string;
|
|
||||||
messageId?: string;
|
|
||||||
subject: string;
|
|
||||||
from: EmailAddress[];
|
|
||||||
to: EmailAddress[];
|
|
||||||
cc?: EmailAddress[];
|
|
||||||
bcc?: EmailAddress[];
|
|
||||||
date: Date;
|
|
||||||
flags: {
|
|
||||||
seen: boolean;
|
|
||||||
flagged: boolean;
|
|
||||||
answered: boolean;
|
|
||||||
deleted: boolean;
|
|
||||||
draft: boolean;
|
|
||||||
};
|
|
||||||
preview?: string;
|
|
||||||
content?: string;
|
|
||||||
html?: string;
|
|
||||||
text?: string;
|
|
||||||
hasAttachments: boolean;
|
|
||||||
attachments?: EmailAttachment[];
|
|
||||||
folder: string;
|
|
||||||
size?: number;
|
|
||||||
contentFetched: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EmailAddress {
|
|
||||||
name: string;
|
|
||||||
address: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EmailAttachment {
|
|
||||||
contentId?: string;
|
|
||||||
filename: string;
|
|
||||||
contentType: string;
|
|
||||||
size: number;
|
|
||||||
path?: string;
|
|
||||||
content?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EmailListResult {
|
export interface EmailListResult {
|
||||||
emails: EmailMessage[];
|
emails: EmailMessage[];
|
||||||
totalEmails: number;
|
totalEmails: number;
|
||||||
@ -198,18 +151,37 @@ export async function getImapConnection(userId: string): Promise<ImapFlow> {
|
|||||||
*/
|
*/
|
||||||
export async function getUserEmailCredentials(userId: string): Promise<EmailCredentials | null> {
|
export async function getUserEmailCredentials(userId: string): Promise<EmailCredentials | null> {
|
||||||
const credentials = await prisma.mailCredentials.findUnique({
|
const credentials = await prisma.mailCredentials.findUnique({
|
||||||
where: { userId }
|
where: { userId },
|
||||||
|
select: {
|
||||||
|
email: true,
|
||||||
|
password: true,
|
||||||
|
host: true,
|
||||||
|
port: true,
|
||||||
|
secure: true,
|
||||||
|
smtp_host: true,
|
||||||
|
smtp_port: true,
|
||||||
|
smtp_secure: true,
|
||||||
|
display_name: true,
|
||||||
|
color: true
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return only the fields that exist in credentials
|
||||||
return {
|
return {
|
||||||
email: credentials.email,
|
email: credentials.email,
|
||||||
password: credentials.password,
|
password: credentials.password,
|
||||||
host: credentials.host,
|
host: credentials.host,
|
||||||
port: credentials.port
|
port: credentials.port,
|
||||||
|
...(credentials.secure !== undefined && { secure: credentials.secure }),
|
||||||
|
...(credentials.smtp_host && { smtp_host: credentials.smtp_host }),
|
||||||
|
...(credentials.smtp_port && { smtp_port: credentials.smtp_port }),
|
||||||
|
...(credentials.smtp_secure !== undefined && { smtp_secure: credentials.smtp_secure }),
|
||||||
|
...(credentials.display_name && { display_name: credentials.display_name }),
|
||||||
|
...(credentials.color && { color: credentials.color })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,14 +199,26 @@ export async function saveUserEmailCredentials(
|
|||||||
email: credentials.email,
|
email: credentials.email,
|
||||||
password: credentials.password,
|
password: credentials.password,
|
||||||
host: credentials.host,
|
host: credentials.host,
|
||||||
port: credentials.port
|
port: credentials.port,
|
||||||
|
secure: credentials.secure ?? true,
|
||||||
|
smtp_host: credentials.smtp_host,
|
||||||
|
smtp_port: credentials.smtp_port,
|
||||||
|
smtp_secure: credentials.smtp_secure,
|
||||||
|
display_name: credentials.display_name,
|
||||||
|
color: credentials.color
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
userId,
|
userId,
|
||||||
email: credentials.email,
|
email: credentials.email,
|
||||||
password: credentials.password,
|
password: credentials.password,
|
||||||
host: credentials.host,
|
host: credentials.host,
|
||||||
port: credentials.port
|
port: credentials.port,
|
||||||
|
secure: credentials.secure ?? true,
|
||||||
|
smtp_host: credentials.smtp_host,
|
||||||
|
smtp_port: credentials.smtp_port,
|
||||||
|
smtp_secure: credentials.smtp_secure,
|
||||||
|
display_name: credentials.display_name,
|
||||||
|
color: credentials.color
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -645,11 +629,11 @@ export async function sendEmail(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create SMTP transporter
|
// Create SMTP transporter with user's SMTP settings if available
|
||||||
const transporter = nodemailer.createTransport({
|
const transporter = nodemailer.createTransport({
|
||||||
host: 'smtp.infomaniak.com', // Using Infomaniak SMTP server
|
host: credentials.smtp_host || 'smtp.infomaniak.com', // Use custom SMTP or default
|
||||||
port: 587,
|
port: credentials.smtp_port || 587,
|
||||||
secure: false,
|
secure: credentials.smtp_secure || false,
|
||||||
auth: {
|
auth: {
|
||||||
user: credentials.email,
|
user: credentials.email,
|
||||||
pass: credentials.password,
|
pass: credentials.password,
|
||||||
@ -709,10 +693,20 @@ export async function getMailboxes(client: ImapFlow): Promise<string[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test email connection with given credentials
|
* Test email connections with given credentials
|
||||||
*/
|
*/
|
||||||
export async function testEmailConnection(credentials: EmailCredentials): Promise<boolean> {
|
export async function testEmailConnection(credentials: EmailCredentials): Promise<{
|
||||||
const client = new ImapFlow({
|
imap: boolean;
|
||||||
|
smtp: boolean;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
|
// Test IMAP connection
|
||||||
|
let imapSuccess = false;
|
||||||
|
let smtpSuccess = false;
|
||||||
|
let errorMessage = '';
|
||||||
|
|
||||||
|
// First test IMAP
|
||||||
|
const imapClient = new ImapFlow({
|
||||||
host: credentials.host,
|
host: credentials.host,
|
||||||
port: credentials.port,
|
port: credentials.port,
|
||||||
secure: true,
|
secure: true,
|
||||||
@ -727,19 +721,60 @@ export async function testEmailConnection(credentials: EmailCredentials): Promis
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await client.connect();
|
await imapClient.connect();
|
||||||
await client.mailboxOpen('INBOX');
|
await imapClient.mailboxOpen('INBOX');
|
||||||
return true;
|
imapSuccess = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Connection test failed:', error);
|
console.error('IMAP connection test failed:', error);
|
||||||
return false;
|
errorMessage = error instanceof Error ? error.message : 'Unknown IMAP error';
|
||||||
|
return { imap: false, smtp: false, error: `IMAP connection failed: ${errorMessage}` };
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
await client.logout();
|
await imapClient.logout();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Ignore logout errors
|
// Ignore logout errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If IMAP successful and SMTP details provided, test SMTP
|
||||||
|
if (credentials.smtp_host && credentials.smtp_port) {
|
||||||
|
const transporter = nodemailer.createTransport({
|
||||||
|
host: credentials.smtp_host,
|
||||||
|
port: credentials.smtp_port,
|
||||||
|
secure: true,
|
||||||
|
auth: {
|
||||||
|
user: credentials.email,
|
||||||
|
pass: credentials.password,
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
rejectUnauthorized: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await transporter.verify();
|
||||||
|
smtpSuccess = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('SMTP connection test failed:', error);
|
||||||
|
errorMessage = error instanceof Error ? error.message : 'Unknown SMTP error';
|
||||||
|
return {
|
||||||
|
imap: imapSuccess,
|
||||||
|
smtp: false,
|
||||||
|
error: `SMTP connection failed: ${errorMessage}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If no SMTP details, just mark as successful
|
||||||
|
smtpSuccess = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { imap: imapSuccess, smtp: smtpSuccess };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original simplified function for backward compatibility
|
||||||
|
export async function testImapConnection(credentials: EmailCredentials): Promise<boolean> {
|
||||||
|
const result = await testEmailConnection(credentials);
|
||||||
|
return result.imap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Email formatting functions have been moved to lib/utils/email-formatter.ts
|
// Email formatting functions have been moved to lib/utils/email-formatter.ts
|
||||||
|
|||||||
67
lib/types.ts
Normal file
67
lib/types.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
export interface EmailCredentials {
|
||||||
|
// IMAP Settings
|
||||||
|
email: string;
|
||||||
|
password?: string;
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
secure?: boolean;
|
||||||
|
encryptedPassword?: string;
|
||||||
|
|
||||||
|
// SMTP Settings
|
||||||
|
smtp_host?: string;
|
||||||
|
smtp_port?: number;
|
||||||
|
smtp_secure?: boolean; // true for SSL, false for TLS
|
||||||
|
|
||||||
|
// Display Settings
|
||||||
|
display_name?: string;
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmailAddress {
|
||||||
|
name: string;
|
||||||
|
address: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmailAttachment {
|
||||||
|
contentId?: string;
|
||||||
|
filename: string;
|
||||||
|
contentType: string;
|
||||||
|
size: number;
|
||||||
|
path?: string;
|
||||||
|
content?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmailMessage {
|
||||||
|
id: string;
|
||||||
|
messageId?: string;
|
||||||
|
subject: string;
|
||||||
|
from: EmailAddress[];
|
||||||
|
to: EmailAddress[];
|
||||||
|
cc?: EmailAddress[];
|
||||||
|
bcc?: EmailAddress[];
|
||||||
|
date: Date;
|
||||||
|
flags: {
|
||||||
|
seen: boolean;
|
||||||
|
flagged: boolean;
|
||||||
|
answered: boolean;
|
||||||
|
deleted: boolean;
|
||||||
|
draft: boolean;
|
||||||
|
};
|
||||||
|
preview?: string;
|
||||||
|
content?: string;
|
||||||
|
html?: string;
|
||||||
|
text?: string;
|
||||||
|
hasAttachments: boolean;
|
||||||
|
attachments?: EmailAttachment[];
|
||||||
|
folder: string;
|
||||||
|
size?: number;
|
||||||
|
contentFetched: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Account {
|
||||||
|
id: number | string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
color: string;
|
||||||
|
folders?: string[];
|
||||||
|
}
|
||||||
@ -63,6 +63,17 @@ model MailCredentials {
|
|||||||
password String
|
password String
|
||||||
host String
|
host String
|
||||||
port Int
|
port Int
|
||||||
|
secure Boolean @default(true)
|
||||||
|
|
||||||
|
// SMTP Settings
|
||||||
|
smtp_host String?
|
||||||
|
smtp_port Int?
|
||||||
|
smtp_secure Boolean? @default(false)
|
||||||
|
|
||||||
|
// Display Settings
|
||||||
|
display_name String?
|
||||||
|
color String? @default("#0082c9")
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user