mail-bridge
Version:
Send email using any email provider.
435 lines (423 loc) • 13.1 kB
JavaScript
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/providers/aws.ts
import { SendEmailCommand, SESClient } from "@aws-sdk/client-ses";
var sendEmail_AWS_SES = (email, config) => __async(void 0, null, function* () {
const sesClient = new SESClient({ region: config == null ? void 0 : config.region });
let to_address;
if (typeof email.to === "string") {
to_address = [email.to];
} else {
to_address = email.to;
}
const sendEmailCommand = new SendEmailCommand({
Destination: {
ToAddresses: to_address
},
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: email.text
}
},
Subject: {
Charset: "UTF-8",
Data: email.subject
}
},
Source: email.from
});
try {
const data = yield sesClient.send(sendEmailCommand);
return {
provider: "aws_ses",
time: /* @__PURE__ */ new Date(),
id: data.MessageId,
email
};
} catch (error) {
console.log(error);
const msg = {
provider: "AWS_SES",
time: /* @__PURE__ */ new Date(),
error
};
throw new Error(JSON.stringify(msg));
}
});
// src/utils/smtp.ts
import { createTransport } from "nodemailer";
var util_sendEmail_SMTP = (transporter, email) => __async(void 0, null, function* () {
const mailTransporter = createTransport(transporter);
try {
return yield mailTransporter.sendMail(email);
} catch (error) {
console.error(error);
throw new Error("SMTP send failed");
}
});
// src/providers/brevo.ts
var sendEmail_BREVO = (email, config) => __async(void 0, null, function* () {
try {
if (!config)
throw new Error("BREVO is not configured properly.");
const message = yield util_sendEmail_SMTP(config, email);
return {
provider: "brevo",
time: /* @__PURE__ */ new Date(),
id: message.messageId,
email
};
} catch (error) {
console.log(error);
const msg = {
provider: "BREVO",
time: /* @__PURE__ */ new Date(),
error
};
throw new Error(JSON.stringify(msg));
}
});
// src/providers/gmail.ts
var sendEmail_GMAIL = (email, config) => __async(void 0, null, function* () {
try {
if (!config)
throw new Error("GMAIL is not configured properly.");
const message = yield util_sendEmail_SMTP(config, email);
return {
provider: "gmail",
time: /* @__PURE__ */ new Date(),
id: message.messageId,
email
};
} catch (error) {
console.log(error);
const msg = {
provider: "GMAIL",
time: /* @__PURE__ */ new Date(),
error
};
throw new Error(JSON.stringify(msg));
}
});
// src/providers/mailgun.ts
import FormData from "form-data";
import Mailgun from "mailgun.js";
var sendEmail_MAILGUN = (email, config) => __async(void 0, null, function* () {
const mailgun = new Mailgun(FormData);
try {
const mg = mailgun.client({
username: "api",
key: config == null ? void 0 : config.api_key
});
const data = yield mg.messages.create(config == null ? void 0 : config.domain, {
from: email.from,
to: email.to,
subject: email.subject,
html: email.text
});
return {
provider: "mailgun",
time: /* @__PURE__ */ new Date(),
id: data.id,
email
};
} catch (error) {
console.log(error);
const msg = {
provider: "MAILGUN",
time: /* @__PURE__ */ new Date(),
error
};
throw new Error(JSON.stringify(msg));
}
});
// src/providers/outlook.ts
var sendEmail_OUTLOOK = (email, config) => __async(void 0, null, function* () {
try {
if (!config)
throw new Error("OUTLOOK is not configured properly.");
const message = yield util_sendEmail_SMTP(config, email);
return {
provider: "outlook",
time: /* @__PURE__ */ new Date(),
id: message.messageId,
email
};
} catch (error) {
console.log(error);
const msg = {
provider: "OUTLOOK",
time: /* @__PURE__ */ new Date(),
error
};
throw new Error(JSON.stringify(msg));
}
});
// src/providers/resend.ts
import { Resend } from "resend";
var sendEmail_RESEND = (email, config) => __async(void 0, null, function* () {
var _a;
try {
const resend = new Resend(config == null ? void 0 : config.api_key);
const data = yield resend.emails.send({
from: email.from,
to: email.to,
subject: email.subject,
html: email.text
});
return {
provider: "resend",
time: /* @__PURE__ */ new Date(),
id: (_a = data.data) == null ? void 0 : _a.id,
email
};
} catch (error) {
console.log(error);
const msg = {
provider: "RESEND",
time: /* @__PURE__ */ new Date(),
error
};
throw new Error(JSON.stringify(msg));
}
});
// src/providers/smtp.ts
var sendEmail_SMTP = (email, config) => __async(void 0, null, function* () {
try {
if (!config)
throw new Error("SMTP is not configured properly.");
const message = yield util_sendEmail_SMTP(config, email);
return {
provider: "smtp",
time: /* @__PURE__ */ new Date(),
id: message.messageId,
email
};
} catch (error) {
console.log(error);
const msg = {
provider: "SMTP",
time: /* @__PURE__ */ new Date(),
error
};
throw new Error(JSON.stringify(msg));
}
});
// src/sendEmail.ts
var sendEmail = (email, config, provider) => __async(void 0, null, function* () {
switch (provider) {
case "aws_ses":
return yield sendEmail_AWS_SES(email, config.aws_ses);
case "brevo":
return yield sendEmail_BREVO(email, config.brevo);
case "gmail":
return yield sendEmail_GMAIL(email, config.gmail);
case "mailgun":
return yield sendEmail_MAILGUN(email, config.mailgun);
case "outlook":
return yield sendEmail_OUTLOOK(email, config.outlook);
case "resend":
return yield sendEmail_RESEND(email, config.resend);
case "smtp":
return yield sendEmail_SMTP(email, config.smtp);
default:
throw new Error("Invalid provider");
}
});
// src/processEmail.ts
var processEmail = (email, config, provider_priority) => __async(void 0, null, function* () {
const provider = provider_priority.shift();
if (!provider)
throw new Error("No providers provided");
try {
const response = yield sendEmail(email, config, provider);
return response;
} catch (error) {
if (provider_priority.length === 0) {
throw new Error("All providers failed to send email");
}
return yield processEmail(email, config, provider_priority);
}
});
// src/index.ts
var MailBridge = class {
constructor({
config,
defaultFrom,
priority,
retryCount
}) {
this.config = config;
this.defaultFrom = defaultFrom;
if (priority) {
this.provider_priority = priority.filter(
(provider) => Object.keys(config).includes(provider)
);
if (this.provider_priority.length !== Object.keys(config).length) {
const allProviders = Object.keys(config);
const missingProviders = allProviders.filter(
(provider) => !this.provider_priority.includes(provider)
);
this.provider_priority = this.provider_priority.concat(missingProviders);
}
} else {
this.provider_priority = Object.keys(config);
}
this.retryCount = retryCount || this.provider_priority.length;
if (retryCount === 0)
this.retryCount = 0;
console.log("MailBridge initialized");
}
send(email, override) {
return __async(this, null, function* () {
if (!email.from) {
email.from = this.defaultFrom;
}
if ((override == null ? void 0 : override.provider) && this.provider_priority.includes(override.provider)) {
this.provider_priority = this.provider_priority.filter(
(p) => p !== override.provider
);
this.provider_priority.unshift(override.provider);
}
if (override == null ? void 0 : override.retryCount) {
this.provider_priority = this.provider_priority.slice(
0,
override.retryCount + 1
);
} else if ((override == null ? void 0 : override.retryCount) === 0) {
this.provider_priority = this.provider_priority.slice(0, 1);
} else if (this.retryCount === 0) {
this.provider_priority = this.provider_priority.slice(0, 1);
} else {
this.provider_priority = this.provider_priority.slice(
0,
this.retryCount + 1
);
}
return yield processEmail(email, this.config, this.provider_priority);
});
}
/**
* Check the configuration of the MailBridge
*/
checkConfig() {
let report = {
providers: Array(),
errors: Array(),
defaultFrom: void 0,
comment: ""
};
for (let provider of this.provider_priority) {
report.providers.push(provider);
}
if (this.provider_priority.includes("aws_ses") && this.config.aws_ses) {
const { region: REGION } = this.config.aws_ses;
if (!REGION)
report.errors.push("aws_ses.region is required");
}
if (this.provider_priority.includes("brevo") && this.config.brevo) {
const { host, port, auth } = this.config.brevo;
if (!host)
report.errors.push("brevo.host is required.");
if (!port)
report.errors.push("brevo.port is required.");
if (!(auth == null ? void 0 : auth.user))
report.errors.push("brevo.auth.user is required.");
if (!(auth == null ? void 0 : auth.pass))
report.errors.push("brevo.auth.pass is required.");
}
if (this.provider_priority.includes("gmail") && this.config.gmail) {
const { host, port, auth } = this.config.gmail;
if (!host)
report.errors.push("gmail.host is required.");
if (!port)
report.errors.push("gmail.port is required.");
if (!(auth == null ? void 0 : auth.user))
report.errors.push("gmail.auth.user is required.");
if (!(auth == null ? void 0 : auth.pass))
report.errors.push("gmail.auth.pass is required.");
}
if (this.provider_priority.includes("mailgun") && this.config.mailgun) {
const { api_key: MAILGUN_API_KEY, domain: MAILGUN_DOMAIN } = this.config.mailgun;
if (!MAILGUN_API_KEY)
report.errors.push("mailgun.api_key is required.");
if (!MAILGUN_DOMAIN)
report.errors.push("mailgun.domain is required.");
}
if (this.provider_priority.includes("outlook")) {
if (this.config.outlook) {
const { host, port, auth } = this.config.outlook;
if (!host)
report.errors.push("outlook.host is required.");
if (!port)
report.errors.push("outlook.port is required.");
if (!(auth == null ? void 0 : auth.user))
report.errors.push("outlook.auth.user is required.");
if (!(auth == null ? void 0 : auth.pass))
report.errors.push("outlook.auth.pass is required.");
} else {
report.errors.push("outlook is not configured properly.");
}
}
if (this.provider_priority.includes("resend") && this.config.resend) {
const { api_key: API_KEY } = this.config.resend;
if (!API_KEY)
report.errors.push("resend.api_key is required");
}
if (this.provider_priority.includes("smtp")) {
if (this.config.smtp) {
const { host, port, auth } = this.config.smtp;
if (!host)
report.errors.push("smtp.host is required.");
if (!port)
report.errors.push("smtp.port is required.");
if (!(auth == null ? void 0 : auth.user))
report.errors.push("smtp.auth.user is required.");
if (!(auth == null ? void 0 : auth.pass))
report.errors.push("smtp.auth.pass is required.");
} else {
report.errors.push("SMTP is not configured properly.");
}
}
if (!this.defaultFrom) {
report.errors.push("Default from address is not configured");
} else {
if (!this.defaultFrom.includes("@")) {
report.errors.push("Default from address is not a valid email address");
}
report.defaultFrom = this.defaultFrom;
}
if (this.retryCount < 0) {
report.errors.push("Retry count cannot be negative");
}
if (report.errors.length === 0) {
report.comment = "\u2705 Looks good!";
} else {
report.comment = "\u274C Errors found in the configuration";
}
return report;
}
};
export {
MailBridge
};