package com.mailserver.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; /** * Domains whose mailboxes live on this server ({@code mailserver.domains}), and the optional catch-all mailbox * ({@code mailserver.catch-all}): when set, mail to ANY address is stored there and nothing is delivered outside — * a mail trap for dev/staging. */ @Component public class MailDomains { private final Set domains; private final String catchAll; public MailDomains(@Value("${mailserver.domains:localhost}") String domains, @Value("${mailserver.catch-all:}") String catchAll) { this.domains = Arrays.stream(domains.split(",")) .map(d -> d.trim().toLowerCase(Locale.ROOT)) .filter(d -> !d.isEmpty()) .collect(Collectors.toUnmodifiableSet()); this.catchAll = catchAll.trim().toLowerCase(Locale.ROOT); if (this.domains.isEmpty()) { throw new IllegalStateException("mailserver.domains is empty"); } } public boolean isLocal(String address) { return domains.contains(domainOf(address)); } /** Mailbox that receives everything, or null. */ public String catchAll() { return catchAll.isEmpty() ? null : catchAll; } public Set domains() { return domains; } /** * Address without its "+tag": {@code bob+prod@x} → {@code bob@x}. Mailbox and list names never contain "+", * so the part after it is a label chosen by the sender — the folder the message goes to. */ public static String baseOf(String address) { String lower = address.toLowerCase(Locale.ROOT); int at = lower.lastIndexOf('@'); int plus = lower.indexOf('+'); return plus > 0 && plus < at ? lower.substring(0, plus) + lower.substring(at) : lower; } /** The "+tag" of an address, or null: {@code bob+prod@x} → {@code prod}. */ public static String tagOf(String address) { int at = address.lastIndexOf('@'); int plus = address.indexOf('+'); return plus > 0 && plus < at - 1 ? address.substring(plus + 1, at) : null; } public static String domainOf(String address) { int at = address == null ? -1 : address.lastIndexOf('@'); return at < 0 ? "" : address.substring(at + 1).toLowerCase(Locale.ROOT); } }