UNPKG

unemail

Version:

A modern TypeScript email library with zero dependencies, supporting multiple providers including AWS SES, Resend, MailCrab, and HTTP APIs

142 lines (139 loc) 4.08 kB
import smtpProvider from 'unemail/providers/smtp'; import { createError } from 'unemail/utils'; export { defineProvider } from './providers/base.mjs'; const DEFAULT_PROVIDER = smtpProvider; class EmailService { provider; options; initialized = false; /** * Creates a new email service instance * * @param options Configuration options for the email service */ constructor(options = {}) { this.options = { debug: options.debug || false, timeout: options.timeout || 3e4, retries: options.retries || 3, provider: options.provider, config: options.config }; } /** * Get the provider instance */ async getProvider() { if (!this.provider) { try { const providerOption = this.options.provider || DEFAULT_PROVIDER; if (typeof providerOption === "function") { const config = this.options.config?.options || {}; if (providerOption === DEFAULT_PROVIDER && !("host" in config)) { config.host = "localhost"; config.port = 1025; } this.provider = providerOption(config); } else if (providerOption && typeof providerOption === "object" && "initialize" in providerOption) { this.provider = providerOption; } else if (providerOption && typeof providerOption === "object" && "name" in providerOption) { throw new Error(`Provider specification with name property is no longer supported. Please import the provider directly and pass the provider instance or factory.`); } else { throw new Error("Invalid provider configuration. Please provide a valid provider instance or factory function."); } } catch (error) { throw createError( "core", `Failed to initialize provider: ${error.message}`, { cause: error } ); } } return this.provider; } /** * Initializes the email service and underlying provider */ async initialize() { if (this.initialized) { return; } try { const provider = await this.getProvider(); await provider.initialize(); this.initialized = true; } catch (error) { throw createError( "core", `Failed to initialize email service: ${error.message}`, { cause: error } ); } } /** * Checks if the configured provider is available * * @returns Promise resolving to a boolean indicating availability */ async isAvailable() { try { const provider = await this.getProvider(); return await provider.isAvailable(); } catch (error) { if (this.options.debug) { console.error("Error checking provider availability:", error); } return false; } } /** * Sends an email using the configured provider * * @param options Email sending options * @returns Promise resolving to email result */ async sendEmail(options) { try { if (!this.initialized) { await this.initialize(); } const provider = await this.getProvider(); return await provider.sendEmail(options); } catch (error) { return { success: false, error: createError( "core", `Failed to send email: ${error.message}`, { cause: error } ) }; } } /** * Validates credentials for the current provider * * @returns Promise resolving to a boolean indicating if credentials are valid */ async validateCredentials() { try { if (!this.initialized) { await this.initialize(); } const provider = await this.getProvider(); if (provider.validateCredentials) { return await provider.validateCredentials(); } return true; } catch (error) { if (this.options.debug) { console.error("Error validating credentials:", error); } return false; } } } function createEmailService(options = {}) { return new EmailService(options); } export { EmailService, createEmailService };