port-nimara-client-portal/components/EmailCredentialsSetup.vue

254 lines
7.8 KiB
Vue

<template>
<v-card>
<v-card-title class="text-h6 d-flex align-center">
<v-icon class="mr-2">mdi-email-lock</v-icon>
Email Account Setup
</v-card-title>
<v-card-text>
<v-alert type="info" variant="tonal" class="mb-4">
Enter your email credentials to send and receive emails. Your password is encrypted and stored only for this session.
</v-alert>
<v-form @submit.prevent="testConnection" ref="form">
<v-text-field
v-model="credentials.email"
label="Email Address"
type="email"
variant="outlined"
density="comfortable"
prepend-inner-icon="mdi-email"
:rules="[rules.required, rules.email]"
:disabled="testing"
/>
<v-text-field
v-model="credentials.password"
label="Password"
:type="showPassword ? 'text' : 'password'"
variant="outlined"
density="comfortable"
prepend-inner-icon="mdi-lock"
:append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
@click:append-inner="showPassword = !showPassword"
:rules="[rules.required]"
:disabled="testing"
/>
<v-expansion-panels variant="accordion" class="mb-4">
<v-expansion-panel>
<v-expansion-panel-title>
<v-icon class="mr-2">mdi-cog</v-icon>
Advanced Settings
</v-expansion-panel-title>
<v-expansion-panel-text>
<v-text-field
v-model="credentials.imapHost"
label="IMAP Host"
variant="outlined"
density="comfortable"
placeholder="mail.portnimara.com"
:disabled="testing"
/>
<v-text-field
v-model="credentials.smtpHost"
label="SMTP Host"
variant="outlined"
density="comfortable"
placeholder="mail.portnimara.com"
:disabled="testing"
/>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel>
<v-expansion-panel-title>
<v-icon class="mr-2">mdi-card-account-details</v-icon>
Email Signature
</v-expansion-panel-title>
<v-expansion-panel-text>
<v-text-field
v-model="signature.name"
label="Your Name"
variant="outlined"
density="comfortable"
placeholder="John Doe"
class="mb-3"
/>
<v-text-field
v-model="signature.title"
label="Job Title"
variant="outlined"
density="comfortable"
placeholder="Sales & Marketing Director"
class="mb-3"
/>
<v-text-field
v-model="signature.company"
label="Company"
variant="outlined"
density="comfortable"
placeholder="Port Nimara"
class="mb-3"
/>
<v-textarea
v-model="signature.contactInfo"
label="Additional Contact Info"
variant="outlined"
density="comfortable"
rows="3"
placeholder="Phone: +1234567890&#10;Mobile: +0987654321"
/>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
<v-btn
type="submit"
color="primary"
block
size="large"
:loading="testing"
:disabled="testing"
>
<v-icon start>mdi-connection</v-icon>
Test Connection & Continue
</v-btn>
</v-form>
</v-card-text>
</v-card>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
interface Emits {
(e: 'connected', email: string): void;
(e: 'credentials-saved', data: { sessionId: string }): void;
}
const emit = defineEmits<Emits>();
const user = useDirectusUser();
const toast = useToast();
const form = ref();
const testing = ref(false);
const showPassword = ref(false);
const credentials = ref({
email: '',
password: '',
imapHost: '',
smtpHost: ''
});
const signature = ref({
name: '',
title: 'Sales & Marketing Director',
company: 'Port Nimara',
contactInfo: ''
});
const rules = {
required: (v: string) => !!v || 'Required',
email: (v: string) => /.+@.+\..+/.test(v) || 'Invalid email'
};
// Generate or get session ID
const getSessionId = () => {
let sessionId = localStorage.getItem('emailSessionId');
if (!sessionId) {
sessionId = `session-${Date.now()}-${Math.random().toString(36).substring(2)}`;
localStorage.setItem('emailSessionId', sessionId);
}
return sessionId;
};
const testConnection = async () => {
// Prevent multiple simultaneous connection attempts
if (testing.value) {
console.log('[EmailCredentialsSetup] Connection test already in progress, ignoring');
return;
}
const { valid } = await form.value.validate();
if (!valid) return;
testing.value = true;
try {
const response = await $fetch<{ success: boolean; message: string; email: string }>('/api/email/test-connection', {
method: 'POST',
headers: {
'x-tag': user.value?.email ? '094ut234' : 'pjnvü1230',
},
body: {
email: credentials.value.email,
password: credentials.value.password,
imapHost: credentials.value.imapHost || undefined,
smtpHost: credentials.value.smtpHost || undefined,
sessionId: getSessionId()
},
timeout: 15000 // 15 second timeout
});
if (response.success) {
toast.success('Email connection successful!');
// Store email and signature config
localStorage.setItem('connectedEmail', credentials.value.email);
localStorage.setItem('emailSignature', JSON.stringify(signature.value));
// Emit both events for compatibility
emit('connected', credentials.value.email);
emit('credentials-saved', { sessionId: getSessionId() });
}
} catch (error: any) {
console.error('Connection test failed:', error);
// If it's a timeout error, offer to proceed anyway
if (error.message?.includes('timeout') || error.statusCode === 504) {
const proceed = confirm('Connection test timed out, but the email system might still work. Would you like to proceed anyway?');
if (proceed) {
// Store credentials anyway
toast.info('Proceeding with email setup...');
localStorage.setItem('connectedEmail', credentials.value.email);
localStorage.setItem('emailSignature', JSON.stringify(signature.value));
// Manually store encrypted credentials
try {
// Generate a session ID if not already present
const sessionId = getSessionId();
// We'll trust that the credentials are correct and proceed
emit('connected', credentials.value.email);
emit('credentials-saved', { sessionId: sessionId });
} catch (e) {
console.error('Failed to store credentials:', e);
}
}
} else {
toast.error(error.data?.statusMessage || 'Failed to connect to email server');
}
} finally {
testing.value = false;
}
};
// Pre-fill email from user if available
onMounted(() => {
if (user.value?.email) {
credentials.value.email = user.value.email;
}
// Load saved signature
const savedSignature = localStorage.getItem('emailSignature');
if (savedSignature) {
try {
signature.value = JSON.parse(savedSignature);
} catch (e) {
console.error('Failed to load saved signature:', e);
}
}
});
</script>