Fix email system error handling and remove hardcoded credentials

- Handle missing email sessions gracefully without throwing errors
- Clear partial session data when no valid session exists
- Return empty results instead of 401 errors for missing credentials
- Remove hardcoded Documenso API key and require env variables
- Reduce email fetch limit from 50 to 20 for performance
- Add documentation for email system fixes
This commit is contained in:
Matt 2025-06-09 22:50:06 +02:00
parent f7cc2973e1
commit 5f10e9fb54
5 changed files with 103 additions and 9 deletions

View File

@ -76,6 +76,12 @@ const checkConnection = () => {
if (sessionId && email) { if (sessionId && email) {
isConnected.value = true; isConnected.value = true;
connectedEmail.value = email; connectedEmail.value = email;
} else {
// Clear any partial session data
sessionStorage.removeItem('emailSessionId');
sessionStorage.removeItem('connectedEmail');
isConnected.value = false;
connectedEmail.value = '';
} }
}; };

View File

@ -181,6 +181,15 @@ const truncateText = (text: string, maxLength: number = 200) => {
}; };
const loadEmails = async () => { const loadEmails = async () => {
// Check if we have a session ID before trying to fetch emails
const sessionId = getSessionId();
if (!sessionId) {
// No credentials, don't try to fetch
threads.value = [];
loading.value = false;
return;
}
loading.value = true; loading.value = true;
try { try {
@ -196,18 +205,19 @@ const loadEmails = async () => {
body: { body: {
clientEmail: props.interest['Email Address'], clientEmail: props.interest['Email Address'],
interestId: props.interest.Id, interestId: props.interest.Id,
sessionId: getSessionId(), sessionId: sessionId,
limit: 50 limit: 20
} }
}); });
if (response.success) { if (response.success) {
threads.value = response.threads; threads.value = response.threads || [];
} }
} catch (error: any) { } catch (error: any) {
console.error('Failed to load emails:', error); console.error('Failed to load emails:', error);
if (error.data?.statusMessage?.includes('Email credentials not found')) { if (error.data?.statusMessage?.includes('Email credentials not found')) {
// Don't show error, parent component should handle reconnection // Don't show error, parent component should handle reconnection
threads.value = [];
} else { } else {
toast.error(error.data?.statusMessage || 'Failed to load email history'); toast.error(error.data?.statusMessage || 'Failed to load email history');
} }

View File

@ -0,0 +1,69 @@
# Email System Fixes
## Issues Addressed
### 1. Email Credentials Not Found Errors
- **Problem**: The system was trying to fetch emails even when no credentials were present
- **Solution**:
- Added session ID check in `EmailThreadView` before attempting to fetch emails
- Modified `fetch-thread` API to return empty results instead of throwing errors when credentials are missing
- Added proper session cleanup in `EmailCommunication` component
### 2. 502 Gateway Timeout Errors
- **Problem**: Email fetching was causing timeouts, especially when editing/saving interest cards
- **Solution**:
- Reduced email fetch limit from 50 to 20 emails
- Added 15-second timeout for IMAP connections
- Prevented unnecessary email fetches when no session exists
### 3. EOI Generation Issues
- **Problem**: EOI generation may fail due to missing Documenso configuration
- **Solution**:
- Added environment variable validation for `NUXT_DOCUMENSO_API_KEY` and `NUXT_DOCUMENSO_BASE_URL`
- Improved error messages to indicate when configuration is missing
## Required Environment Variables
Make sure these are set in your `.env` file:
```env
# Email Configuration
NUXT_EMAIL_ENCRYPTION_KEY=your-32-character-encryption-key
NUXT_EMAIL_IMAP_HOST=mail.portnimara.com
NUXT_EMAIL_IMAP_PORT=993
NUXT_EMAIL_SMTP_HOST=mail.portnimara.com
NUXT_EMAIL_SMTP_PORT=587
NUXT_EMAIL_LOGO_URL=https://portnimara.com/logo.png
# Documenso Configuration (REQUIRED for EOI generation)
NUXT_DOCUMENSO_API_KEY=your-actual-api-key
NUXT_DOCUMENSO_BASE_URL=https://signatures.portnimara.dev
```
## How It Works Now
1. **Email Session Management**:
- Sessions are stored in browser's sessionStorage
- If no session exists, email features are gracefully disabled
- Users can connect/disconnect at any time
2. **Email Fetching**:
- Only attempts to fetch when valid session exists
- Limited to 20 emails to prevent timeouts
- Falls back to cached emails from MinIO if IMAP fails
- 15-second timeout prevents hanging connections
3. **EOI Generation**:
- Validates all required fields before attempting generation
- Checks for Documenso configuration
- Returns clear error messages if configuration is missing
- Inserts client's signing link directly into email body
## Troubleshooting
If you're still experiencing issues:
1. **Check Docker logs**: `docker logs <container-name>`
2. **Verify environment variables are set correctly**
3. **Ensure Documenso API credentials are valid**
4. **Try disconnecting and reconnecting email credentials**

View File

@ -36,10 +36,12 @@ export default defineEventHandler(async (event) => {
// Get encrypted credentials from session // Get encrypted credentials from session
const encryptedCredentials = getCredentialsFromSession(sessionId); const encryptedCredentials = getCredentialsFromSession(sessionId);
if (!encryptedCredentials) { if (!encryptedCredentials) {
throw createError({ // Return empty results instead of throwing error
statusCode: 401, return {
statusMessage: "Email credentials not found. Please reconnect." success: true,
}); emails: [],
threads: []
};
} }
// Decrypt credentials // Decrypt credentials

View File

@ -80,10 +80,17 @@ export default defineEventHandler(async (event) => {
const berthNumbers = berths.map(b => b['Mooring Number']).join(', '); const berthNumbers = berths.map(b => b['Mooring Number']).join(', ');
// Documenso API configuration // Documenso API configuration
const documensoApiKey = process.env.NUXT_DOCUMENSO_API_KEY || 'api_malptg62zqyb0wrp'; const documensoApiKey = process.env.NUXT_DOCUMENSO_API_KEY;
const documensoBaseUrl = process.env.NUXT_DOCUMENSO_BASE_URL || 'https://signatures.portnimara.dev'; const documensoBaseUrl = process.env.NUXT_DOCUMENSO_BASE_URL;
const templateId = '9'; const templateId = '9';
if (!documensoApiKey || !documensoBaseUrl) {
throw createError({
statusCode: 500,
statusMessage: "Documenso configuration missing. Please check NUXT_DOCUMENSO_API_KEY and NUXT_DOCUMENSO_BASE_URL environment variables."
});
}
// 1. Get template (optional - just to verify it exists) // 1. Get template (optional - just to verify it exists)
try { try {
const templateResponse = await fetch(`${documensoBaseUrl}/api/v1/templates/${templateId}`, { const templateResponse = await fetch(`${documensoBaseUrl}/api/v1/templates/${templateId}`, {