diff --git a/src/modules/email/services/email-spam.service.ts b/src/modules/email/services/email-spam.service.ts index bf979d5..ef0e1a4 100644 --- a/src/modules/email/services/email-spam.service.ts +++ b/src/modules/email/services/email-spam.service.ts @@ -235,10 +235,23 @@ export class EmailSpamService { const domainTag = user.business?.id || "default"; const wildduckUserId = user.wildduckUserId; - // Check blocked domains + // Check blocked domains for both business-specific tag and default (server-level) const blockedDomainsResponse = await this.listBlockedDomains(domainTag); const blockedDomains = blockedDomainsResponse?.results || []; - const isBlocked = blockedDomains.some((entry: any) => entry.domain?.toLowerCase() === senderDomain.toLowerCase()); + + // Also check server-level blocking (default tag) if domainTag is not "default" + let serverLevelBlockedDomains: any[] = []; + if (domainTag !== "default") { + try { + const serverLevelResponse = await this.listBlockedDomains("default"); + serverLevelBlockedDomains = serverLevelResponse?.results || []; + } catch (error) { + this.logger.warn(`Could not check server-level blocked domains: ${error instanceof Error ? error.message : "Unknown error"}`); + } + } + + const allBlockedDomains = [...blockedDomains, ...serverLevelBlockedDomains]; + const isBlocked = allBlockedDomains.some((entry: any) => entry.domain?.toLowerCase() === senderDomain.toLowerCase()); // Check filters let blockingFilters: any[] = []; @@ -343,6 +356,59 @@ export class EmailSpamService { this.logger.warn(`Could not get address settings: ${error instanceof Error ? error.message : "Unknown error"}`); } + // Check allowlisted domains (in case domain needs to be allowlisted) + let allowlistedDomains: any[] = []; + try { + const allowedResponse = await this.listAllowedDomains(domainTag); + allowlistedDomains = allowedResponse?.results || []; + + // Also check server-level allowlist + if (domainTag !== "default") { + try { + const serverLevelAllowed = await this.listAllowedDomains("default"); + allowlistedDomains = [...allowlistedDomains, ...(serverLevelAllowed?.results || [])]; + } catch (_error) { + // Ignore if can't check server-level + } + } + } catch (error) { + this.logger.warn(`Could not check allowlisted domains: ${error instanceof Error ? error.message : "Unknown error"}`); + } + + // Check server health + let serverHealth: any = null; + try { + const health = await firstValueFrom(this.mailServerService.health.getHealthStatus()); + serverHealth = { + status: "ok", + version: health.version, + processes: health.processes, + connections: health.connections, + storage: { + database: health.storage?.database?.status, + redis: health.storage?.redis?.status, + }, + }; + } catch (error) { + this.logger.warn(`Could not get server health: ${error instanceof Error ? error.message : "Unknown error"}`); + serverHealth = { status: "error", message: error instanceof Error ? error.message : "Unknown error" }; + } + + // Check server settings (SMTP configuration) + let serverSettings: any = null; + try { + const settings = await firstValueFrom(this.mailServerService.settings.getAllSettings()); + serverSettings = { + smtpHostname: settings.smtpHostname, + smtpPort: settings.smtpPort, + smtpAuth: settings.smtpAuth, + smtpTLS: settings.smtpTLS, + smtpMaxConnections: settings.smtpMaxConnections, + }; + } catch (error) { + this.logger.warn(`Could not get server settings: ${error instanceof Error ? error.message : "Unknown error"}`); + } + const result: any = { recipientEmail, senderDomain, @@ -354,10 +420,11 @@ export class EmailSpamService { }, domainTag, blocked: isBlocked, - blockedDomains: blockedDomains.map((entry: any) => ({ + blockedDomains: allBlockedDomains.map((entry: any) => ({ domain: entry.domain, description: entry.description, created: entry.created, + level: blockedDomains.some((b: any) => b.domain === entry.domain) ? "business" : "server", })), allFilters: allFilters.map((filter: any) => ({ id: filter.id, @@ -374,9 +441,17 @@ export class EmailSpamService { queryFrom: filter.query_from, actions: filter.action || [], })), + allowlistedDomains: allowlistedDomains.map((entry: any) => ({ + domain: entry.domain, + description: entry.description, + created: entry.created, + })), emailsFromSender, userSettings, addressSettings, + serverHealth, + serverSettings, + recommendations: [], }; // Unblock if requested and domain is blocked @@ -393,7 +468,7 @@ export class EmailSpamService { } else if (isBlocked && !unblock) { result.message = `Domain ${senderDomain} is blocked. Use unblock=true to unblock it.`; } else { - // Provide more detailed message based on findings + // Provide more detailed message and recommendations based on findings if (emailsFromSender.total > 0) { const locations = []; if (emailsFromSender.inbox.length > 0) locations.push(`${emailsFromSender.inbox.length} in inbox`); @@ -402,8 +477,32 @@ export class EmailSpamService { if (emailsFromSender.archive.length > 0) locations.push(`${emailsFromSender.archive.length} in archive`); result.message = `Domain ${senderDomain} is not blocked. Found ${emailsFromSender.total} email(s) from this domain: ${locations.join(", ")}.`; + + if (emailsFromSender.junk.length > 0) { + result.recommendations.push("Emails are being marked as spam. Check spam filter settings or mark sender as not spam."); + } } else { result.message = `Domain ${senderDomain} is not blocked, but no emails from this domain were found. This suggests emails may be rejected at SMTP level or not reaching the server.`; + + // Add recommendations + result.recommendations.push("Check WildDuck server logs for SMTP rejection messages"); + result.recommendations.push("Verify DNS/MX records for recipient domain (humapek.co)"); + result.recommendations.push("Check sender's email server logs for delivery attempts"); + result.recommendations.push("Verify SPF/DKIM/DMARC records for sender domain (metixco.ae)"); + result.recommendations.push("Check firewall rules - ensure sender's IP is not blocked"); + result.recommendations.push("Verify recipient email address is correct: r.sadat@humapek.co"); + + if (serverHealth?.status !== "ok") { + result.recommendations.push("Server health check failed - investigate server status"); + } + + if (userSettings?.disabled) { + result.recommendations.push("User account is disabled - enable the account"); + } + + if (addressSettings?.addresses?.length === 0) { + result.recommendations.push("No email addresses configured for user - verify address setup"); + } } }