22 * License, v. 2.0. If a copy of the MPL was not distributed with this
33 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44
5- import { SES } from '@aws-sdk/client-ses' ;
65import { Bounces } from './bounces' ;
76import { StatsD } from 'hot-shots' ;
87import { ILogger } from '@fxa/shared/log' ;
@@ -37,10 +36,14 @@ export type MailerConfig = {
3736 /** DNS timeout for smtp server connection. */
3837 dnsTimeout : number ;
3938
40- /** Optional user name. If not supplied, we fallback to local SES config . */
39+ /** Optional user name for SMTP authentication . */
4140 user ?: string ;
42- /** Optional password. If not supplied, we fallback to local SES config . */
41+ /** Optional password for SMTP authentication . */
4342 password ?: string ;
43+ /** Optional flag to ignore STARTTLS even if the server advertises it. */
44+ ignoreTLS ?: boolean ;
45+ /** Optional flag to require STARTTLS even if the server does not advertise it. */
46+ requireTLS ?: boolean ;
4447 sesConfigurationSet ?: string ;
4548 sender : string ;
4649 retry : {
@@ -81,6 +84,26 @@ export type Email = {
8184 headers : Record < string , string > ;
8285} ;
8386
87+ type SmtpTransportOptions = nodemailer . TransportOptions & {
88+ host : string ;
89+ port : number ;
90+ secure : boolean ;
91+ pool : boolean ;
92+ maxConnections : number ;
93+ maxMessages : number ;
94+ connectionTimeout : number ;
95+ greetingTimeout : number ;
96+ socketTimeout : number ;
97+ dnsTimeout : number ;
98+ sendingRate : number ;
99+ ignoreTLS ?: boolean ;
100+ requireTLS ?: boolean ;
101+ auth ?: {
102+ user : string ;
103+ pass : string ;
104+ } ;
105+ } ;
106+
84107/**
85108 * Sends an email to end end user.
86109 */
@@ -93,36 +116,10 @@ export class EmailSender {
93116 private readonly statsd : StatsD ,
94117 private readonly log : ILogger
95118 ) {
96- // Determine auth credentials
97- const auth = ( ( ) => {
98- // If the user name and password are set use this
99- if ( config . user && config . password ) {
100- return {
101- auth : {
102- user : config . user ,
103- pass : config . password ,
104- } ,
105- } ;
106- }
107-
108- // Otherwise fallback to the SES configuration
109- const ses = new SES ( {
110- // The key apiVersion is no longer supported in v3, and can be removed.
111- // @deprecated The client uses the "latest" apiVersion.
112- apiVersion : '2010-12-01' ,
113- } ) ;
114- return {
115- SES : { ses } ,
116- sendingRate : 5 ,
117- maxConnections : 10 ,
118- } ;
119- } ) ( ) ;
120-
121- // Build node mailer options
122- const options = {
119+ // Build SMTP-only nodemailer options
120+ const options : SmtpTransportOptions = {
123121 host : config . host ,
124122 secure : config . secure ,
125- ignoreTLS : ! config . secure ,
126123 port : config . port ,
127124 pool : config . pool ,
128125 maxConnections : config . maxConnections ,
@@ -131,9 +128,24 @@ export class EmailSender {
131128 greetingTimeout : config . greetingTimeout ,
132129 socketTimeout : config . socketTimeout ,
133130 dnsTimeout : config . dnsTimeout ,
134- sendingRate : this . config . sendingRate ,
135- ...auth ,
131+ sendingRate : config . sendingRate ,
136132 } ;
133+
134+ if ( config . user && config . password ) {
135+ options . auth = {
136+ user : config . user ,
137+ pass : config . password ,
138+ } ;
139+ }
140+
141+ if ( typeof config . ignoreTLS === 'boolean' ) {
142+ options . ignoreTLS = config . ignoreTLS ;
143+ }
144+
145+ if ( typeof config . requireTLS === 'boolean' ) {
146+ options . requireTLS = config . requireTLS ;
147+ }
148+
137149 this . emailClient = nodemailer . createTransport ( options ) ;
138150 }
139151
@@ -261,9 +273,9 @@ export class EmailSender {
261273 attempt = 0
262274 ) : Promise < {
263275 sent : boolean ;
264- message ?: string ;
265276 messageId ?: string ;
266277 response ?: string ;
278+ message ?: string ;
267279 } > {
268280 const { maxAttempts, backOffMs } = this . config . retry ;
269281 const isRetry = attempt > 0 ;
@@ -292,7 +304,7 @@ export class EmailSender {
292304 await this . emailClient . sendMail ( sendMailPayload ) ;
293305
294306 this . log . debug ( 'mailer.send' , {
295- status : info . message ,
307+ status : info . response ,
296308 id : info . messageId ,
297309 to : email . to ,
298310 isRetry,
@@ -307,13 +319,23 @@ export class EmailSender {
307319 retryAttempt : attempt ,
308320 } ) ;
309321
310- // Relay email payload and send status back to calling code.
311- return {
322+ const result : {
323+ sent : boolean ;
324+ messageId ?: string ;
325+ response ?: string ;
326+ message ?: string ;
327+ } = {
312328 sent : true ,
313- message : info ?. message ,
314329 messageId : info ?. messageId ,
315330 response : info ?. response ,
316331 } ;
332+
333+ if ( info ?. message ) {
334+ result . message = info . message ;
335+ }
336+
337+ // Relay email payload and send status back to calling code.
338+ return result ;
317339 } catch ( err ) {
318340 // retry if configured
319341 if ( ! isFinalAttempt && backOffMs > 0 ) {
0 commit comments