@@ -7,28 +7,49 @@ import { env } from "@/env";
77import { generateUnsubscribeToken } from "@/lib/unsubscribe-tokens" ;
88import { filterSuppressedEmails } from "./email-suppression" ;
99
10- const transport = nodemailer . createTransport ( {
11- host : env . SMTP_HOST ,
12- port : env . SMTP_PORT ,
13- secure : env . SMTP_SECURE ,
14- auth : {
15- user : env . SMTP_USER ,
16- pass : env . SMTP_PASS ,
17- } ,
18- pool : true ,
19- maxConnections : 5 ,
20- maxMessages : 100 ,
21- rateLimit : 10 ,
22- rateDelta : 1000 ,
23- socketTimeout : 45000 ,
24- connectionTimeout : 30000 ,
25- } ) ;
10+ let _transport : nodemailer . Transporter | null = null ;
11+
12+ function getTransport ( ) : nodemailer . Transporter {
13+ if ( _transport ) return _transport ;
14+ _transport = nodemailer . createTransport ( {
15+ host : env . SMTP_HOST ,
16+ port : env . SMTP_PORT ,
17+ secure : env . SMTP_SECURE ,
18+ auth : {
19+ user : env . SMTP_USER ,
20+ pass : env . SMTP_PASS ,
21+ } ,
22+ pool : true ,
23+ maxConnections : 5 ,
24+ maxMessages : 100 ,
25+ rateLimit : 10 ,
26+ rateDelta : 1000 ,
27+ socketTimeout : 45000 ,
28+ connectionTimeout : 30000 ,
29+ } ) ;
30+ return _transport ;
31+ }
2632
2733process . on ( "SIGTERM" , ( ) => {
28- console . log ( "Closing email transport..." ) ;
29- transport . close ( ) ;
34+ if ( _transport ) {
35+ console . log ( "Closing email transport..." ) ;
36+ _transport . close ( ) ;
37+ }
3038} ) ;
3139
40+ export function validateEmailAllowed ( ) : void {
41+ if ( ! env . EMAIL_ENABLED ) {
42+ throw new AppError ( "FORBIDDEN" , "Email functionality is currently disabled" , { reason : "EMAIL_DISABLED" } ) ;
43+ }
44+ }
45+
46+ function applyRedirect ( to : string , subject : string ) : { to : string ; subject : string } {
47+ if ( env . EMAIL_REDIRECT_TO ) {
48+ return { to : env . EMAIL_REDIRECT_TO , subject : `[TEST to: ${ to } ] ${ subject } ` } ;
49+ }
50+ return { to, subject } ;
51+ }
52+
3253interface SendReferralEmailParams {
3354 prospects : Prospect [ ] ;
3455 referralCode : string ;
@@ -44,10 +65,13 @@ export async function sendReferralEmails({
4465
4566 try {
4667 for ( const prospect of prospects ) {
68+ const originalSubject = "You've Been Invited!" ;
69+ const { to, subject } = applyRedirect ( prospect . prospectEmail , originalSubject ) ;
70+
4771 const mail = {
4872 from : env . FROM_EMAIL ,
49- to : prospect . prospectEmail ,
50- subject : "You've Been Invited!" ,
73+ to,
74+ subject,
5175 html : generateEmailHtml ( prospect . prospectName , memberName , referralCode ) ,
5276 attachments : [
5377 {
@@ -58,7 +82,7 @@ export async function sendReferralEmails({
5882 ] ,
5983 } ;
6084
61- await transport . sendMail ( mail ) ;
85+ await getTransport ( ) . sendMail ( mail ) ;
6286 }
6387 } catch ( error ) {
6488 throw new AppError ( "EMAIL_ERROR" , "Failed to send referral emails" , {
@@ -145,11 +169,13 @@ export async function sendGroupEmails(
145169</p>
146170` ;
147171
148- await transport . sendMail ( {
172+ const { to, subject : redirectedSubject } = applyRedirect ( recipient . email , subject ) ;
173+
174+ await getTransport ( ) . sendMail ( {
149175 from : `${ senderName } <${ env . FROM_EMAIL } >` ,
150- to : recipient . email ,
176+ to,
151177 replyTo,
152- subject,
178+ subject : redirectedSubject ,
153179 html : htmlWithFooter ,
154180 headers : {
155181 "List-Unsubscribe-Post" : "List-Unsubscribe=One-Click" ,
0 commit comments