mail-bridge
Version:
Send email using any email provider.
471 lines (458 loc) • 14.8 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
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/index.ts
var src_exports = {};
__export(src_exports, {
MailBridge: () => MailBridge
});
module.exports = __toCommonJS(src_exports);
// src/providers/aws.ts
var import_client_ses = require("@aws-sdk/client-ses");
var sendEmail_AWS_SES = (email, config) => __async(void 0, null, function* () {
const sesClient = new import_client_ses.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 import_client_ses.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
var import_nodemailer = require("nodemailer");
var util_sendEmail_SMTP = (transporter, email) => __async(void 0, null, function* () {
const mailTransporter = (0, import_nodemailer.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
var import_form_data = __toESM(require("form-data"));
var import_mailgun = __toESM(require("mailgun.js"));
var sendEmail_MAILGUN = (email, config) => __async(void 0, null, function* () {
const mailgun = new import_mailgun.default(import_form_data.default);
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
var import_resend = require("resend");
var sendEmail_RESEND = (email, config) => __async(void 0, null, function* () {
var _a;
try {
const resend = new import_resend.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;
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
MailBridge
});
;