@@ -44,15 +44,24 @@ async function onAuth(auth, session, fn) {
4444 // TODO: replace usage of config.recordPrefix with config.paidPrefix and config.freePrefix
4545
4646 try {
47+ // Cache server type checks for performance (conditional logic simplification)
48+ const isIMAPServer = this . server instanceof IMAPServer ;
49+ const isPOP3Server = this . server instanceof POP3Server ;
50+ const isIMAPorPOP3 = isIMAPServer || isPOP3Server ;
51+ const isCalDAV = this ?. constructor ?. name === 'CalDAV' ;
52+ const isCardDAV = this ?. constructor ?. name === 'CardDAV' ;
53+ const isAPI = this ?. constructor ?. name === 'API' ;
54+ const isIMAP = this ?. constructor ?. name === 'IMAP' ;
55+ const isPOP3 = this ?. constructor ?. name === 'POP3' ;
56+
4757 //
4858 // NOTE: until onConnect is available for IMAP and POP3 servers
4959 // we leverage the existing SMTP helper in the interim
5060 // <https://github.com/nodemailer/wildduck/issues/540>
5161 // <https://github.com/nodemailer/wildduck/issues/721>
5262 // (see this same comment in `helpers/on-connect.js`)
5363 //
54- if ( this . server instanceof IMAPServer || this . server instanceof POP3Server )
55- await onConnectPromise . call ( this , session ) ;
64+ if ( isIMAPorPOP3 ) await onConnectPromise . call ( this , session ) ;
5665
5766 // check if server is in the process of shutting down
5867 if ( this . isClosing ) throw new ServerShutdownError ( ) ;
@@ -62,7 +71,7 @@ async function onAuth(auth, session, fn) {
6271
6372 // NOTE: WildDuck POP3 doesn't expose socket on session yet (also see similar comment in onAuth helper)
6473 // check if socket is still connected (only applicable for IMAP and POP3 servers)
65- if ( this . server instanceof IMAPServer ) {
74+ if ( isIMAPServer ) {
6675 const socket =
6776 ( session . socket && session . socket . _parent ) || session . socket ;
6877 if ( ! socket || socket ?. destroyed || socket ?. readyState !== 'open' )
@@ -71,8 +80,7 @@ async function onAuth(auth, session, fn) {
7180
7281 // NOTE: this is only required for WildDuck servers (IMAP/POP3)
7382 // override session.getQueryResponse (safeguard)
74- if ( this . server instanceof IMAPServer || this . server instanceof POP3Server )
75- session . getQueryResponse = getQueryResponse ;
83+ if ( isIMAPorPOP3 ) session . getQueryResponse = getQueryResponse ;
7684
7785 // username must be a valid email address
7886 if (
@@ -163,55 +171,163 @@ async function onAuth(auth, session, fn) {
163171 }
164172 ) ;
165173
166- const domain = await Domains . findOne ( {
167- name : domainName ,
168- verification_record : verifications [ 0 ] ,
169- plan : { $in : [ 'enhanced_protection' , 'team' ] }
170- } )
171- . populate (
172- 'members.user' ,
173- `id group plan ${ config . userFields . isBanned } ${ config . userFields . hasVerifiedEmail } ${ config . userFields . planExpiresAt } ${ config . userFields . stripeSubscriptionID } ${ config . userFields . paypalSubscriptionID } timezone`
174- )
175- . select ( '+tokens.hash +tokens.salt' )
176- . lean ( )
177- . exec ( ) ;
174+ //
175+ // OPTIMIZATION: Combined domain and alias query using aggregation pipeline
176+ // This reduces two separate database queries into one
177+ //
178+
179+ const results = await Domains . aggregate ( [
180+ {
181+ $match : {
182+ name : domainName ,
183+ verification_record : verifications [ 0 ] ,
184+ plan : { $in : [ 'enhanced_protection' , 'team' ] }
185+ }
186+ } ,
187+ {
188+ $lookup : {
189+ from : 'aliases' ,
190+ let : { domainId : '$_id' } ,
191+ pipeline : [
192+ {
193+ $match : {
194+ $expr : {
195+ $and : [
196+ { $eq : [ '$domain' , '$$domainId' ] } ,
197+ { $eq : [ '$name' , name ] }
198+ ]
199+ }
200+ }
201+ } ,
202+ {
203+ $lookup : {
204+ from : 'users' ,
205+ localField : 'user' ,
206+ foreignField : '_id' ,
207+ as : 'user'
208+ }
209+ } ,
210+ {
211+ $unwind : {
212+ path : '$user' ,
213+ preserveNullAndEmptyArrays : true
214+ }
215+ } ,
216+ {
217+ $addFields : {
218+ user : {
219+ _id : '$user._id' ,
220+ id : '$user.id' ,
221+ [ config . userFields
222+ . isBanned ] : `$user.${ config . userFields . isBanned } ` ,
223+ [ config . userFields
224+ . smtpLimit ] : `$user.${ config . userFields . smtpLimit } ` ,
225+ email : '$user.email' ,
226+ [ config . lastLocaleField ] : `$user.${ config . lastLocaleField } ` ,
227+ timezone : '$user.timezone'
228+ }
229+ }
230+ }
231+ ] ,
232+ as : 'alias'
233+ }
234+ } ,
235+ {
236+ $lookup : {
237+ from : 'users' ,
238+ localField : 'members.user' ,
239+ foreignField : '_id' ,
240+ as : 'memberUsers'
241+ }
242+ } ,
243+ {
244+ $addFields : {
245+ members : {
246+ $map : {
247+ input : '$members' ,
248+ as : 'member' ,
249+ in : {
250+ $mergeObjects : [
251+ '$$member' ,
252+ {
253+ user : {
254+ $arrayElemAt : [
255+ {
256+ $filter : {
257+ input : '$memberUsers' ,
258+ as : 'u' ,
259+ cond : { $eq : [ '$$u._id' , '$$member.user' ] }
260+ }
261+ } ,
262+ 0
263+ ]
264+ }
265+ }
266+ ]
267+ }
268+ }
269+ }
270+ }
271+ } ,
272+ {
273+ $project : {
274+ memberUsers : 0 ,
275+ 'members.user.password' : 0 ,
276+ 'members.user.api_token' : 0 ,
277+ 'members.user.otp_recovery_keys' : 0 ,
278+ 'members.user.otp_enabled' : 0 ,
279+ 'members.user.reset_token_expires_at' : 0 ,
280+ 'members.user.reset_token' : 0
281+ }
282+ } ,
283+ {
284+ $addFields : {
285+ alias : {
286+ $cond : {
287+ if : { $gt : [ { $size : '$alias' } , 0 ] } ,
288+ // eslint-disable-next-line unicorn/no-thenable
289+ then : { $arrayElemAt : [ '$alias' , 0 ] } ,
290+ else : null
291+ }
292+ }
293+ }
294+ }
295+ ] ) ;
296+
297+ const result = results [ 0 ] ;
298+ if ( ! result ) {
299+ throw new SMTPError (
300+ `Domain not found or does not have a valid plan, go to ${
301+ config . urls . web
302+ } /my-account/domains/${ punycode . toASCII (
303+ domainName
304+ ) } and click "Verify"`,
305+ {
306+ responseCode : 535 ,
307+ ignoreHook : true
308+ }
309+ ) ;
310+ }
311+
312+ const domain = result ;
313+ const alias = name === '*' ? null : result . alias ;
178314
179315 // validate domain
180316 validateDomain ( domain , domainName ) ;
181317
182- let alias ;
183- if ( name !== '*' )
184- alias = await Aliases . findOne ( {
185- name,
186- domain : domain . _id
187- } )
188- . populate (
189- 'user' ,
190- `id ${ config . userFields . isBanned } ${ config . userFields . smtpLimit } email ${ config . lastLocaleField } timezone`
191- )
192- . select ( '+tokens.hash +tokens.salt +is_rekey' )
193- . lean ( )
194- . exec ( ) ;
195-
196318 // validate alias (will throw an error if !alias)
197- if (
198- alias ||
199- this . server instanceof IMAPServer ||
200- this . server instanceof POP3Server
201- )
202- validateAlias ( alias , domain . name , name ) ;
319+ if ( alias || isIMAPorPOP3 ) validateAlias ( alias , domain . name , name ) ;
203320
204321 //
205322 // validate the `auth.password` provided
206323 //
207324
208325 // IMAP/POP3/CalDAV/CardDAV/API servers can only validate against aliases
209326 if (
210- this . server instanceof IMAPServer ||
211- this . server instanceof POP3Server ||
212- ( alias && this ?. constructor ?. name === 'CalDAV' ) ||
213- ( alias && this ?. constructor ?. name === 'CardDAV' ) ||
214- ( alias && this ?. constructor ?. name === 'API' )
327+ isIMAPorPOP3 ||
328+ ( alias && isCalDAV ) ||
329+ ( alias && isCardDAV ) ||
330+ ( alias && isAPI )
215331 ) {
216332 if (
217333 alias &&
@@ -295,8 +411,7 @@ async function onAuth(auth, session, fn) {
295411 // we allow users to use a generated token for the domain
296412 //
297413 if (
298- ! ( this . server instanceof IMAPServer ) &&
299- ! ( this . server instanceof POP3Server ) &&
414+ ! isIMAPorPOP3 &&
300415 ! isValid &&
301416 Array . isArray ( domain . tokens ) &&
302417 domain . tokens . length > 0
@@ -349,11 +464,16 @@ async function onAuth(auth, session, fn) {
349464 ) ;
350465 }
351466
352- // Clear authentication limit for this IP address
353- await this . client . del ( `auth_limit_${ config . env } :${ session . remoteAddress } ` ) ;
354-
355- // this also ensures that at least one admin has a verified email address
356- const obj = await Domains . getToAndMajorityLocaleByDomain ( domain ) ;
467+ //
468+ // OPTIMIZATION: Parallelize independent async operations
469+ // Clear auth limit and get locale info can run in parallel
470+ //
471+ const [ , obj ] = await Promise . all ( [
472+ // Clear authentication limit for this IP address
473+ this . client . del ( `auth_limit_${ config . env } :${ session . remoteAddress } ` ) ,
474+ // this also ensures that at least one admin has a verified email address
475+ Domains . getToAndMajorityLocaleByDomain ( domain )
476+ ] ) ;
357477
358478 const to = [ ] ;
359479
@@ -376,7 +496,7 @@ async function onAuth(auth, session, fn) {
376496 // alert them by email to inform them they need to enable SMTP
377497 // (otherwise calendar invites will not be sent out automatically)
378498 //
379- if ( alias && this ?. constructor ?. name === 'CalDAV' && ! domain . has_smtp ) {
499+ if ( alias && isCalDAV && ! domain . has_smtp ) {
380500 this . client
381501 . get ( `caldav_smtp_check:${ domain . id } ` )
382502 . then ( async ( cache ) => {
@@ -439,13 +559,7 @@ async function onAuth(auth, session, fn) {
439559 alias &&
440560 ! alias . has_imap &&
441561 ! _ . isDate ( alias . imap_not_enabled_sent_at ) &&
442- ( this . server instanceof IMAPServer ||
443- this . server instanceof POP3Server ||
444- this ?. constructor ?. name === 'CalDAV' ||
445- this ?. constructor ?. name === 'CardDAV' ||
446- this ?. constructor ?. name === 'API' ||
447- this ?. constructor ?. name === 'IMAP' ||
448- this ?. constructor ?. name === 'POP3' )
562+ ( isIMAPorPOP3 || isCalDAV || isCardDAV || isAPI || isIMAP || isPOP3 )
449563 ) {
450564 this . client
451565 . get ( `imap_check:${ alias . id } ` )
@@ -538,7 +652,7 @@ async function onAuth(auth, session, fn) {
538652 // NOTE: this is only for IMAP servers
539653 // <https://github.com/zone-eu/wildduck/issues/629#issuecomment-1956910918>
540654 //
541- if ( this ?. constructor ?. name === 'IMAP' && this . server ) {
655+ if ( isIMAP && this . server ) {
542656 const key = `concurrent_${ this . constructor . name . toLowerCase ( ) } _${
543657 config . env
544658 } :${ alias ? alias . id : domain . id } `;
@@ -672,14 +786,7 @@ async function onAuth(auth, session, fn) {
672786 //
673787 // if we're on IMAP, POP3, or CalDAV server then sync messages with user
674788 //
675- if (
676- alias &&
677- alias . has_imap &&
678- ( this . server instanceof IMAPServer ||
679- this . server instanceof POP3Server ||
680- this ?. constructor ?. name === 'CalDAV' ) &&
681- this . wsp
682- ) {
789+ if ( alias && alias . has_imap && ( isIMAPorPOP3 || isCalDAV ) && this . wsp ) {
683790 // sync with tmp db
684791 this . wsp
685792 . request (
0 commit comments