diff --git a/memento-note/app/(main)/admin/settings/admin-settings-form.tsx b/memento-note/app/(main)/admin/settings/admin-settings-form.tsx index eccb94d..53152b4 100644 --- a/memento-note/app/(main)/admin/settings/admin-settings-form.tsx +++ b/memento-note/app/(main)/admin/settings/admin-settings-form.tsx @@ -277,6 +277,8 @@ export function AdminSettingsForm({ config }: { config: Record } if (emailProvider === 'resend') { const key = formData.get('RESEND_API_KEY') as string if (key) data.RESEND_API_KEY = key + const from = formData.get('SMTP_FROM') as string + if (from) data.SMTP_FROM = from } else { data.SMTP_HOST = formData.get('SMTP_HOST') as string data.SMTP_PORT = formData.get('SMTP_PORT') as string @@ -300,6 +302,32 @@ export function AdminSettingsForm({ config }: { config: Record } const handleTestEmail = async () => { setIsTesting(true) try { + // Save email config to DB first so test uses the latest values + const emailForm = document.querySelector('form[name="email-form"]') as HTMLFormElement + if (emailForm) { + const formData = new FormData(emailForm) + const saveData: Record = { EMAIL_PROVIDER: emailProvider } + if (emailProvider === 'resend') { + const key = formData.get('RESEND_API_KEY') as string + if (key) saveData.RESEND_API_KEY = key + const from = formData.get('SMTP_FROM') as string + if (from) saveData.SMTP_FROM = from + } else { + saveData.SMTP_HOST = formData.get('SMTP_HOST') as string + saveData.SMTP_PORT = formData.get('SMTP_PORT') as string + saveData.SMTP_USER = formData.get('SMTP_USER') as string + saveData.SMTP_PASS = formData.get('SMTP_PASS') as string + saveData.SMTP_FROM = formData.get('SMTP_FROM') as string + saveData.SMTP_IGNORE_CERT = smtpIgnoreCert ? 'true' : 'false' + saveData.SMTP_SECURE = smtpSecure ? 'true' : 'false' + } + const saveResult = await updateSystemConfig(saveData) + if (saveResult.error) { + toast.error('Failed to save settings before testing: ' + saveResult.error) + setIsTesting(false) + return + } + } const result: any = await testEmail(emailProvider) if (result.success) { toast.success(t('admin.smtp.testSuccess')) @@ -892,7 +920,7 @@ export function AdminSettingsForm({ config }: { config: Record } {t('admin.email.title')} {t('admin.email.description')} -
{ e.preventDefault(); handleSaveEmail(new FormData(e.currentTarget)) }}> + { e.preventDefault(); handleSaveEmail(new FormData(e.currentTarget)) }}>
@@ -957,6 +985,11 @@ export function AdminSettingsForm({ config }: { config: Record }

{t('admin.resend.apiKeyHint')}

+
+ + +

Email address used as sender. Must be a domain verified in Resend.

+
{config.RESEND_API_KEY && (
diff --git a/memento-note/app/actions/notes.ts b/memento-note/app/actions/notes.ts index b4c3e41..d73adc7 100644 --- a/memento-note/app/actions/notes.ts +++ b/memento-note/app/actions/notes.ts @@ -509,10 +509,26 @@ export async function createNote(data: { console.log('[BG] Auto-labeling check: enabled=', autoLabelingEnabled, 'confidence=', autoLabelingConfidence, 'notebookId=', notebookId) if (autoLabelingEnabled) { + // Detect user's language from their existing notes for localized prompts + let userLang = 'en' + try { + const langResult = await prisma.note.groupBy({ + by: ['language'], + where: { userId, language: { not: null } }, + _count: true, + orderBy: { _count: { language: 'desc' } }, + take: 1, + }) + if (langResult.length > 0 && langResult[0].language) { + userLang = langResult[0].language + } + } catch {} + const suggestions = await contextualAutoTagService.suggestLabels( content, notebookId, - userId + userId, + userLang ) console.log('[BG] Auto-labeling suggestions:', suggestions.length, suggestions.map(s => s.label)) diff --git a/memento-note/lib/ai/services/contextual-auto-tag.service.ts b/memento-note/lib/ai/services/contextual-auto-tag.service.ts index e4ed5ff..4da9f80 100644 --- a/memento-note/lib/ai/services/contextual-auto-tag.service.ts +++ b/memento-note/lib/ai/services/contextual-auto-tag.service.ts @@ -5,7 +5,7 @@ */ import { prisma } from '@/lib/prisma' -import { getAIProvider } from '@/lib/ai/factory' +import { getTagsProvider } from '@/lib/ai/factory' import { getSystemConfig } from '@/lib/config' export interface LabelSuggestion { @@ -77,7 +77,7 @@ export class ContextualAutoTagService { try { const config = await getSystemConfig() - const provider = getAIProvider(config) + const provider = getTagsProvider(config) // Use generateText with JSON response const response = await provider.generateText(prompt) @@ -161,7 +161,7 @@ export class ContextualAutoTagService { try { const config = await getSystemConfig() - const provider = getAIProvider(config) + const provider = getTagsProvider(config) // Use generateText with JSON response const response = await provider.generateText(prompt) diff --git a/memento-note/lib/mail.ts b/memento-note/lib/mail.ts index bd341a0..2d6e8ac 100644 --- a/memento-note/lib/mail.ts +++ b/memento-note/lib/mail.ts @@ -41,12 +41,12 @@ export async function sendEmail({ to, subject, html, attachments }: MailOptions, // Force Resend (no fallback) if (provider === 'resend') { if (!resendKey) return { success: false, error: 'No Resend API key configured' }; - return sendViaResend(resendKey, { to, subject, html, attachments }); + return sendViaResend(resendKey, config, { to, subject, html, attachments }); } // Auto: try Resend, fall back to SMTP if (resendKey) { - const result = await sendViaResend(resendKey, { to, subject, html, attachments }); + const result = await sendViaResend(resendKey, config, { to, subject, html, attachments }); if (result.success) return result; console.warn('[Mail] Resend failed, falling back to SMTP:', result.error); @@ -56,14 +56,13 @@ export async function sendEmail({ to, subject, html, attachments }: MailOptions, return sendViaSMTP(config, { to, subject, html, attachments }); } -async function sendViaResend(apiKey: string, { to, subject, html, attachments }: MailOptions): Promise { +async function sendViaResend(apiKey: string, config: Record, { to, subject, html, attachments }: MailOptions): Promise { try { const { Resend } = await import('resend'); const resend = new Resend(apiKey); // Build a valid "from" address for Resend // Priority: SMTP_FROM from DB config > env var > derived from NEXTAUTH_URL > Resend default - const config = await getSystemConfig(); const smtpFrom = config.SMTP_FROM || process.env.SMTP_FROM; let from: string; if (smtpFrom) {