mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: smtp error for SMTP_SECURE false. Added in .env
This commit is contained in:
@@ -26,7 +26,7 @@ import {
|
||||
} from "@/components/wrappers/dashboard/admin/settings/email/email-form/email-form.action";
|
||||
import {toast} from "sonner";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {sendEmail} from "@/lib/email/email-helper";
|
||||
import {sendEmail} from "@/lib/email";
|
||||
import {render} from "@react-email/components";
|
||||
import EmailSettingsTest from "@/components/emails/email-settings-test";
|
||||
import {ButtonWithLoading} from "@/components/wrappers/common/button/button-with-loading";
|
||||
|
||||
@@ -18,7 +18,7 @@ import {userAction} from "@/lib/safe-actions/actions";
|
||||
import {
|
||||
addMemberOrganizationAction
|
||||
} from "@/components/wrappers/dashboard/admin/organizations/organization/details/add-member.action";
|
||||
import {sendEmail} from "@/lib/email/email-helper";
|
||||
import {sendEmail} from "@/lib/email";
|
||||
import EmailCreateUser from "@/components/emails/email-create-user";
|
||||
import {SignUpUser} from "@/types/auth";
|
||||
import {createUserDb} from "@/db/services/user";
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE "settings" ADD COLUMN "smtp_secure" boolean;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -218,6 +218,13 @@
|
||||
"when": 1768763883339,
|
||||
"tag": "0030_dizzy_morlocks",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 31,
|
||||
"version": "7",
|
||||
"when": 1768931603846,
|
||||
"tag": "0031_chemical_edwin_jarvis",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import {pgTable, timestamp, uuid, varchar} from "drizzle-orm/pg-core";
|
||||
import {boolean, pgTable, timestamp, uuid, varchar} from "drizzle-orm/pg-core";
|
||||
import {typeStorageEnum} from "./types";
|
||||
import {createSelectSchema} from "drizzle-zod";
|
||||
import {z} from "zod";
|
||||
@@ -19,6 +19,7 @@ export const setting = pgTable("settings", {
|
||||
smtpHost: varchar("smtp_host", {length: 255}),
|
||||
smtpPort: varchar("smtp_port", {length: 255}),
|
||||
smtpUser: varchar("smtp_user", {length: 255}),
|
||||
smtpSecure: boolean("smtp_secure"),
|
||||
defaultStorageChannelId: uuid('default_storage_channel_id')
|
||||
.references(() => storageChannel.id, {onDelete: "set null"}),
|
||||
...timestamps
|
||||
|
||||
@@ -22,6 +22,7 @@ export const env = createEnv({
|
||||
SMTP_HOST: z.string().optional(),
|
||||
SMTP_PORT: z.string().optional(),
|
||||
SMTP_USER: z.string().optional(),
|
||||
SMTP_SECURE: z.coerce.boolean().default(true),
|
||||
|
||||
AUTH_GOOGLE_ID: z.string().optional(),
|
||||
AUTH_GOOGLE_SECRET: z.string().optional(),
|
||||
@@ -60,6 +61,7 @@ export const env = createEnv({
|
||||
SMTP_HOST: process.env.SMTP_HOST,
|
||||
SMTP_PORT: process.env.SMTP_PORT,
|
||||
SMTP_USER: process.env.SMTP_USER,
|
||||
SMTP_SECURE: process.env.SMTP_SECURE,
|
||||
|
||||
AUTH_GOOGLE_ID: process.env.AUTH_GOOGLE_ID,
|
||||
AUTH_GOOGLE_SECRET: process.env.AUTH_GOOGLE_SECRET,
|
||||
|
||||
@@ -9,7 +9,7 @@ import {ac, admin, orgAdmin, orgMember, orgOwner, pending, superadmin, user} fro
|
||||
import {headers} from "next/headers";
|
||||
import {count, eq} from "drizzle-orm";
|
||||
import {MemberWithUser, OrganizationWithMembersAndUsers} from "@/db/schema/03_organization";
|
||||
import {sendEmail} from "@/lib/email/email-helper";
|
||||
import {sendEmail} from "@/lib/email";
|
||||
import {render} from "@react-email/render";
|
||||
import {AuthProviderConfig, SUPPORTED_PROVIDERS} from "../../../portabase.config";
|
||||
import {withUpdatedAt} from "@/db/utils";
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import {db} from "@/db";
|
||||
import {eq} from "drizzle-orm";
|
||||
import nodemailer from "nodemailer";
|
||||
import * as drizzleDb from "@/db";
|
||||
|
||||
type Payload = {
|
||||
to: string;
|
||||
from?: string;
|
||||
subject: string;
|
||||
html: any;
|
||||
};
|
||||
|
||||
type Server = {
|
||||
host: string;
|
||||
port: number;
|
||||
user: string;
|
||||
pass: string;
|
||||
from: string;
|
||||
};
|
||||
|
||||
type EmailCustomProps = {
|
||||
data: Payload;
|
||||
server: Server;
|
||||
};
|
||||
|
||||
type EmailMassProps = {
|
||||
data: Payload;
|
||||
servers: Server[];
|
||||
};
|
||||
|
||||
export const sendEmail = async (data: Payload) => {
|
||||
const settings = await db
|
||||
.select()
|
||||
.from(drizzleDb.schemas.setting)
|
||||
.where(eq(drizzleDb.schemas.setting.name, "system"))
|
||||
.then((res) => res[0]);
|
||||
|
||||
if (!settings) {
|
||||
throw new Error("SMTP system settings not found.");
|
||||
}
|
||||
|
||||
if (!settings.smtpHost || !settings.smtpPort || !settings.smtpUser || !settings.smtpPassword || !settings.smtpFrom) {
|
||||
console.warn("Incomplete SMTP settings. Email not sent.");
|
||||
return;
|
||||
}
|
||||
|
||||
const emailsArray = data.to.split(",")
|
||||
.map(email => email.trim());
|
||||
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
pool: true,
|
||||
host: settings.smtpHost ?? "",
|
||||
port: parseInt(settings.smtpPort ?? "587"),
|
||||
secure: true,
|
||||
auth: {
|
||||
user: settings.smtpUser ?? "",
|
||||
pass: settings.smtpPassword ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
return await transporter.sendMail({
|
||||
...data,
|
||||
to: emailsArray,
|
||||
from: settings.smtpFrom ?? undefined,
|
||||
});
|
||||
};
|
||||
|
||||
export const sendCustomEmail = async (data: EmailCustomProps) => {
|
||||
const transporter = nodemailer.createTransport({
|
||||
secure: true,
|
||||
replyTo: data.server.user,
|
||||
host: data.server.host,
|
||||
port: data.server.port,
|
||||
auth: {
|
||||
user: data.server.user,
|
||||
pass: data.server.pass,
|
||||
},
|
||||
});
|
||||
|
||||
return await transporter.sendMail({
|
||||
...data.data,
|
||||
});
|
||||
};
|
||||
|
||||
export const sendMassEmail = async (data: EmailMassProps) => {
|
||||
for (const server of data.servers) {
|
||||
const transporter = nodemailer.createTransport({
|
||||
secure: true,
|
||||
host: server.host,
|
||||
port: server.port,
|
||||
auth: {
|
||||
user: server.user,
|
||||
pass: server.pass,
|
||||
},
|
||||
});
|
||||
|
||||
return await transporter.sendMail({
|
||||
...data.data,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import nodemailer from "nodemailer";
|
||||
|
||||
export const createTransporter = (server: Server) => {
|
||||
const portNumber = Number(server.port);
|
||||
return nodemailer.createTransport({
|
||||
pool: true,
|
||||
host: server.host,
|
||||
port: portNumber,
|
||||
secure: server.secure ?? portNumber === 465,
|
||||
auth: {
|
||||
user: server.user,
|
||||
pass: server.pass,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
"use server"
|
||||
import {db} from "@/db";
|
||||
import {eq} from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {createTransporter} from "@/lib/email/helpers";
|
||||
|
||||
export const sendEmail = async (data: Payload) => {
|
||||
const settings = await db
|
||||
.select()
|
||||
.from(drizzleDb.schemas.setting)
|
||||
.where(eq(drizzleDb.schemas.setting.name, "system"))
|
||||
.then((res) => res[0]);
|
||||
|
||||
if (!settings) {
|
||||
throw new Error("SMTP system settings not found.");
|
||||
}
|
||||
|
||||
if (!settings.smtpHost || !settings.smtpPort || !settings.smtpUser || !settings.smtpPassword || !settings.smtpFrom) {
|
||||
console.warn("Incomplete SMTP settings. Email not sent.");
|
||||
return;
|
||||
}
|
||||
|
||||
const emailsArray = data.to.split(",")
|
||||
.map(email => email.trim());
|
||||
|
||||
const transporter = createTransporter({
|
||||
host: settings.smtpHost,
|
||||
port: Number(settings.smtpPort),
|
||||
user: settings.smtpUser,
|
||||
pass: settings.smtpPassword,
|
||||
from: settings.smtpFrom,
|
||||
secure: settings.smtpSecure ?? false,
|
||||
});
|
||||
await transporter.verify();
|
||||
|
||||
return await transporter.sendMail({
|
||||
...data,
|
||||
to: emailsArray,
|
||||
from: settings.smtpFrom ?? undefined,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
"use server";
|
||||
|
||||
|
||||
type Payload = {
|
||||
to: string;
|
||||
from?: string;
|
||||
subject: string;
|
||||
html: any;
|
||||
};
|
||||
|
||||
type Server = {
|
||||
host: string;
|
||||
port: number;
|
||||
user: string;
|
||||
pass: string;
|
||||
from: string;
|
||||
secure: boolean;
|
||||
};
|
||||
|
||||
+2
-3
@@ -4,8 +4,6 @@ import {eq} from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {retentionJob} from "@/lib/tasks";
|
||||
import {generateRSAKeys} from "@/utils/rsa-keys";
|
||||
import {Provider} from "react";
|
||||
import type {ProviderKind} from "@/features/notifications/types";
|
||||
import {StorageProviderKind} from "@/features/storages/types";
|
||||
|
||||
|
||||
@@ -34,6 +32,7 @@ async function createSettingsIfNotExist() {
|
||||
smtpHost: env.SMTP_HOST ?? null,
|
||||
smtpPort: env.SMTP_PORT ?? null,
|
||||
smtpUser: env.SMTP_USER ?? null,
|
||||
smtpSecure: env.SMTP_SECURE,
|
||||
};
|
||||
|
||||
const [existing] = await db.select().from(drizzleDb.schemas.setting).where(eq(drizzleDb.schemas.setting.name, "system")).limit(1);
|
||||
@@ -59,7 +58,7 @@ async function createSettingsIfNotExist() {
|
||||
console.log("====Local Storage : Create ====");
|
||||
const [localChannelCreated] = await db.insert(drizzleDb.schemas.storageChannel).values(localChannelValues).returning();
|
||||
|
||||
if (localChannelCreated){
|
||||
if (localChannelCreated) {
|
||||
await db.update(drizzleDb.schemas.setting).set({
|
||||
defaultStorageChannelId: localChannelCreated.id,
|
||||
}).where(eq(drizzleDb.schemas.setting.name, "system"));
|
||||
|
||||
Reference in New Issue
Block a user