249 lines
6.8 KiB
TypeScript
249 lines
6.8 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import Imap from 'imap';
|
|
import { simpleParser } from 'mailparser';
|
|
import getConfig from 'next/config';
|
|
|
|
// Get server runtime config
|
|
const { serverRuntimeConfig } = getConfig();
|
|
|
|
// Debug logging for environment variables
|
|
console.log('Environment Variables:', {
|
|
IMAP_USER: serverRuntimeConfig.IMAP_USER,
|
|
IMAP_HOST: serverRuntimeConfig.IMAP_HOST,
|
|
IMAP_PORT: serverRuntimeConfig.IMAP_PORT,
|
|
IMAP_PASSWORD: serverRuntimeConfig.IMAP_PASSWORD ? '***' : undefined,
|
|
NODE_ENV: process.env.NODE_ENV
|
|
});
|
|
|
|
// IMAP configuration
|
|
const imapConfig: Imap.Config = {
|
|
user: serverRuntimeConfig.IMAP_USER as string,
|
|
password: serverRuntimeConfig.IMAP_PASSWORD as string,
|
|
host: serverRuntimeConfig.IMAP_HOST || 'mail.infomaniak.com',
|
|
port: parseInt(serverRuntimeConfig.IMAP_PORT || '993', 10),
|
|
tls: true,
|
|
tlsOptions: {
|
|
rejectUnauthorized: false,
|
|
servername: serverRuntimeConfig.IMAP_HOST || 'mail.infomaniak.com'
|
|
},
|
|
authTimeout: 10000,
|
|
connTimeout: 10000,
|
|
debug: console.log // Enable IMAP debug logging
|
|
};
|
|
|
|
// Debug logging for IMAP configuration
|
|
console.log('IMAP Configuration:', {
|
|
user: imapConfig.user,
|
|
host: imapConfig.host,
|
|
port: imapConfig.port,
|
|
tls: imapConfig.tls,
|
|
hasPassword: !!imapConfig.password,
|
|
authTimeout: imapConfig.authTimeout,
|
|
connTimeout: imapConfig.connTimeout
|
|
});
|
|
|
|
// Validate IMAP configuration
|
|
if (!imapConfig.user || !imapConfig.password) {
|
|
console.error('IMAP configuration error:', {
|
|
user: imapConfig.user,
|
|
hasPassword: !!imapConfig.password
|
|
});
|
|
throw new Error('IMAP credentials are not properly configured. Please check your .env file.');
|
|
}
|
|
|
|
interface ImapMessage {
|
|
header: {
|
|
from?: string[];
|
|
to?: string[];
|
|
subject?: string[];
|
|
date?: string[];
|
|
[key: string]: string[] | undefined;
|
|
};
|
|
body: string;
|
|
attributes: {
|
|
flags: string[];
|
|
};
|
|
}
|
|
|
|
interface ImapError extends Error {
|
|
type?: string;
|
|
textCode?: string;
|
|
source?: string;
|
|
}
|
|
|
|
// Helper function to create a promise-based IMAP connection
|
|
function createImapConnection() {
|
|
return new Promise((resolve, reject) => {
|
|
console.log('Creating new IMAP connection with config:', {
|
|
user: imapConfig.user,
|
|
host: imapConfig.host,
|
|
port: imapConfig.port,
|
|
tls: imapConfig.tls
|
|
});
|
|
|
|
const imap = new Imap(imapConfig);
|
|
|
|
imap.once('ready', () => {
|
|
console.log('IMAP connection established successfully');
|
|
resolve(imap);
|
|
});
|
|
|
|
imap.once('error', (err: ImapError) => {
|
|
console.error('IMAP connection error:', err);
|
|
console.error('Error details:', {
|
|
type: err.type,
|
|
textCode: err.textCode,
|
|
source: err.source
|
|
});
|
|
reject(err);
|
|
});
|
|
|
|
imap.once('end', () => {
|
|
console.log('IMAP connection ended');
|
|
});
|
|
|
|
try {
|
|
console.log('Attempting to connect to IMAP server...');
|
|
imap.connect();
|
|
} catch (err) {
|
|
console.error('Error during IMAP connection:', err);
|
|
reject(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Helper function to promisify the message fetching
|
|
function fetchMessages(imap: Imap, box: string): Promise<ImapMessage[]> {
|
|
return new Promise((resolve, reject) => {
|
|
imap.openBox(box, false, (err, mailbox) => {
|
|
if (err) {
|
|
reject(err);
|
|
return;
|
|
}
|
|
|
|
// Search for all messages
|
|
imap.search(['ALL'], (err, results) => {
|
|
if (err) {
|
|
reject(err);
|
|
return;
|
|
}
|
|
|
|
// No messages found
|
|
if (!results || !results.length) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
|
|
const fetch = imap.fetch(results, {
|
|
bodies: ['HEADER.FIELDS (FROM TO SUBJECT DATE)', 'TEXT'],
|
|
struct: true
|
|
});
|
|
|
|
const messages: ImapMessage[] = [];
|
|
|
|
fetch.on('message', (msg) => {
|
|
const message: Partial<ImapMessage> = {};
|
|
|
|
msg.on('body', (stream, info) => {
|
|
let buffer = '';
|
|
stream.on('data', (chunk) => {
|
|
buffer += chunk.toString('utf8');
|
|
});
|
|
stream.once('end', () => {
|
|
if (info.which === 'TEXT') {
|
|
message.body = buffer;
|
|
} else {
|
|
message.header = Imap.parseHeader(buffer);
|
|
}
|
|
});
|
|
});
|
|
|
|
msg.once('attributes', (attrs) => {
|
|
message.attributes = attrs;
|
|
});
|
|
|
|
msg.once('end', () => {
|
|
messages.push(message as ImapMessage);
|
|
});
|
|
});
|
|
|
|
fetch.once('error', (err) => {
|
|
reject(err);
|
|
});
|
|
|
|
fetch.once('end', () => {
|
|
resolve(messages);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
export async function GET(request: Request) {
|
|
try {
|
|
console.log('Starting email fetch process...');
|
|
|
|
// Validate IMAP configuration
|
|
if (!imapConfig.user || !imapConfig.password) {
|
|
console.error('IMAP configuration error:', {
|
|
user: imapConfig.user,
|
|
hasPassword: !!imapConfig.password
|
|
});
|
|
throw new Error('IMAP credentials are not properly configured. Please check your .env file.');
|
|
}
|
|
|
|
console.log('Creating IMAP connection...');
|
|
const imap = await createImapConnection() as Imap;
|
|
|
|
console.log('Fetching messages...');
|
|
const messages = await fetchMessages(imap, 'INBOX');
|
|
|
|
console.log(`Successfully fetched ${messages.length} messages`);
|
|
|
|
// Process messages into the format expected by the frontend
|
|
const processedMessages = messages.map((msg: ImapMessage, index: number) => ({
|
|
id: index + 1,
|
|
accountId: 1,
|
|
from: msg.header.from?.[0] || '',
|
|
fromName: (msg.header.from?.[0] || '').split('<')[0].trim(),
|
|
to: msg.header.to?.[0] || '',
|
|
subject: msg.header.subject?.[0] || '',
|
|
body: msg.body || '',
|
|
date: msg.header.date?.[0] || new Date().toISOString(),
|
|
read: !(msg.attributes.flags.indexOf('\\Seen') < 0),
|
|
starred: !(msg.attributes.flags.indexOf('\\Flagged') < 0),
|
|
category: 'inbox'
|
|
}));
|
|
|
|
imap.end();
|
|
return NextResponse.json({ messages: processedMessages });
|
|
|
|
} catch (error) {
|
|
console.error('Error in GET handler:', error);
|
|
return NextResponse.json({
|
|
error: 'Failed to fetch emails',
|
|
details: error instanceof Error ? error.message : 'Unknown error'
|
|
}, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// Add endpoint to get mailboxes
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const imap = await createImapConnection() as Imap;
|
|
|
|
const mailboxes = await new Promise((resolve, reject) => {
|
|
imap.getBoxes((err, boxes) => {
|
|
if (err) reject(err);
|
|
resolve(boxes);
|
|
});
|
|
});
|
|
|
|
imap.end();
|
|
return NextResponse.json({ mailboxes });
|
|
|
|
} catch (error) {
|
|
console.error('Error fetching mailboxes:', error);
|
|
return NextResponse.json({ error: 'Failed to fetch mailboxes' }, { status: 500 });
|
|
}
|
|
}
|