Tech4biz-channel/Channel-Backend/src/services/mail.service.ts
2026-07-23 20:18:28 +05:30

107 lines
5.7 KiB
TypeScript

import nodemailer from 'nodemailer';
import { originStorage } from '../utils/origin-storage';
export class MailService {
private transporter: nodemailer.Transporter;
constructor() {
const host = process.env.SMTP_HOST || 'smtp.mailtrap.io';
const port = parseInt(process.env.SMTP_PORT || '2525', 10);
const user = process.env.SMTP_USER || '';
const pass = process.env.SMTP_PASS || '';
this.transporter = nodemailer.createTransport({
host,
port,
secure: port === 465,
auth: user && pass ? { user, pass } : undefined,
tls: {
rejectUnauthorized: false,
},
});
}
public async sendInviteEmail(email: string, inviteToken: string) {
const origin = originStorage.getStore() || process.env.CLIENT_ORIGIN || 'http://localhost:5173';
const inviteUrl = `${origin}/invite?token=${inviteToken}`;
const isRealEmailAllowed = process.env.ENABLE_REAL_EMAILS === 'true' && process.env.NODE_ENV === 'production';
if (!isRealEmailAllowed) {
console.log(`[DEV EMAIL SAFEGUARD] Blocked real email dispatch to real user/client: ${email}`);
console.log(`[DEV EMAIL SAFEGUARD] Mock Invite URL: ${inviteUrl}`);
return { messageId: 'mock-dev-safeguard-id' };
}
const mailOptions = {
from: process.env.SMTP_FROM || (process.env.SMTP_USER ? `"Tech4Biz Portal" <${process.env.SMTP_USER}>` : '"Tech4Biz Portal" <noreply@tech4biz.com>'),
to: email,
subject: 'Tech4Biz Partner Portal Invitation',
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 30px; border: 1px solid #e2e8f0; border-radius: 12px; background-color: #ffffff;">
<div style="text-align: left; margin-bottom: 24px;">
<h2 style="color: #1e293b; margin: 0; font-size: 20px; font-weight: bold;">Tech4Biz Partner Portal</h2>
<p style="color: #64748b; font-size: 13px; margin: 4px 0 0 0;">Authorized Collaborative Access Gateway</p>
</div>
<div style="border-top: 1px solid #e2e8f0; padding-top: 24px; margin-top: 16px;">
<p style="font-size: 14px; color: #334155; line-height: 1.6; margin: 0 0 16px 0;">Hello,</p>
<p style="font-size: 14px; color: #334155; line-height: 1.6; margin: 0 0 16px 0;">You have been invited to register for the <strong>Tech4Biz Partner Portal</strong> as a collaborative member. This portal allows your organization to view shared resources, asset files, and manage onboarding documentation.</p>
<p style="font-size: 14px; color: #334155; line-height: 1.6; margin: 0 0 24px 0;">To set up your account and access the platform, please proceed to the link below to configure your credentials and review the partner documentation:</p>
<div style="text-align: left; margin: 24px 0;">
<a href="${inviteUrl}" style="background-color: #0f172a; color: #ffffff; padding: 12px 24px; font-size: 14px; font-weight: bold; text-decoration: none; border-radius: 6px; display: inline-block;">Access Partner Portal</a>
</div>
<p style="font-size: 12px; color: #64748b; line-height: 1.6; margin: 24px 0 8px 0;">If you are unable to click the button above, please copy and paste the URL below into your web browser:</p>
<p style="font-size: 12px; color: #334155; font-family: monospace; background-color: #f8fafc; border: 1px solid #e2e8f0; padding: 12px; border-radius: 6px; word-break: break-all; margin: 0 0 24px 0;">${inviteUrl}</p>
</div>
<div style="border-top: 1px solid #e2e8f0; padding-top: 20px; margin-top: 30px; text-align: center;">
<p style="font-size: 11px; color: #94a3b8; margin: 0;">© 2026 Tech4Biz Solutions Inc. All rights reserved.</p>
</div>
</div>
`
};
try {
const info = await this.transporter.sendMail(mailOptions);
console.log(`[SMTP] Invitation email successfully sent to ${email}. Message ID: ${info.messageId}`);
return info;
} catch (err) {
console.error(`[SMTP ERROR] Failed to send invitation email to ${email}:`, err);
throw err;
}
}
public async sendCustomAnnouncement(options: { recipients: string[]; subject: string; messageBody: string }) {
if (!options.recipients || options.recipients.length === 0) return;
const isRealEmailAllowed = process.env.ENABLE_REAL_EMAILS === 'true' && process.env.NODE_ENV === 'production';
if (!isRealEmailAllowed) {
console.log(`[DEV EMAIL SAFEGUARD] Blocked announcement email to ${options.recipients.length} recipients (Development mode safety guard). Subject: "${options.subject}"`);
return;
}
const mailOptions = {
from: process.env.SMTP_FROM || '"Tech4Biz Portal" <noreply@tech4biz.com>',
to: options.recipients.join(', '),
subject: options.subject,
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 24px; border: 1px solid #e2e8f0; border-radius: 8px; background-color: #ffffff;">
<h2 style="color: #0f172a; margin-top: 0;">${options.subject}</h2>
<div style="font-size: 14px; color: #334155; line-height: 1.6; white-space: pre-wrap; background: #f8fafc; padding: 16px; border-radius: 6px; border: 1px solid #e2e8f0;">${options.messageBody}</div>
<p style="font-size: 12px; color: #64748b; margin-top: 24px;">Sent via Tech4Biz Channel Partner Platform</p>
</div>
`
};
try {
await this.transporter.sendMail(mailOptions);
console.log(`[SMTP] Announcement email sent to ${options.recipients.length} recipients.`);
} catch (err) {
console.error('[SMTP ERROR] Failed to send announcement email:', err);
}
}
}