database wf 9
This commit is contained in:
parent
58f0b37476
commit
ed6a33b8d7
@ -58,6 +58,35 @@ export const authOptions: NextAuthOptions = {
|
||||
strategy: "jwt",
|
||||
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||||
},
|
||||
cookies: {
|
||||
sessionToken: {
|
||||
name: `__Secure-next-auth.session-token`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
secure: true
|
||||
}
|
||||
},
|
||||
callbackUrl: {
|
||||
name: `__Secure-next-auth.callback-url`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
secure: true
|
||||
}
|
||||
},
|
||||
csrfToken: {
|
||||
name: `__Host-next-auth.csrf-token`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
secure: true
|
||||
}
|
||||
}
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, account, profile }) {
|
||||
if (account && profile) {
|
||||
@ -121,11 +150,13 @@ export const authOptions: NextAuthOptions = {
|
||||
|
||||
session.accessToken = token.accessToken;
|
||||
session.user = {
|
||||
...session.user,
|
||||
id: token.sub as string,
|
||||
name: token.name,
|
||||
email: token.email,
|
||||
image: null,
|
||||
username: token.username ?? '',
|
||||
first_name: token.first_name ?? '',
|
||||
last_name: token.last_name ?? '',
|
||||
username: token.username ?? '',
|
||||
role: token.role ?? [],
|
||||
};
|
||||
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import Imap from 'imap';
|
||||
import { cookies } from 'next/headers';
|
||||
|
||||
interface StoredCredentials {
|
||||
user: string;
|
||||
email: string;
|
||||
password: string;
|
||||
host: string;
|
||||
port: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
export let storedCredentials: StoredCredentials | null = null;
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const { email, password, host, port } = await request.json();
|
||||
@ -40,8 +39,25 @@ export async function POST(request: Request) {
|
||||
return new Promise((resolve, reject) => {
|
||||
imap.once('ready', () => {
|
||||
imap.end();
|
||||
// Store credentials
|
||||
storedCredentials = { user: email, password, host, port };
|
||||
|
||||
// Store credentials in cookie
|
||||
const cookieStore = cookies();
|
||||
const credentials: StoredCredentials = {
|
||||
email,
|
||||
password,
|
||||
host,
|
||||
port: parseInt(port)
|
||||
};
|
||||
|
||||
// Set the cookie with proper security options
|
||||
cookieStore.set('imap_credentials', JSON.stringify(credentials), {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 30 * 24 * 60 * 60 // 30 days
|
||||
});
|
||||
|
||||
resolve(NextResponse.json({ success: true }));
|
||||
});
|
||||
|
||||
@ -78,14 +94,25 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
if (!storedCredentials) {
|
||||
const cookieStore = cookies();
|
||||
const credentialsCookie = cookieStore.get('imap_credentials');
|
||||
|
||||
if (!credentialsCookie?.value) {
|
||||
return NextResponse.json(
|
||||
{ error: 'No stored credentials found' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
// Return credentials without password
|
||||
const { password, ...safeCredentials } = storedCredentials;
|
||||
return NextResponse.json(safeCredentials);
|
||||
try {
|
||||
const credentials = JSON.parse(credentialsCookie.value);
|
||||
// Return credentials without password for security
|
||||
const { password, ...safeCredentials } = credentials;
|
||||
return NextResponse.json(safeCredentials);
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid credentials format' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,362 +1,52 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import Imap from 'imap';
|
||||
import nodemailer from 'nodemailer';
|
||||
import { parseEmailHeaders, decodeEmailBody } from '@/lib/email-parser';
|
||||
import { cookies } from 'next/headers';
|
||||
import { ImapFlow } from 'imapflow';
|
||||
|
||||
interface StoredCredentials {
|
||||
email: string;
|
||||
password: string;
|
||||
host: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
interface Email {
|
||||
id: string;
|
||||
from: string;
|
||||
subject: string;
|
||||
date: Date;
|
||||
read: boolean;
|
||||
starred: boolean;
|
||||
body: string;
|
||||
to?: string;
|
||||
folder: string;
|
||||
}
|
||||
|
||||
interface ImapBox {
|
||||
messages: {
|
||||
total: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface ImapMessage {
|
||||
on: (event: string, callback: (data: any) => void) => void;
|
||||
once: (event: string, callback: (data: any) => void) => void;
|
||||
attributes: {
|
||||
uid: number;
|
||||
flags: string[];
|
||||
size: number;
|
||||
};
|
||||
body: {
|
||||
[key: string]: {
|
||||
on: (event: string, callback: (data: any) => void) => void;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface ImapConfig {
|
||||
user: string;
|
||||
password: string;
|
||||
host: string;
|
||||
port: number;
|
||||
tls: boolean;
|
||||
authTimeout: number;
|
||||
connTimeout: number;
|
||||
debug?: (info: string) => void;
|
||||
}
|
||||
|
||||
function getStoredCredentials(): StoredCredentials | null {
|
||||
const cookieStore = cookies();
|
||||
|
||||
const credentialsCookie = cookieStore.get('imap_credentials');
|
||||
console.log('Retrieved credentials cookie:', credentialsCookie ? 'Found' : 'Not found');
|
||||
|
||||
if (!credentialsCookie?.value) {
|
||||
console.log('No credentials cookie found');
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const credentials = JSON.parse(credentialsCookie.value);
|
||||
console.log('Parsed credentials:', {
|
||||
...credentials,
|
||||
password: '***'
|
||||
});
|
||||
const cookieStore = cookies();
|
||||
const credentials = cookieStore.get('imap_credentials');
|
||||
|
||||
// Validate required fields
|
||||
if (!credentials.email || !credentials.password || !credentials.host || !credentials.port) {
|
||||
console.error('Missing required credentials fields');
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
email: credentials.email,
|
||||
password: credentials.password,
|
||||
host: credentials.host,
|
||||
port: credentials.port
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error parsing credentials cookie:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const credentials = getStoredCredentials();
|
||||
if (!credentials) {
|
||||
return NextResponse.json(
|
||||
{ error: 'No stored credentials found' },
|
||||
{ error: 'No credentials found' },
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
// Get pagination parameters from URL
|
||||
const url = new URL(request.url);
|
||||
const folder = url.searchParams.get('folder') || 'INBOX';
|
||||
const page = parseInt(url.searchParams.get('page') || '1');
|
||||
const limit = parseInt(url.searchParams.get('limit') || '24');
|
||||
const offset = (page - 1) * limit;
|
||||
const { email, password, host, port } = JSON.parse(credentials.value);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const imap = new Imap({
|
||||
user: credentials.email,
|
||||
password: credentials.password,
|
||||
host: credentials.host,
|
||||
port: credentials.port,
|
||||
tls: true,
|
||||
tlsOptions: { rejectUnauthorized: false },
|
||||
authTimeout: 30000,
|
||||
connTimeout: 30000
|
||||
});
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
console.error('IMAP connection timeout');
|
||||
imap.end();
|
||||
resolve(NextResponse.json({
|
||||
emails: [],
|
||||
error: 'Connection timeout'
|
||||
}));
|
||||
}, 30000);
|
||||
|
||||
imap.once('error', (err: Error) => {
|
||||
console.error('IMAP error:', err);
|
||||
clearTimeout(timeout);
|
||||
resolve(NextResponse.json({
|
||||
emails: [],
|
||||
error: 'IMAP connection error'
|
||||
}));
|
||||
});
|
||||
|
||||
imap.once('ready', () => {
|
||||
imap.getBoxes((err, boxes) => {
|
||||
if (err) {
|
||||
console.error('Error getting mailboxes:', err);
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
resolve(NextResponse.json({ emails: [], error: 'Failed to get mailboxes' }));
|
||||
return;
|
||||
}
|
||||
|
||||
const availableMailboxes = Object.keys(boxes).filter(
|
||||
box => !['Starred', 'Archives'].includes(box)
|
||||
);
|
||||
console.log('Available mailboxes:', availableMailboxes);
|
||||
|
||||
// Only process the requested folder
|
||||
imap.openBox(folder, false, (err, box) => {
|
||||
if (err) {
|
||||
console.error(`Error opening box ${folder}:`, err);
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
resolve(NextResponse.json({ emails: [], error: `Failed to open folder ${folder}` }));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the specified folder
|
||||
const totalMessages = box.messages.total;
|
||||
|
||||
// Calculate the range of messages to fetch
|
||||
const start = Math.max(1, totalMessages - offset - limit + 1);
|
||||
const end = totalMessages - offset;
|
||||
|
||||
if (start > end) {
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
resolve(NextResponse.json({
|
||||
emails: [],
|
||||
folders: availableMailboxes,
|
||||
mailUrl: process.env.NEXT_PUBLIC_IFRAME_MAIL_URL
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch messages in the calculated range
|
||||
imap.search(['ALL'], (err, results) => {
|
||||
if (err) {
|
||||
console.error(`Error searching in ${folder}:`, err);
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
resolve(NextResponse.json({ emails: [], error: `Failed to search in ${folder}` }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!results || results.length === 0) {
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
resolve(NextResponse.json({
|
||||
emails: [],
|
||||
folders: availableMailboxes,
|
||||
mailUrl: process.env.NEXT_PUBLIC_IFRAME_MAIL_URL
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
// Take only the most recent emails up to the limit
|
||||
const recentResults = results.slice(-limit);
|
||||
const emails: any[] = [];
|
||||
|
||||
const fetch = imap.fetch(recentResults, {
|
||||
bodies: ['HEADER', 'TEXT'],
|
||||
struct: true
|
||||
});
|
||||
|
||||
fetch.on('message', (msg) => {
|
||||
let header = '';
|
||||
let text = '';
|
||||
let messageId: number | null = null;
|
||||
let messageFlags: string[] = [];
|
||||
|
||||
msg.once('attributes', (attrs) => {
|
||||
messageId = attrs.uid;
|
||||
messageFlags = attrs.flags || [];
|
||||
});
|
||||
|
||||
msg.on('body', (stream, info) => {
|
||||
let buffer = '';
|
||||
stream.on('data', (chunk) => {
|
||||
buffer += chunk.toString('utf8');
|
||||
});
|
||||
stream.on('end', () => {
|
||||
if (info.which === 'HEADER') {
|
||||
header = buffer;
|
||||
} else if (info.which === 'TEXT') {
|
||||
text = buffer;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
msg.on('end', () => {
|
||||
if (!messageId) {
|
||||
console.error('No message ID found for email');
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedHeader = Imap.parseHeader(header);
|
||||
const email = {
|
||||
id: messageId,
|
||||
from: parsedHeader.from?.[0] || '',
|
||||
to: parsedHeader.to?.[0] || '',
|
||||
subject: parsedHeader.subject?.[0] || '(No subject)',
|
||||
date: parsedHeader.date?.[0] || new Date().toISOString(),
|
||||
body: text,
|
||||
folder: folder,
|
||||
flags: messageFlags,
|
||||
read: messageFlags.includes('\\Seen'),
|
||||
starred: messageFlags.includes('\\Flagged')
|
||||
};
|
||||
emails.push(email);
|
||||
});
|
||||
});
|
||||
|
||||
fetch.on('error', (err) => {
|
||||
console.error(`Error fetching emails from ${folder}:`, err);
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
resolve(NextResponse.json({ emails: [], error: `Failed to fetch emails from ${folder}` }));
|
||||
});
|
||||
|
||||
fetch.on('end', () => {
|
||||
// Sort emails by date (most recent first)
|
||||
emails.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
||||
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
resolve(NextResponse.json({
|
||||
emails,
|
||||
folders: availableMailboxes,
|
||||
mailUrl: process.env.NEXT_PUBLIC_IFRAME_MAIL_URL
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
imap.connect();
|
||||
const client = new ImapFlow({
|
||||
host,
|
||||
port: parseInt(port),
|
||||
secure: true,
|
||||
auth: {
|
||||
user: email,
|
||||
pass: password,
|
||||
},
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
const mailbox = await client.mailboxOpen('INBOX');
|
||||
const messages = await client.fetch('1:10', { envelope: true });
|
||||
|
||||
const result = [];
|
||||
for await (const message of messages) {
|
||||
result.push({
|
||||
id: message.uid,
|
||||
subject: message.envelope.subject,
|
||||
from: message.envelope.from[0].address,
|
||||
date: message.envelope.date,
|
||||
});
|
||||
}
|
||||
|
||||
await client.logout();
|
||||
return NextResponse.json(result);
|
||||
} catch (error) {
|
||||
console.error('Error in GET /api/mail:', error);
|
||||
console.error('Mail API error:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to fetch emails' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const credentials = getStoredCredentials();
|
||||
if (!credentials) {
|
||||
return NextResponse.json(
|
||||
{ error: 'No stored credentials found' },
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
let body;
|
||||
try {
|
||||
body = await request.json();
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid JSON in request body' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const { to, subject, body: emailBody, attachments } = body;
|
||||
|
||||
if (!to || !subject || !emailBody) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Missing required fields: to, subject, or body' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: credentials.host,
|
||||
port: credentials.port,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: credentials.email,
|
||||
pass: credentials.password,
|
||||
},
|
||||
});
|
||||
|
||||
const mailOptions = {
|
||||
from: credentials.email,
|
||||
to,
|
||||
subject,
|
||||
text: emailBody,
|
||||
attachments: attachments || [],
|
||||
};
|
||||
|
||||
const info = await transporter.sendMail(mailOptions);
|
||||
console.log('Email sent:', info.messageId);
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
messageId: info.messageId,
|
||||
message: 'Email sent successfully'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error sending email:', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: error instanceof Error ? error.message : 'Failed to send email',
|
||||
details: error instanceof Error ? error.stack : undefined
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,6 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { setCookie } from 'cookies-next';
|
||||
|
||||
export default function LoginPage() {
|
||||
const router = useRouter();
|
||||
@ -43,34 +42,24 @@ export default function LoginPage() {
|
||||
throw new Error(testData.error || 'Failed to connect to email server');
|
||||
}
|
||||
|
||||
// Store all credentials in a single cookie
|
||||
const credentials = {
|
||||
email,
|
||||
password,
|
||||
host,
|
||||
port: parseInt(port),
|
||||
};
|
||||
|
||||
console.log('Storing credentials in cookie:', {
|
||||
...credentials,
|
||||
password: '***'
|
||||
// Store credentials using the API endpoint
|
||||
const loginResponse = await fetch('/api/mail/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
password,
|
||||
host,
|
||||
port,
|
||||
}),
|
||||
});
|
||||
|
||||
// Store as a single cookie with proper options
|
||||
setCookie('imap_credentials', JSON.stringify(credentials), {
|
||||
maxAge: 60 * 60 * 24, // 1 day
|
||||
path: '/',
|
||||
sameSite: 'lax',
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
httpOnly: false // Allow access from JavaScript
|
||||
});
|
||||
const loginData = await loginResponse.json();
|
||||
|
||||
// Verify cookie was set
|
||||
const stored = document.cookie.split(';').find(c => c.trim().startsWith('imap_credentials='));
|
||||
console.log('Cookie verification:', stored ? 'Cookie found' : 'Cookie not found');
|
||||
|
||||
if (!stored) {
|
||||
throw new Error('Failed to store credentials');
|
||||
if (!loginResponse.ok) {
|
||||
throw new Error(loginData.error || 'Failed to store credentials');
|
||||
}
|
||||
|
||||
// Redirect to mail page
|
||||
|
||||
@ -18,6 +18,14 @@ export default withAuth(
|
||||
if (req.nextUrl.pathname === "/" || req.nextUrl.pathname === "/signin") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the request is for an API route
|
||||
if (req.nextUrl.pathname.startsWith('/api/')) {
|
||||
// For API routes, require a valid token
|
||||
return !!token;
|
||||
}
|
||||
|
||||
// For all other routes, require a valid token
|
||||
return !!token;
|
||||
},
|
||||
},
|
||||
|
||||
10
node_modules/.package-lock.json
generated
vendored
10
node_modules/.package-lock.json
generated
vendored
@ -2214,6 +2214,16 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/imapflow": {
|
||||
"version": "1.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/imapflow/-/imapflow-1.0.20.tgz",
|
||||
"integrity": "sha512-kmBeiV815byuxYlu2lomAx3VY3SsyOYg4rDsK5vT6CGZ6Sow2AUEZwieql8uAizO6+p4sQchw/g3vQX76XBIpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mailparser": {
|
||||
"version": "3.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.5.tgz",
|
||||
|
||||
21
node_modules/@types/imapflow/LICENSE
generated
vendored
Normal file
21
node_modules/@types/imapflow/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
15
node_modules/@types/imapflow/README.md
generated
vendored
Normal file
15
node_modules/@types/imapflow/README.md
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Installation
|
||||
> `npm install --save @types/imapflow`
|
||||
|
||||
# Summary
|
||||
This package contains type definitions for imapflow (https://imapflow.com/).
|
||||
|
||||
# Details
|
||||
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/imapflow.
|
||||
|
||||
### Additional Details
|
||||
* Last updated: Mon, 03 Mar 2025 07:02:16 GMT
|
||||
* Dependencies: [@types/node](https://npmjs.com/package/@types/node)
|
||||
|
||||
# Credits
|
||||
These definitions were written by [Jeffrey Ratton](https://github.com/jeffreyratton98), [Martin Badin](https://github.com/martin-badin), [Northern Star](https://github.com/grayson-code), and [Zachary Nawar](https://github.com/remscar).
|
||||
393
node_modules/@types/imapflow/index.d.ts
generated
vendored
Normal file
393
node_modules/@types/imapflow/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,393 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
import { EventEmitter } from "stream";
|
||||
|
||||
export type Readable = import("stream").Readable;
|
||||
|
||||
export class ImapFlow extends EventEmitter {
|
||||
constructor(options: ImapFlowOptions);
|
||||
authenticated: string | boolean;
|
||||
capabilities: Map<string, (boolean | number)>;
|
||||
emitLogs: boolean;
|
||||
enabled: Set<string>;
|
||||
id: string;
|
||||
idling: boolean;
|
||||
mailbox: MailboxObject | boolean;
|
||||
secureConnection: boolean;
|
||||
serverInfo: IdInfoObject;
|
||||
usable: boolean;
|
||||
|
||||
append(
|
||||
path: string,
|
||||
content: string | Buffer,
|
||||
flags?: string[],
|
||||
idate?: Date | string,
|
||||
): Promise<AppendResonseObject>;
|
||||
|
||||
connect(): Promise<void>;
|
||||
logout(): Promise<void>;
|
||||
close(): void;
|
||||
download(
|
||||
range: SequenceString,
|
||||
part?: string,
|
||||
options?: { uid?: boolean; maxBytes?: number; chunkSize?: number },
|
||||
): Promise<DownloadObject>;
|
||||
|
||||
getMailboxLock(path: string, options?: null | { readonly?: boolean }): Promise<MailboxLockObject>;
|
||||
|
||||
getQuota(path: string): Promise<QuotaResponse | boolean>;
|
||||
|
||||
idle(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* @see {@link https://imapflow.com/module-imapflow-ImapFlow.html#list}
|
||||
*/
|
||||
list(options?: {
|
||||
statusQuery?: StatusQuery;
|
||||
specialUseHints?: SpecialUseHints;
|
||||
}): Promise<ListResponse[]>;
|
||||
|
||||
listTree(): Promise<ListTreeResponse>;
|
||||
|
||||
mailboxClose(): Promise<boolean>;
|
||||
|
||||
mailboxCreate(path: string | any[]): Promise<MailboxCreateResponse>;
|
||||
|
||||
mailboxDelete(path: string | any[]): Promise<MailboxDeleteResponse>;
|
||||
|
||||
mailboxOpen(path: string | any[], options?: { readOnly?: boolean }): Promise<MailboxObject>;
|
||||
|
||||
mailboxRename(path: string | any[], newPath: string | any[]): Promise<MailboxRenameResponse>;
|
||||
|
||||
mailboxSubscribe(path: string | any[]): Promise<boolean>;
|
||||
|
||||
mailboxUnsubscribe(path: string | any[]): Promise<boolean>;
|
||||
|
||||
messageCopy(
|
||||
range: SequenceString | number[] | SearchObject,
|
||||
destination: string,
|
||||
options?: { uid?: boolean },
|
||||
): Promise<CopyResponseObject>;
|
||||
|
||||
messageDelete(range: SequenceString | number[] | SearchObject, options?: { uid?: boolean }): Promise<boolean>;
|
||||
|
||||
messageFlagsAdd(
|
||||
range: SequenceString | number[] | SearchObject,
|
||||
Array: string[],
|
||||
options?: { uid?: boolean; unchangedSince?: bigint; useLabels?: boolean },
|
||||
): Promise<boolean>;
|
||||
|
||||
messageFlagsRemove(
|
||||
range: SequenceString | number[] | SearchObject,
|
||||
Array: string[],
|
||||
options?: { uid?: boolean; unchangedSince?: bigint; useLabels?: boolean },
|
||||
): Promise<boolean>;
|
||||
|
||||
messageFlagsSet(
|
||||
range: SequenceString | number[] | SearchObject,
|
||||
Array: string[],
|
||||
options?: { uid?: boolean; unchangedSince?: bigint; useLabels?: boolean },
|
||||
): Promise<boolean>;
|
||||
|
||||
messageMove(
|
||||
range: SequenceString | number[] | SearchObject,
|
||||
destination: string,
|
||||
options?: { uid?: boolean },
|
||||
): Promise<CopyResponseObject>;
|
||||
|
||||
fetchOne(
|
||||
seq: SequenceString,
|
||||
query: FetchQueryObject,
|
||||
options?: {
|
||||
uid?: boolean;
|
||||
},
|
||||
): Promise<FetchMessageObject>;
|
||||
|
||||
noop(): Promise<void>;
|
||||
|
||||
search(query: SearchObject, options?: { uid?: boolean }): Promise<number[]>;
|
||||
|
||||
status(
|
||||
path: string,
|
||||
query: {
|
||||
messages?: boolean;
|
||||
recent?: boolean;
|
||||
uidNext?: boolean;
|
||||
uidValidity?: boolean;
|
||||
unseen?: boolean;
|
||||
highestModseq?: boolean;
|
||||
},
|
||||
): Promise<StatusObject>;
|
||||
|
||||
fetch(
|
||||
range: SequenceString | number[] | SearchObject,
|
||||
query: FetchQueryObject,
|
||||
options?: { uid?: boolean; changedSince?: bigint; binary?: boolean },
|
||||
): AsyncGenerator<FetchMessageObject, never, void>;
|
||||
|
||||
fetchAll(
|
||||
range: SequenceString | number[] | SearchObject,
|
||||
query: FetchQueryObject,
|
||||
options?: { uid?: boolean; changedSince?: bigint; binary?: boolean },
|
||||
): Promise<FetchMessageObject[]>;
|
||||
}
|
||||
|
||||
export interface ImapFlowOptions {
|
||||
host: string;
|
||||
port: number;
|
||||
auth: {
|
||||
user: string;
|
||||
pass?: string;
|
||||
accessToken?: string;
|
||||
};
|
||||
secure?: boolean;
|
||||
servername?: string;
|
||||
disableCompression?: boolean;
|
||||
clientInfo?: IdInfoObject;
|
||||
disableAutoIdle?: boolean;
|
||||
tls?: object;
|
||||
logger?: Logger | false;
|
||||
emitLogs?: boolean;
|
||||
verifyOnly?: boolean;
|
||||
logRaw?: boolean;
|
||||
proxy?: string;
|
||||
qresync?: boolean;
|
||||
maxIdleTime?: number;
|
||||
missingIdleCommand?: string;
|
||||
disableBinary?: boolean;
|
||||
disableAutoEnable?: boolean;
|
||||
connectionTimeout?: number;
|
||||
greetingTimeout?: number;
|
||||
socketTimeout?: number;
|
||||
}
|
||||
|
||||
export interface AppendResonseObject {
|
||||
path: string;
|
||||
uidValidity?: bigint;
|
||||
uid?: number;
|
||||
seq?: number;
|
||||
}
|
||||
|
||||
export interface CopyResponseObject {
|
||||
path: string;
|
||||
destination: string;
|
||||
uidValidity?: bigint;
|
||||
uidMap?: Map<number, number>;
|
||||
}
|
||||
|
||||
export interface DownloadObject {
|
||||
content: Readable;
|
||||
meta: {
|
||||
expectedSize: number;
|
||||
contentType: string;
|
||||
charset?: string;
|
||||
disposition?: string;
|
||||
filename?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MailboxObject {
|
||||
path: string;
|
||||
delimeter: string;
|
||||
flags: Set<string>;
|
||||
specialUse: string;
|
||||
listed: boolean;
|
||||
subscribed: boolean;
|
||||
permanentFlags: Set<string>;
|
||||
mailboxId: string;
|
||||
highestModseq: BigInt;
|
||||
uidValidity: BigInt;
|
||||
uidNext: number;
|
||||
exists: number;
|
||||
}
|
||||
|
||||
export interface MailboxLockObject {
|
||||
path: string;
|
||||
release: () => void;
|
||||
}
|
||||
|
||||
export interface FetchMessageObject {
|
||||
seq: number;
|
||||
uid: number;
|
||||
source: Buffer;
|
||||
modseq: BigInt;
|
||||
emailId: string;
|
||||
threadId?: string;
|
||||
labels: Set<string>;
|
||||
size: number;
|
||||
flags: Set<string>;
|
||||
envelope: MessageEnvelopeObject;
|
||||
bodyStructure: MessageStructureObject;
|
||||
internalDate: Date;
|
||||
bodyParts: Map<string, Buffer>;
|
||||
headers: Buffer;
|
||||
}
|
||||
|
||||
export interface FetchQueryObject {
|
||||
uid?: boolean;
|
||||
flags?: boolean;
|
||||
bodyStructure?: boolean;
|
||||
envelope?: boolean;
|
||||
internalDate?: boolean;
|
||||
size?: boolean;
|
||||
source?: boolean | object;
|
||||
threadId?: boolean;
|
||||
labels?: boolean;
|
||||
headers?: boolean | string[];
|
||||
bodyParts?: string[];
|
||||
}
|
||||
|
||||
export interface MailboxRenameResponse {
|
||||
path: string;
|
||||
newPath: string;
|
||||
}
|
||||
|
||||
export interface MessageAddressObject {
|
||||
name?: string;
|
||||
address?: string;
|
||||
}
|
||||
|
||||
export interface MessageEnvelopeObject {
|
||||
date: Date;
|
||||
subject: string;
|
||||
messageId: string;
|
||||
inReplyTo: string;
|
||||
from: MessageAddressObject[];
|
||||
sender: MessageAddressObject[];
|
||||
replyTo: MessageAddressObject[];
|
||||
to: MessageAddressObject[];
|
||||
cc: MessageAddressObject[];
|
||||
bcc: MessageAddressObject[];
|
||||
}
|
||||
|
||||
export interface QuotaResponse {
|
||||
path: string;
|
||||
storage?: object;
|
||||
messages?: object;
|
||||
}
|
||||
|
||||
export type SequenceString = string;
|
||||
|
||||
export interface SearchObject {
|
||||
seq?: SequenceString;
|
||||
answered?: boolean;
|
||||
deleted?: boolean;
|
||||
draft?: boolean;
|
||||
flagged?: boolean;
|
||||
seen?: boolean;
|
||||
all?: boolean;
|
||||
new?: boolean;
|
||||
old?: boolean;
|
||||
recent?: boolean;
|
||||
from?: string;
|
||||
to?: string;
|
||||
cc?: string;
|
||||
bcc?: string;
|
||||
body?: string;
|
||||
subject?: string;
|
||||
larger?: number;
|
||||
smaller?: number;
|
||||
uid?: SequenceString;
|
||||
modseq?: bigint;
|
||||
emailId?: string;
|
||||
threadId?: string;
|
||||
before?: Date | string;
|
||||
on?: Date | string;
|
||||
since?: Date | string;
|
||||
sentBefore?: Date | string;
|
||||
sentOn?: Date | string;
|
||||
sentSince?: Date | string;
|
||||
keyword?: string;
|
||||
unKeyword?: string;
|
||||
header?: { [key: string]: boolean | string };
|
||||
or?: SearchObject[];
|
||||
}
|
||||
|
||||
export interface StatusObject {
|
||||
path: string;
|
||||
messages?: number;
|
||||
recent?: number;
|
||||
uidNext?: number;
|
||||
uidValidity?: bigint;
|
||||
unseen?: number;
|
||||
highestModseq?: bigint;
|
||||
}
|
||||
|
||||
export interface IdInfoObject {
|
||||
name?: string;
|
||||
version?: string;
|
||||
os?: string;
|
||||
vendor?: string;
|
||||
"support-url"?: string;
|
||||
date?: Date;
|
||||
}
|
||||
|
||||
export interface ListResponse {
|
||||
path: string;
|
||||
name: string;
|
||||
delimiter: string;
|
||||
flags: Set<string>;
|
||||
specialUse: string;
|
||||
listed: boolean;
|
||||
subscribed: boolean;
|
||||
status?: StatusObject;
|
||||
}
|
||||
|
||||
export interface ListTreeResponse {
|
||||
root: boolean;
|
||||
path: string;
|
||||
name: string;
|
||||
delimiter: string;
|
||||
flags: [];
|
||||
specialUse: string;
|
||||
listed: boolean;
|
||||
subscribed: boolean;
|
||||
disabled: boolean;
|
||||
folders: ListTreeResponse[];
|
||||
}
|
||||
|
||||
export interface MailboxCreateResponse {
|
||||
path: string;
|
||||
mailboxId?: string;
|
||||
created: boolean;
|
||||
}
|
||||
|
||||
export interface MailboxDeleteResponse {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface MessageStructureObject {
|
||||
part: string;
|
||||
type: string;
|
||||
parameters: string;
|
||||
id: string;
|
||||
encoding: string;
|
||||
size: number;
|
||||
envelope: MessageEnvelopeObject;
|
||||
disposition: string;
|
||||
dispositionParameters: string;
|
||||
childNodes: MessageStructureObject[];
|
||||
}
|
||||
|
||||
export interface Logger {
|
||||
debug: (obj: object) => void;
|
||||
info: (obj: object) => void;
|
||||
warn: (obj: object) => void;
|
||||
error: (obj: object) => void;
|
||||
}
|
||||
|
||||
export interface StatusQuery {
|
||||
messages?: boolean;
|
||||
recent?: boolean;
|
||||
uidNext?: boolean;
|
||||
uidValidity?: boolean;
|
||||
unseen?: boolean;
|
||||
highestModseq?: boolean;
|
||||
}
|
||||
|
||||
export interface SpecialUseHints {
|
||||
sent: string;
|
||||
trash: string;
|
||||
junk: string;
|
||||
drafts: string;
|
||||
}
|
||||
43
node_modules/@types/imapflow/package.json
generated
vendored
Normal file
43
node_modules/@types/imapflow/package.json
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@types/imapflow",
|
||||
"version": "1.0.20",
|
||||
"description": "TypeScript definitions for imapflow",
|
||||
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/imapflow",
|
||||
"license": "MIT",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Jeffrey Ratton",
|
||||
"githubUsername": "jeffreyratton98",
|
||||
"url": "https://github.com/jeffreyratton98"
|
||||
},
|
||||
{
|
||||
"name": "Martin Badin",
|
||||
"githubUsername": "martin-badin",
|
||||
"url": "https://github.com/martin-badin"
|
||||
},
|
||||
{
|
||||
"name": "Northern Star",
|
||||
"githubUsername": "grayson-code",
|
||||
"url": "https://github.com/grayson-code"
|
||||
},
|
||||
{
|
||||
"name": "Zachary Nawar",
|
||||
"githubUsername": "remscar",
|
||||
"url": "https://github.com/remscar"
|
||||
}
|
||||
],
|
||||
"main": "",
|
||||
"types": "index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||
"directory": "types/imapflow"
|
||||
},
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"typesPublisherContentHash": "5a7661a9dee2cf2fab17d371ef006249b141fe3d09adc38c21661ce457b282ac",
|
||||
"typeScriptVersion": "5.0"
|
||||
}
|
||||
11
package-lock.json
generated
11
package-lock.json
generated
@ -75,6 +75,7 @@
|
||||
"vaul": "^0.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/imapflow": "^1.0.20",
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
@ -2831,6 +2832,16 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/imapflow": {
|
||||
"version": "1.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/imapflow/-/imapflow-1.0.20.tgz",
|
||||
"integrity": "sha512-kmBeiV815byuxYlu2lomAx3VY3SsyOYg4rDsK5vT6CGZ6Sow2AUEZwieql8uAizO6+p4sQchw/g3vQX76XBIpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mailparser": {
|
||||
"version": "3.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.5.tgz",
|
||||
|
||||
@ -76,6 +76,7 @@
|
||||
"vaul": "^0.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/imapflow": "^1.0.20",
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
|
||||
@ -1014,6 +1014,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/imapflow@^1.0.20":
|
||||
version "1.0.20"
|
||||
resolved "https://registry.npmjs.org/@types/imapflow/-/imapflow-1.0.20.tgz"
|
||||
integrity sha512-kmBeiV815byuxYlu2lomAx3VY3SsyOYg4rDsK5vT6CGZ6Sow2AUEZwieql8uAizO6+p4sQchw/g3vQX76XBIpA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/mailparser@^3.4.5":
|
||||
version "3.4.5"
|
||||
resolved "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.5.tgz"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user