@geekmidas/emailkit
v0.0.7
Published
Type-safe email client with SMTP support and React templates
Downloads
301
Readme
@geekmidas/emailkit
Type-safe email client with SMTP support and React templates.
Features
- Type-Safe Templates: Templates are provided at construction time with full TypeScript inference for both template names and their corresponding props
- SMTP Support: Works with any SMTP server via nodemailer configuration
- React Templates: Uses
react-dom/serverto render React components to HTML
Installation
pnpm add @geekmidas/emailkitQuick Start
import { createEmailClient } from '@geekmidas/emailkit';
// Define your templates with props
const WelcomeEmail = ({ name, confirmationUrl }: {
name: string;
confirmationUrl?: string;
}) => (
<div style={{ fontFamily: 'Arial, sans-serif', maxWidth: '600px' }}>
<h1>Welcome, {name}!</h1>
<p>We're excited to have you on board.</p>
{confirmationUrl && (
<p>
<a href={confirmationUrl} style={{
backgroundColor: '#007bff',
color: 'white',
padding: '10px 20px',
textDecoration: 'none',
borderRadius: '4px'
}}>
Confirm Email
</a>
</p>
)}
</div>
);
const templates = {
welcome: WelcomeEmail,
};
// Create client with templates - types are fully inferred
const client = createEmailClient({
smtp: {
host: 'smtp.example.com',
port: 587,
auth: {
user: '[email protected]',
pass: 'password',
},
},
templates,
defaults: {
from: '[email protected]',
},
});
// Send email with full type safety
await client.sendTemplate('welcome', {
from: '[email protected]',
to: '[email protected]',
subject: 'Welcome to our service!',
props: {
name: 'John Doe',
confirmationUrl: 'https://example.com/confirm/123',
},
});API Reference
createEmailClient<T>(config: EmailClientConfig<T>): SMTPClient<T>
Creates a new email client with type-safe template support.
Configuration
interface EmailClientConfig<T extends TemplateRecord> {
smtp: SMTPConfig;
templates: T;
defaults?: {
from?: string | Address;
replyTo?: string | Address;
};
}
interface SMTPConfig {
host: string;
port: number;
secure?: boolean;
auth?: {
user: string;
pass: string;
};
tls?: {
rejectUnauthorized?: boolean;
servername?: string;
};
pool?: boolean;
maxConnections?: number;
maxMessages?: number;
rateLimit?: number;
logger?: boolean;
debug?: boolean;
}Client Methods
send(options: PlainEmailOptions): Promise<SendResult>
Send a plain text or HTML email.
await client.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Plain email',
text: 'This is a plain text email',
html: '<p>This is an HTML email</p>',
});sendTemplate<K>(template: K, options): Promise<SendResult>
Send an email using a React template with type-safe props.
await client.sendTemplate('welcome', {
from: '[email protected]',
to: '[email protected]',
subject: 'Welcome!',
props: { name: 'John', confirmationUrl: 'https://...' },
});verify(): Promise<boolean>
Verify the SMTP connection.
close(): Promise<void>
Close the SMTP connection.
getTemplateNames(): string[]
Get available template names.
Built-in Template Examples
Welcome Email
interface WelcomeEmailProps {
name: string;
confirmationUrl?: string;
}
const WelcomeEmail = ({ name, confirmationUrl }: WelcomeEmailProps) => (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Welcome!</title>
</head>
<body style={{ margin: 0, padding: 0, backgroundColor: '#f4f4f4' }}>
<div style={{
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
lineHeight: 1.6,
color: '#333',
maxWidth: '600px',
margin: '0 auto',
padding: '20px',
}}>
<h1 style={{ color: '#2c3e50', marginBottom: '20px' }}>
Welcome, {name}!
</h1>
<p>
We're excited to have you on board. Your account has been successfully created.
</p>
{confirmationUrl && (
<>
<p>Please confirm your email address by clicking the button below:</p>
<p style={{ textAlign: 'center', margin: '30px 0' }}>
<a href={confirmationUrl} style={{
display: 'inline-block',
padding: '12px 24px',
backgroundColor: '#3498db',
color: '#ffffff',
textDecoration: 'none',
borderRadius: '4px',
fontWeight: 'bold',
}}>
Confirm Email
</a>
</p>
</>
)}
<div style={{
marginTop: '40px',
paddingTop: '20px',
borderTop: '1px solid #eee',
fontSize: '14px',
color: '#666',
}}>
<p>If you have any questions, feel free to reply to this email.</p>
<p>Best regards,<br />The Team</p>
</div>
</div>
</body>
</html>
);Password Reset Email
interface PasswordResetEmailProps {
name: string;
resetUrl: string;
expiresIn: string;
}
const PasswordResetEmail = ({ name, resetUrl, expiresIn }: PasswordResetEmailProps) => (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Password Reset Request</title>
</head>
<body style={{ margin: 0, padding: 0, backgroundColor: '#f4f4f4' }}>
<div style={{
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
lineHeight: 1.6,
color: '#333',
maxWidth: '600px',
margin: '0 auto',
padding: '20px',
}}>
<h1 style={{ color: '#2c3e50', marginBottom: '20px' }}>
Password Reset Request
</h1>
<p>Hi {name},</p>
<p>
We received a request to reset your password. Click the button below to create a new password:
</p>
<p style={{ textAlign: 'center', margin: '30px 0' }}>
<a href={resetUrl} style={{
display: 'inline-block',
padding: '12px 24px',
backgroundColor: '#3498db',
color: '#ffffff',
textDecoration: 'none',
borderRadius: '4px',
fontWeight: 'bold',
}}>
Reset Password
</a>
</p>
<p>
This link will expire in {expiresIn}. If you didn't request a password reset,
you can safely ignore this email.
</p>
<div style={{
marginTop: '40px',
paddingTop: '20px',
borderTop: '1px solid #eee',
fontSize: '14px',
color: '#666',
}}>
<p>For security reasons, this link can only be used once.</p>
</div>
</div>
</body>
</html>
);Notification Email
interface NotificationEmailProps {
name: string;
title: string;
message: string;
actionUrl?: string;
actionText?: string;
}
const NotificationEmail = ({
name,
title,
message,
actionUrl,
actionText = 'View Details'
}: NotificationEmailProps) => (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
</head>
<body style={{ margin: 0, padding: 0, backgroundColor: '#f4f4f4' }}>
<div style={{
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
lineHeight: 1.6,
color: '#333',
maxWidth: '600px',
margin: '0 auto',
padding: '20px',
}}>
<h1 style={{ color: '#2c3e50', marginBottom: '20px' }}>
{title}
</h1>
<p>Hi {name},</p>
<p>{message}</p>
{actionUrl && (
<p style={{ textAlign: 'center', margin: '30px 0' }}>
<a href={actionUrl} style={{
display: 'inline-block',
padding: '12px 24px',
backgroundColor: '#3498db',
color: '#ffffff',
textDecoration: 'none',
borderRadius: '4px',
fontWeight: 'bold',
}}>
{actionText}
</a>
</p>
)}
<div style={{
marginTop: '40px',
paddingTop: '20px',
borderTop: '1px solid #eee',
fontSize: '14px',
color: '#666',
}}>
<p>This is an automated notification from our system.</p>
</div>
</div>
</body>
</html>
);Multiple Templates Example
import { createEmailClient } from '@geekmidas/emailkit';
const templates = {
welcome: WelcomeEmail,
passwordReset: PasswordResetEmail,
notification: NotificationEmail,
};
const client = createEmailClient({
smtp: {
host: 'smtp.example.com',
port: 587,
auth: {
user: '[email protected]',
pass: 'password',
},
},
templates,
defaults: {
from: '[email protected]',
},
});
// All template names and props are fully type-safe
await client.sendTemplate('welcome', {
from: '[email protected]',
to: '[email protected]',
subject: 'Welcome to our service!',
props: { name: 'John Doe', confirmationUrl: 'https://example.com/confirm/123' },
});
await client.sendTemplate('passwordReset', {
from: '[email protected]',
to: '[email protected]',
subject: 'Reset your password',
props: { name: 'John Doe', resetUrl: 'https://example.com/reset/456', expiresIn: '24 hours' },
});
await client.sendTemplate('notification', {
from: '[email protected]',
to: '[email protected]',
subject: 'Important notification',
props: {
name: 'John Doe',
title: 'Account Update',
message: 'Your account settings have been updated.',
actionUrl: 'https://example.com/settings',
actionText: 'View Settings'
},
});TypeScript Support
The library provides full TypeScript support with:
- Template name inference - Only valid template names are accepted
- Props type checking - Props are validated based on the template's prop types
- Autocomplete support - IDE autocomplete for template names and props
- Compile-time safety - Catch template and prop errors at build time
License
MIT
