Changes
This commit is contained in:
179
supabase/functions/send-test-email/index.ts
Normal file
179
supabase/functions/send-test-email/index.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
|
||||
|
||||
const corsHeaders = {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
|
||||
};
|
||||
|
||||
interface TestEmailRequest {
|
||||
to: string;
|
||||
smtp_host: string;
|
||||
smtp_port: number;
|
||||
smtp_username: string;
|
||||
smtp_password: string;
|
||||
smtp_from_name: string;
|
||||
smtp_from_email: string;
|
||||
smtp_use_tls: boolean;
|
||||
}
|
||||
|
||||
async function sendEmail(config: TestEmailRequest): Promise<{ success: boolean; message: string }> {
|
||||
const { to, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from_name, smtp_from_email, smtp_use_tls } = config;
|
||||
|
||||
// Build email content
|
||||
const boundary = "----=_Part_" + Math.random().toString(36).substr(2, 9);
|
||||
const emailContent = [
|
||||
`From: "${smtp_from_name}" <${smtp_from_email}>`,
|
||||
`To: ${to}`,
|
||||
`Subject: =?UTF-8?B?${btoa("Email Uji Coba - Konfigurasi SMTP Berhasil")}?=`,
|
||||
`MIME-Version: 1.0`,
|
||||
`Content-Type: multipart/alternative; boundary="${boundary}"`,
|
||||
``,
|
||||
`--${boundary}`,
|
||||
`Content-Type: text/plain; charset=UTF-8`,
|
||||
``,
|
||||
`Ini adalah email uji coba dari sistem notifikasi Anda.`,
|
||||
`Jika Anda menerima email ini, konfigurasi SMTP Anda sudah benar.`,
|
||||
``,
|
||||
`--${boundary}`,
|
||||
`Content-Type: text/html; charset=UTF-8`,
|
||||
``,
|
||||
`<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="UTF-8"></head>
|
||||
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
|
||||
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
|
||||
<h2 style="color: #0066cc;">Email Uji Coba Berhasil! ✓</h2>
|
||||
<p>Ini adalah email uji coba dari sistem notifikasi Anda.</p>
|
||||
<p>Jika Anda menerima email ini, konfigurasi SMTP Anda sudah benar.</p>
|
||||
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
|
||||
<p style="font-size: 12px; color: #666;">
|
||||
Dikirim dari: ${smtp_from_email}<br>
|
||||
Server: ${smtp_host}:${smtp_port}
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>`,
|
||||
`--${boundary}--`,
|
||||
].join("\r\n");
|
||||
|
||||
// Connect to SMTP server
|
||||
const conn = smtp_use_tls
|
||||
? await Deno.connectTls({ hostname: smtp_host, port: smtp_port })
|
||||
: await Deno.connect({ hostname: smtp_host, port: smtp_port });
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
async function readResponse(): Promise<string> {
|
||||
const buffer = new Uint8Array(1024);
|
||||
const n = await conn.read(buffer);
|
||||
if (n === null) return "";
|
||||
return decoder.decode(buffer.subarray(0, n));
|
||||
}
|
||||
|
||||
async function sendCommand(cmd: string): Promise<string> {
|
||||
await conn.write(encoder.encode(cmd + "\r\n"));
|
||||
return await readResponse();
|
||||
}
|
||||
|
||||
try {
|
||||
// Read greeting
|
||||
await readResponse();
|
||||
|
||||
// EHLO
|
||||
let response = await sendCommand(`EHLO localhost`);
|
||||
console.log("EHLO response:", response);
|
||||
|
||||
// For non-TLS connection on port 587, we may need STARTTLS
|
||||
if (!smtp_use_tls && response.includes("STARTTLS")) {
|
||||
await sendCommand("STARTTLS");
|
||||
// Upgrade to TLS - not supported in basic Deno.connect
|
||||
// For now, recommend using TLS directly
|
||||
}
|
||||
|
||||
// AUTH LOGIN
|
||||
response = await sendCommand("AUTH LOGIN");
|
||||
console.log("AUTH response:", response);
|
||||
|
||||
// Username (base64)
|
||||
response = await sendCommand(btoa(smtp_username));
|
||||
console.log("Username response:", response);
|
||||
|
||||
// Password (base64)
|
||||
response = await sendCommand(btoa(smtp_password));
|
||||
console.log("Password response:", response);
|
||||
|
||||
if (!response.includes("235") && !response.includes("Authentication successful")) {
|
||||
throw new Error("Authentication failed: " + response);
|
||||
}
|
||||
|
||||
// MAIL FROM
|
||||
response = await sendCommand(`MAIL FROM:<${smtp_from_email}>`);
|
||||
if (!response.includes("250")) {
|
||||
throw new Error("MAIL FROM failed: " + response);
|
||||
}
|
||||
|
||||
// RCPT TO
|
||||
response = await sendCommand(`RCPT TO:<${to}>`);
|
||||
if (!response.includes("250")) {
|
||||
throw new Error("RCPT TO failed: " + response);
|
||||
}
|
||||
|
||||
// DATA
|
||||
response = await sendCommand("DATA");
|
||||
if (!response.includes("354")) {
|
||||
throw new Error("DATA failed: " + response);
|
||||
}
|
||||
|
||||
// Send email content
|
||||
await conn.write(encoder.encode(emailContent + "\r\n.\r\n"));
|
||||
response = await readResponse();
|
||||
if (!response.includes("250")) {
|
||||
throw new Error("Email send failed: " + response);
|
||||
}
|
||||
|
||||
// QUIT
|
||||
await sendCommand("QUIT");
|
||||
conn.close();
|
||||
|
||||
return { success: true, message: "Email uji coba berhasil dikirim ke " + to };
|
||||
} catch (error) {
|
||||
conn.close();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
serve(async (req: Request): Promise<Response> => {
|
||||
// Handle CORS preflight
|
||||
if (req.method === "OPTIONS") {
|
||||
return new Response(null, { headers: corsHeaders });
|
||||
}
|
||||
|
||||
try {
|
||||
const body: TestEmailRequest = await req.json();
|
||||
|
||||
// Validate required fields
|
||||
if (!body.to || !body.smtp_host || !body.smtp_username || !body.smtp_password) {
|
||||
return new Response(
|
||||
JSON.stringify({ success: false, message: "Missing required fields" }),
|
||||
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
||||
);
|
||||
}
|
||||
|
||||
console.log("Attempting to send test email to:", body.to);
|
||||
console.log("SMTP config:", { host: body.smtp_host, port: body.smtp_port, user: body.smtp_username });
|
||||
|
||||
const result = await sendEmail(body);
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(result),
|
||||
{ status: 200, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
||||
);
|
||||
} catch (error: any) {
|
||||
console.error("Error sending test email:", error);
|
||||
return new Response(
|
||||
JSON.stringify({ success: false, message: error.message || "Failed to send email" }),
|
||||
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
||||
);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user