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} ;
@@ -71,6 +74,26 @@ export type Email = {
7174 headers : Record < string , string > ;
7275} ;
7376
77+ type SmtpTransportOptions = nodemailer . TransportOptions & {
78+ host : string ;
79+ port : number ;
80+ secure : boolean ;
81+ pool : boolean ;
82+ maxConnections : number ;
83+ maxMessages : number ;
84+ connectionTimeout : number ;
85+ greetingTimeout : number ;
86+ socketTimeout : number ;
87+ dnsTimeout : number ;
88+ sendingRate : number ;
89+ ignoreTLS ?: boolean ;
90+ requireTLS ?: boolean ;
91+ auth ?: {
92+ user : string ;
93+ pass : string ;
94+ } ;
95+ } ;
96+
7497/**
7598 * Sends an email to end end user.
7699 */
@@ -83,36 +106,10 @@ export class EmailSender {
83106 private readonly statsd : StatsD ,
84107 private readonly log : ILogger
85108 ) {
86- // Determine auth credentials
87- const auth = ( ( ) => {
88- // If the user name and password are set use this
89- if ( config . user && config . password ) {
90- return {
91- auth : {
92- user : config . user ,
93- pass : config . password ,
94- } ,
95- } ;
96- }
97-
98- // Otherwise fallback to the SES configuration
99- const ses = new SES ( {
100- // The key apiVersion is no longer supported in v3, and can be removed.
101- // @deprecated The client uses the "latest" apiVersion.
102- apiVersion : '2010-12-01' ,
103- } ) ;
104- return {
105- SES : { ses } ,
106- sendingRate : 5 ,
107- maxConnections : 10 ,
108- } ;
109- } ) ( ) ;
110-
111- // Build node mailer options
112- const options = {
109+ // Build SMTP-only nodemailer options
110+ const options : SmtpTransportOptions = {
113111 host : config . host ,
114112 secure : config . secure ,
115- ignoreTLS : ! config . secure ,
116113 port : config . port ,
117114 pool : config . pool ,
118115 maxConnections : config . maxConnections ,
@@ -121,9 +118,24 @@ export class EmailSender {
121118 greetingTimeout : config . greetingTimeout ,
122119 socketTimeout : config . socketTimeout ,
123120 dnsTimeout : config . dnsTimeout ,
124- sendingRate : this . config . sendingRate ,
125- ...auth ,
121+ sendingRate : config . sendingRate ,
126122 } ;
123+
124+ if ( config . user && config . password ) {
125+ options . auth = {
126+ user : config . user ,
127+ pass : config . password ,
128+ } ;
129+ }
130+
131+ if ( typeof config . ignoreTLS === 'boolean' ) {
132+ options . ignoreTLS = config . ignoreTLS ;
133+ }
134+
135+ if ( typeof config . requireTLS === 'boolean' ) {
136+ options . requireTLS = config . requireTLS ;
137+ }
138+
127139 this . emailClient = nodemailer . createTransport ( options ) ;
128140 }
129141
@@ -234,9 +246,9 @@ export class EmailSender {
234246
235247 private async sendMail ( email : Email ) : Promise < {
236248 sent : boolean ;
237- message ?: string ;
238249 messageId ?: string ;
239250 response ?: string ;
251+ message ?: string ;
240252 } > {
241253 try {
242254 // Make sure X-Mailer: '' is set in headers. This used to be done by setting
@@ -257,7 +269,7 @@ export class EmailSender {
257269 // xMailer: false,
258270 } ) ;
259271 this . log . debug ( 'mailer.send' , {
260- status : info . message ,
272+ status : info . response ,
261273 id : info . messageId ,
262274 to : email . to ,
263275 } ) ;
@@ -268,13 +280,23 @@ export class EmailSender {
268280 headers : Object . keys ( email . headers ) . join ( ',' ) ,
269281 } ) ;
270282
271- // Relay email payload and send status back to calling code.
272- return {
283+ const result : {
284+ sent : boolean ;
285+ messageId ?: string ;
286+ response ?: string ;
287+ message ?: string ;
288+ } = {
273289 sent : true ,
274- message : info ?. message ,
275290 messageId : info ?. messageId ,
276291 response : info ?. response ,
277292 } ;
293+
294+ if ( info ?. message ) {
295+ result . message = info . message ;
296+ }
297+
298+ // Relay email payload and send status back to calling code.
299+ return result ;
278300 } catch ( err ) {
279301 // Make sure error is logged & captured
280302 if ( isAppError ( err ) ) {
0 commit comments