This commit is contained in:
Matt 2025-06-10 02:10:32 +02:00
parent 662f22a58f
commit e388779e11
3 changed files with 129 additions and 23 deletions

View File

@ -24,7 +24,8 @@ export default defineEventHandler(async (event) => {
try {
const body = await readBody(event);
const { clientEmail, interestId, sessionId, limit = 20 } = body;
// Increase limit to get more complete threads
const { clientEmail, interestId, sessionId, limit = 200 } = body;
if (!clientEmail || !sessionId) {
throw createError({
@ -66,7 +67,21 @@ export default defineEventHandler(async (event) => {
const cachedEmails: EmailMessage[] = [];
if (interestId) {
try {
const files = await listFiles(`client-emails/interest-${interestId}/`, true) as any[];
// List files from the client-emails bucket
const client = getMinioClient();
const stream = client.listObjectsV2('client-emails', `interest-${interestId}/`, true);
const files: any[] = [];
await new Promise((resolve, reject) => {
stream.on('data', (obj) => {
if (obj && obj.name) {
files.push({ name: obj.name, size: obj.size || 0 });
}
});
stream.on('error', reject);
stream.on('end', resolve);
});
console.log('Found cached email files:', files.length);
for (const file of files) {
@ -74,10 +89,14 @@ export default defineEventHandler(async (event) => {
try {
// Read file directly on server using MinIO client (works with private buckets)
const client = getMinioClient();
const bucketName = useRuntimeConfig().minio.bucketName;
// Use the client-emails bucket directly
const bucketName = 'client-emails';
// The file.name is already the correct path within the bucket
const fileName = file.name;
// Get object as stream
const stream = await client.getObject(bucketName, file.name);
const stream = await client.getObject(bucketName, fileName);
// Convert stream to string
let data = '';
@ -224,16 +243,9 @@ async function fetchImapEmails(
return;
}
// Use date-based search to reduce the number of emails fetched
// Search for emails from the last 30 days
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
// Format date for IMAP (e.g., "1-Jan-2024")
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const searchDate = `${thirtyDaysAgo.getDate()}-${months[thirtyDaysAgo.getMonth()]}-${thirtyDaysAgo.getFullYear()}`;
imap.search(['SINCE', searchDate], (err, results) => {
// For specific client searches, don't use date filter to ensure we get complete threads
// Just get ALL emails and filter manually
imap.search(['ALL'], (err, results) => {
if (err) {
console.error(`Search error in ${folderName}:`, err);
searchNextFolder();
@ -316,11 +328,14 @@ async function fetchImapEmails(
interestId: interestId
};
const objectName = `client-emails/interest-${interestId}/${Date.now()}-${email.direction}.json`;
const objectName = `interest-${interestId}/${Date.now()}-${email.direction}.json`;
const buffer = Buffer.from(JSON.stringify(emailData, null, 2));
// Fire and forget - don't wait for upload
uploadFile(objectName, buffer, 'application/json').catch(err => {
// Upload to the client-emails bucket
const client = getMinioClient();
client.putObject('client-emails', objectName, buffer, buffer.length, {
'Content-Type': 'application/json',
}).catch(err => {
console.error('Failed to cache email:', err);
});
} catch (cacheError) {

View File

@ -107,14 +107,15 @@ export default defineEventHandler(async (event) => {
interestId: interestId
};
const objectName = `client-emails/interest-${interestId}/${Date.now()}-sent.json`;
const objectName = `interest-${interestId}/${Date.now()}-sent.json`;
const buffer = Buffer.from(JSON.stringify(emailData, null, 2));
await uploadFile(
objectName,
buffer,
'application/json'
);
// Upload to the client-emails bucket
const { getMinioClient } = await import('~/server/utils/minio');
const client = getMinioClient();
await client.putObject('client-emails', objectName, buffer, buffer.length, {
'Content-Type': 'application/json',
});
// Update EOI Time Sent if the email contains an EOI link
if (emailBody.includes('signatures.portnimara.dev/sign/')) {

View File

@ -0,0 +1,90 @@
import { getMinioClient } from '~/server/utils/minio';
export default defineEventHandler(async (event) => {
const xTagHeader = getRequestHeader(event, "x-tag");
if (!xTagHeader || (xTagHeader !== "094ut234" && xTagHeader !== "pjnvü1230")) {
throw createError({ statusCode: 401, statusMessage: "unauthenticated" });
}
try {
const query = getQuery(event);
const { interestId } = query;
const client = getMinioClient();
// Test 1: Check if client-emails bucket exists
const buckets = await client.listBuckets();
const clientEmailsBucket = buckets.find(b => b.name === 'client-emails');
if (!clientEmailsBucket) {
// Try to create the bucket
await client.makeBucket('client-emails', 'us-east-1');
}
// Test 2: List files in the bucket
const files: any[] = [];
const prefix = interestId ? `interest-${interestId}/` : '';
const stream = client.listObjectsV2('client-emails', prefix, true);
await new Promise((resolve, reject) => {
stream.on('data', (obj) => {
if (obj && obj.name) {
files.push({
name: obj.name,
size: obj.size || 0,
lastModified: obj.lastModified
});
}
});
stream.on('error', reject);
stream.on('end', resolve);
});
// Test 3: Try to write a test file
const testData = {
test: true,
timestamp: new Date().toISOString(),
message: 'MinIO bucket test'
};
const testObjectName = `test/${Date.now()}-test.json`;
const buffer = Buffer.from(JSON.stringify(testData, null, 2));
await client.putObject('client-emails', testObjectName, buffer, buffer.length, {
'Content-Type': 'application/json',
});
// Test 4: Try to read the test file back
const readStream = await client.getObject('client-emails', testObjectName);
let readData = '';
await new Promise((resolve, reject) => {
readStream.on('data', (chunk) => {
readData += chunk;
});
readStream.on('end', resolve);
readStream.on('error', reject);
});
// Clean up test file
await client.removeObject('client-emails', testObjectName);
return {
success: true,
bucketExists: !!clientEmailsBucket,
bucketCreated: !clientEmailsBucket,
filesInBucket: files.length,
files: files.slice(0, 10), // Show first 10 files
writeTestPassed: true,
readTestPassed: JSON.parse(readData).test === true
};
} catch (error) {
console.error('MinIO bucket test failed:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
details: error
};
}
});