initial commit. gotta go

This commit is contained in:
2025-09-26 14:30:57 -05:00
parent b342335502
commit eb0b35bb7f
299 changed files with 6902 additions and 6741 deletions

View File

@@ -1,16 +1,16 @@
import { SMTPServer, SMTPServerOptions, SMTPServerSession } from "smtp-server";
import { Readable } from "stream";
import dotenv from "dotenv";
import { simpleParser } from "mailparser";
import { readFileSync, watch, FSWatcher } from "fs";
import { SMTPServer, SMTPServerOptions, SMTPServerSession } from 'smtp-server';
import { Readable } from 'stream';
import dotenv from 'dotenv';
import { simpleParser } from 'mailparser';
import { readFileSync, watch, FSWatcher } from 'fs';
dotenv.config();
const AUTH_USERNAME = process.env.SMTP_AUTH_USERNAME ?? "usesend";
const AUTH_USERNAME = process.env.SMTP_AUTH_USERNAME ?? 'usesend';
const BASE_URL =
process.env.USESEND_BASE_URL ??
process.env.UNSEND_BASE_URL ??
"https://app.usesend.com";
'https://app.usesend.com';
const SSL_KEY_PATH =
process.env.USESEND_API_KEY_PATH ?? process.env.UNSEND_API_KEY_PATH;
const SSL_CERT_PATH =
@@ -18,17 +18,17 @@ const SSL_CERT_PATH =
async function sendEmailToUseSend(emailData: any, apiKey: string) {
try {
const apiEndpoint = "/api/v1/emails";
const apiEndpoint = '/api/v1/emails';
const url = new URL(apiEndpoint, BASE_URL); // Combine base URL with endpoint
console.log("Sending email to useSend API at:", url.href); // Debug statement
console.log('Sending email to useSend API at:', url.href); // Debug statement
const emailDataText = JSON.stringify(emailData);
const response = await fetch(url.href, {
method: "POST",
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
'Content-Type': 'application/json',
},
body: emailDataText,
});
@@ -36,24 +36,24 @@ async function sendEmailToUseSend(emailData: any, apiKey: string) {
if (!response.ok) {
const errorData = await response.text();
console.error(
"useSend API error response: error:",
'useSend API error response: error:',
JSON.stringify(errorData, null, 4),
`\nemail data: ${emailDataText}`,
);
throw new Error(
`Failed to send email: ${errorData || "Unknown error from server"}`,
`Failed to send email: ${errorData || 'Unknown error from server'}`,
);
}
const responseData = await response.json();
console.log("useSend API response:", responseData);
console.log('useSend API response:', responseData);
} catch (error) {
if (error instanceof Error) {
console.error("Error message:", error.message);
console.error('Error message:', error.message);
throw new Error(`Failed to send email: ${error.message}`);
} else {
console.error("Unexpected error:", error);
throw new Error("Failed to send email: Unexpected error occurred");
console.error('Unexpected error:', error);
throw new Error('Failed to send email: Unexpected error occurred');
}
}
}
@@ -76,24 +76,24 @@ const serverOptions: SMTPServerOptions = {
session: SMTPServerSession,
callback: (error?: Error) => void,
) {
console.log("Receiving email data..."); // Debug statement
console.log('Receiving email data...'); // Debug statement
simpleParser(stream, (err, parsed) => {
if (err) {
console.error("Failed to parse email data:", err.message);
console.error('Failed to parse email data:', err.message);
return callback(err);
}
if (!session.user) {
console.error("No API key found in session");
return callback(new Error("No API key found in session"));
console.error('No API key found in session');
return callback(new Error('No API key found in session'));
}
const emailObject = {
to: Array.isArray(parsed.to)
? parsed.to.map((addr) => addr.text).join(", ")
? parsed.to.map((addr) => addr.text).join(', ')
: parsed.to?.text,
from: Array.isArray(parsed.from)
? parsed.from.map((addr) => addr.text).join(", ")
? parsed.from.map((addr) => addr.text).join(', ')
: parsed.from?.text,
subject: parsed.subject,
text: parsed.text,
@@ -103,20 +103,20 @@ const serverOptions: SMTPServerOptions = {
sendEmailToUseSend(emailObject, session.user)
.then(() => callback())
.then(() => console.log("Email sent successfully to: ", emailObject.to))
.then(() => console.log('Email sent successfully to: ', emailObject.to))
.catch((error) => {
console.error("Failed to send email:", error.message);
console.error('Failed to send email:', error.message);
callback(error);
});
});
},
onAuth(auth, session: any, callback: (error?: Error, user?: any) => void) {
if (auth.username === AUTH_USERNAME && auth.password) {
console.log("Authenticated successfully"); // Debug statement
console.log('Authenticated successfully'); // Debug statement
callback(undefined, { user: auth.password });
} else {
console.error("Invalid username or password");
callback(new Error("Invalid username or password"));
console.error('Invalid username or password');
callback(new Error('Invalid username or password'));
}
},
size: 10485760,
@@ -137,7 +137,7 @@ function startServers() {
);
});
server.on("error", (err) => {
server.on('error', (err) => {
console.error(`Error occurred on port ${port}:`, err);
});
@@ -153,7 +153,7 @@ function startServers() {
console.log(`STARTTLS SMTP server is listening on port ${port}`);
});
server.on("error", (err) => {
server.on('error', (err) => {
console.error(`Error occurred on port ${port}:`, err);
});
@@ -166,10 +166,10 @@ function startServers() {
const { key, cert } = loadCertificates();
if (key && cert) {
servers.forEach((srv) => srv.updateSecureContext({ key, cert }));
console.log("TLS certificates reloaded");
console.log('TLS certificates reloaded');
}
} catch (err) {
console.error("Failed to reload TLS certificates", err);
console.error('Failed to reload TLS certificates', err);
}
};
@@ -183,12 +183,12 @@ function startServers() {
const { servers, watchers } = startServers();
function shutdown() {
console.log("Shutting down SMTP server...");
console.log('Shutting down SMTP server...');
watchers.forEach((w) => w.close());
servers.forEach((s) => s.close());
process.exit(0);
}
["SIGINT", "SIGTERM", "SIGQUIT"].forEach((signal) => {
['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => {
process.on(signal, shutdown);
});

View File

@@ -1,10 +1,10 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { defineConfig, Options } from "tsup";
import { defineConfig, Options } from 'tsup';
// eslint-disable-next-line import/no-default-export
export default defineConfig((options: Options) => ({
entry: ["src/server.ts"],
format: ["cjs"],
entry: ['src/server.ts'],
format: ['cjs'],
dts: true,
minify: true,
clean: true,