Add Mailgun admin tools and contact API
This commit is contained in:
231
app/api/admin/mailgun/route.ts
Normal file
231
app/api/admin/mailgun/route.ts
Normal file
@@ -0,0 +1,231 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { prisma } from '@/lib/db'
|
||||
import { verifyAdminAuth } from '@/lib/admin-auth'
|
||||
import { mailgunService } from '@/lib/mailgun'
|
||||
|
||||
export const runtime = 'nodejs'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const adminUser = await verifyAdminAuth(request)
|
||||
if (!adminUser) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const settings = await prisma.mailgunSettings.findFirst({
|
||||
orderBy: { updatedAt: 'desc' },
|
||||
select: {
|
||||
id: true,
|
||||
domain: true,
|
||||
region: true,
|
||||
fromEmail: true,
|
||||
fromName: true,
|
||||
replyToEmail: true,
|
||||
isEnabled: true,
|
||||
testMode: true,
|
||||
webhookUrl: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
// Don't return the API key for security
|
||||
apiKey: false
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: settings
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error fetching Mailgun settings:', error)
|
||||
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const adminUser = await verifyAdminAuth(request)
|
||||
if (!adminUser) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const {
|
||||
apiKey,
|
||||
domain,
|
||||
region = 'US',
|
||||
fromEmail,
|
||||
fromName,
|
||||
replyToEmail,
|
||||
isEnabled = false,
|
||||
testMode = true,
|
||||
webhookUrl
|
||||
} = body
|
||||
|
||||
// Validate required fields
|
||||
if (!apiKey || !domain || !fromEmail || !fromName) {
|
||||
return NextResponse.json({
|
||||
error: 'API key, domain, from email, and from name are required'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
// Validate email format
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
if (!emailRegex.test(fromEmail)) {
|
||||
return NextResponse.json({
|
||||
error: 'Invalid from email format'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
if (replyToEmail && !emailRegex.test(replyToEmail)) {
|
||||
return NextResponse.json({
|
||||
error: 'Invalid reply-to email format'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
// Disable existing settings
|
||||
await prisma.mailgunSettings.updateMany({
|
||||
data: { isEnabled: false }
|
||||
})
|
||||
|
||||
// Create new settings
|
||||
const settings = await prisma.mailgunSettings.create({
|
||||
data: {
|
||||
apiKey,
|
||||
domain,
|
||||
region,
|
||||
fromEmail,
|
||||
fromName,
|
||||
replyToEmail,
|
||||
isEnabled,
|
||||
testMode,
|
||||
webhookUrl,
|
||||
updatedBy: adminUser.id
|
||||
}
|
||||
})
|
||||
|
||||
// Clear service cache
|
||||
mailgunService.clearCache()
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: {
|
||||
id: settings.id,
|
||||
domain: settings.domain,
|
||||
region: settings.region,
|
||||
fromEmail: settings.fromEmail,
|
||||
fromName: settings.fromName,
|
||||
replyToEmail: settings.replyToEmail,
|
||||
isEnabled: settings.isEnabled,
|
||||
testMode: settings.testMode,
|
||||
webhookUrl: settings.webhookUrl,
|
||||
createdAt: settings.createdAt,
|
||||
updatedAt: settings.updatedAt
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error creating Mailgun settings:', error)
|
||||
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
const adminUser = await verifyAdminAuth(request)
|
||||
if (!adminUser) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const {
|
||||
id,
|
||||
apiKey,
|
||||
domain,
|
||||
region,
|
||||
fromEmail,
|
||||
fromName,
|
||||
replyToEmail,
|
||||
isEnabled,
|
||||
testMode,
|
||||
webhookUrl
|
||||
} = body
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json({ error: 'Settings ID is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if (!domain || !fromEmail || !fromName) {
|
||||
return NextResponse.json({
|
||||
error: 'Domain, from email, and from name are required'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
// Validate email format
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
if (!emailRegex.test(fromEmail)) {
|
||||
return NextResponse.json({
|
||||
error: 'Invalid from email format'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
if (replyToEmail && !emailRegex.test(replyToEmail)) {
|
||||
return NextResponse.json({
|
||||
error: 'Invalid reply-to email format'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
// If enabling this setting, disable others
|
||||
if (isEnabled) {
|
||||
await prisma.mailgunSettings.updateMany({
|
||||
where: { id: { not: id } },
|
||||
data: { isEnabled: false }
|
||||
})
|
||||
}
|
||||
|
||||
// Build update data
|
||||
const updateData: any = {
|
||||
domain,
|
||||
region,
|
||||
fromEmail,
|
||||
fromName,
|
||||
replyToEmail,
|
||||
isEnabled,
|
||||
testMode,
|
||||
webhookUrl,
|
||||
updatedBy: adminUser.id
|
||||
}
|
||||
|
||||
// Only update API key if provided
|
||||
if (apiKey) {
|
||||
updateData.apiKey = apiKey
|
||||
}
|
||||
|
||||
const settings = await prisma.mailgunSettings.update({
|
||||
where: { id },
|
||||
data: updateData
|
||||
})
|
||||
|
||||
// Clear service cache
|
||||
mailgunService.clearCache()
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: {
|
||||
id: settings.id,
|
||||
domain: settings.domain,
|
||||
region: settings.region,
|
||||
fromEmail: settings.fromEmail,
|
||||
fromName: settings.fromName,
|
||||
replyToEmail: settings.replyToEmail,
|
||||
isEnabled: settings.isEnabled,
|
||||
testMode: settings.testMode,
|
||||
webhookUrl: settings.webhookUrl,
|
||||
createdAt: settings.createdAt,
|
||||
updatedAt: settings.updatedAt
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error updating Mailgun settings:', error)
|
||||
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
100
app/api/admin/mailgun/test/route.ts
Normal file
100
app/api/admin/mailgun/test/route.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { verifyAdminAuth } from '@/lib/admin-auth'
|
||||
import { mailgunService } from '@/lib/mailgun'
|
||||
|
||||
export const runtime = 'nodejs'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const adminUser = await verifyAdminAuth(request)
|
||||
if (!adminUser) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { testType, email } = body
|
||||
|
||||
if (testType === 'connection') {
|
||||
// Test connection to Mailgun
|
||||
const result = await mailgunService.testConnection()
|
||||
return NextResponse.json(result)
|
||||
}
|
||||
|
||||
if (testType === 'email') {
|
||||
// Send test email
|
||||
if (!email) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Email address is required for email test'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
const result = await mailgunService.sendEmail({
|
||||
to: email,
|
||||
subject: 'Biblical Guide - Email Configuration Test',
|
||||
text: `Hello,
|
||||
|
||||
This is a configuration test email from Biblical Guide.
|
||||
|
||||
Your email system has been successfully configured and is working properly. You can now receive important notifications from our platform.
|
||||
|
||||
Best regards,
|
||||
The Biblical Guide Team
|
||||
|
||||
---
|
||||
This is an automated message. Please do not reply to this email.
|
||||
Time: ${new Date().toLocaleString()}`,
|
||||
html: `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Biblical Guide - Email Configuration Test</title>
|
||||
</head>
|
||||
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
|
||||
<div style="background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin-bottom: 20px;">
|
||||
<h2 style="color: #2c3e50; margin: 0;">Biblical Guide</h2>
|
||||
<p style="margin: 5px 0 0 0; color: #6c757d;">Email Configuration Test</p>
|
||||
</div>
|
||||
|
||||
<div style="background-color: white; padding: 20px; border-radius: 8px; border: 1px solid #e9ecef;">
|
||||
<p>Hello,</p>
|
||||
|
||||
<p>This is a configuration test email from Biblical Guide.</p>
|
||||
|
||||
<p><strong>Your email system has been successfully configured and is working properly.</strong> You can now receive important notifications from our platform.</p>
|
||||
|
||||
<div style="background-color: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px; padding: 15px; margin: 20px 0;">
|
||||
<p style="margin: 0; color: #155724;"><strong>✓ Configuration successful</strong></p>
|
||||
</div>
|
||||
|
||||
<p>Best regards,<br>
|
||||
The Biblical Guide Team</p>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px; padding: 15px; background-color: #f8f9fa; border-radius: 8px; font-size: 12px; color: #6c757d;">
|
||||
<p style="margin: 0;">This is an automated message. Please do not reply to this email.</p>
|
||||
<p style="margin: 5px 0 0 0;">Time: ${new Date().toLocaleString()}</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
})
|
||||
|
||||
return NextResponse.json(result)
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Invalid test type'
|
||||
}, { status: 400 })
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error testing Mailgun:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Test failed'
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user