mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
feat(api): allow routing all email through fallback (#3509)
This commit is contained in:
1 parent
d564e01518
commit
2d8d130be1
5 files changed
+27
-3
No files matched your search
@@ -30,6 +30,16 @@ describe('DomainRoutedEmailProvider', () => {
|
||||
expect(result).toBe(route === 'primary');
|
||||
});
|
||||
|
||||
it('sends every address through the fallback provider when the domains are *', async () => {
|
||||
const primary = {sendEmail: vi.fn().mockResolvedValue(true)};
|
||||
const fallback = {sendEmail: vi.fn().mockResolvedValue(true)};
|
||||
const provider = new DomainRoutedEmailProvider(primary, fallback, ['*']);
|
||||
await provider.sendEmail(message('[email protected]'));
|
||||
await provider.sendEmail(message('[email protected]'));
|
||||
expect(fallback.sendEmail).toHaveBeenCalledTimes(2);
|
||||
expect(primary.sendEmail).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('never reaches either provider for a bounced address', async () => {
|
||||
const primary = {sendEmail: vi.fn().mockResolvedValue(true)};
|
||||
const fallback = {sendEmail: vi.fn().mockResolvedValue(true)};
|
||||
|
||||
@@ -21,7 +21,7 @@ export class DomainRoutedEmailProvider implements IEmailProvider {
|
||||
.slice(message.to.lastIndexOf('@') + 1)
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const useFallback = this.fallbackDomains.has(domain);
|
||||
const useFallback = this.fallbackDomains.has('*') || this.fallbackDomains.has(domain);
|
||||
logger.debug({domain, provider: useFallback ? 'fallback' : 'primary'}, 'Routing email');
|
||||
return (useFallback ? this.fallback : this.primary).sendEmail(message);
|
||||
}
|
||||
|
||||
@@ -843,7 +843,7 @@ A second SMTP provider can take the mail for chosen recipient domains while ever
|
||||
|
||||
#### `FLUXER_EMAIL_FALLBACK_DOMAINS`
|
||||
|
||||
Default empty. The recipient domains that go through the fallback provider, comma separated, such as `gmail.com,googlemail.com`. Matching ignores case and takes the part of the address after the last `@`. Only an exact match counts, so `gmail.com` leaves `mail.gmail.com` on the main provider. An entry that is not a bare domain fails startup. `.env.example` lists it commented out.
|
||||
Default empty. The recipient domains that go through the fallback provider, comma separated, such as `gmail.com,googlemail.com`. Matching ignores case and takes the part of the address after the last `@`. Only an exact match counts, so `gmail.com` leaves `mail.gmail.com` on the main provider. Set it to `*` alone to send every email through the fallback provider. An entry that is not a bare domain or `*` fails startup. `.env.example` lists it commented out.
|
||||
|
||||
#### `FLUXER_EMAIL_FALLBACK_SMTP_HOST`
|
||||
|
||||
|
||||
@@ -379,8 +379,11 @@ function normalizeEmailFallbackConfig(config: MasterConfig): void {
|
||||
assertIntegerInRange(port, 'FLUXER_EMAIL_FALLBACK_SMTP_PORT', 1, 65_535);
|
||||
validateSmtpHeaders(smtp.headers, 'FLUXER_EMAIL_FALLBACK_SMTP_HEADERS');
|
||||
const normalizedDomains = domains.map((domain) => domain.trim().toLowerCase());
|
||||
if (normalizedDomains.includes('*') && new Set(normalizedDomains).size > 1) {
|
||||
throw new Error('FLUXER_EMAIL_FALLBACK_DOMAINS must be either * or a list of domains');
|
||||
}
|
||||
for (const domain of normalizedDomains) {
|
||||
if (!EMAIL_DOMAIN_PATTERN.test(domain)) {
|
||||
if (domain !== '*' && !EMAIL_DOMAIN_PATTERN.test(domain)) {
|
||||
throw new Error(
|
||||
`FLUXER_EMAIL_FALLBACK_DOMAINS entry ${JSON.stringify(domain)} must be a domain such as gmail.com`,
|
||||
);
|
||||
|
||||
@@ -540,6 +540,17 @@ describe('ConfigLoader', () => {
|
||||
},
|
||||
);
|
||||
|
||||
test('loads * as the email fallback domains', async () => {
|
||||
stubMinimalEnv({...emailFallbackEnv, FLUXER_EMAIL_FALLBACK_DOMAINS: ' * '});
|
||||
const config = await loadConfig();
|
||||
expect(config.integrations.email.fallback?.domains).toEqual(['*']);
|
||||
});
|
||||
|
||||
test('rejects * mixed with email fallback domains', async () => {
|
||||
stubMinimalEnv({...emailFallbackEnv, FLUXER_EMAIL_FALLBACK_DOMAINS: '*,gmail.com'});
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_EMAIL_FALLBACK_DOMAINS must be either * or a list of domains');
|
||||
});
|
||||
|
||||
test('loads the email fallback headers', async () => {
|
||||
stubMinimalEnv({...emailFallbackEnv, FLUXER_EMAIL_FALLBACK_SMTP_HEADERS: '{"X-Tracking":"{\\"enable\\":0}"}'});
|
||||
const config = await loadConfig();
|
||||
|
||||
Reference in new issue
Block a user