Improve email deliverability checks
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
Docker Emulator Test / docker (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Test / docker (push) Has been cancelled
Runs E2E API Tests / build (22.x) (push) Has been cancelled
Runs E2E API Tests with external source of truth / build (22.x) (push) Has been cancelled
Lint & build / lint_and_build (latest) (push) Has been cancelled
Mirror main branch to main-mirror-for-wdb / lint_and_build (push) Has been cancelled
Dev Environment Test / restart-dev-and-test (push) Has been cancelled
Run setup tests / setup-tests (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled

This commit is contained in:
Konstantin Wohlwend 2025-07-28 17:27:21 -07:00
parent b2cc6f2f58
commit ddf1cfd01a
3 changed files with 21 additions and 7 deletions

View File

@ -114,7 +114,7 @@ export function getProjectConfigOverrideQuery(options: ProjectOptions): RawQuery
throw new StackAssertionError(`Expected 0 or 1 project config overrides for project ${options.projectId}, got ${queryResult.length}`, { queryResult });
}
if (queryResult.length === 0) {
throw new StackAssertionError(`Expected 1 project config override for project ${options.projectId}, got 0`, { queryResult, options });
throw new StackAssertionError(`Expected a project row for project ${options.projectId}, got 0`, { queryResult, options });
}
return queryResult[0].projectConfigOverride ?? {};
},

View File

@ -59,9 +59,9 @@ async function _sendEmailWithoutRetries(options: SendEmailOptions): Promise<Resu
}>> {
let finished = false;
runAsynchronously(async () => {
await wait(5000);
await wait(10000);
if (!finished) {
captureError("email-send-timeout", new StackAssertionError("Email send took longer than 5s; maybe the email service is too slow?", {
captureError("email-send-timeout", new StackAssertionError("Email send took longer than 10s; maybe the email service is too slow?", {
config: options.emailConfig.type === 'shared' ? "shared" : pick(options.emailConfig, ['host', 'port', 'username', 'senderEmail', 'senderName']),
to: options.to,
subject: options.subject,
@ -78,7 +78,20 @@ async function _sendEmailWithoutRetries(options: SendEmailOptions): Promise<Resu
if (options.emailConfig.type === 'shared' && emailableApiKey) {
await traceSpan('verifying email addresses with Emailable', async () => {
toArray = (await Promise.all(toArray.map(async (to) => {
const emailableResponse = await fetch(`https://api.emailable.com/v1/verify?email=${encodeURIComponent(options.to as string)}&api_key=${emailableApiKey}`);
const emailableResponseResult = await Result.retry(async (attempt) => {
const res = await fetch(`https://api.emailable.com/v1/verify?email=${encodeURIComponent(options.to as string)}&api_key=${emailableApiKey}`);
if (res.status === 249) {
const text = await res.text();
console.log('Emailable is taking longer than expected, retrying...', text, { to: options.to });
return Result.error(new Error("Emailable API returned a 249 error for " + options.to + ". This means it takes some more time to verify the email address. Response body: " + text));
}
return Result.ok(res);
}, 4, { exponentialDelayBase: 4000 });
if (emailableResponseResult.status === 'error') {
captureError("emailable-api-timeout", emailableResponseResult.error);
return to;
}
const emailableResponse = emailableResponseResult.data;
if (!emailableResponse.ok) {
throw new StackAssertionError("Failed to verify email address with Emailable", {
to: options.to,
@ -87,7 +100,8 @@ async function _sendEmailWithoutRetries(options: SendEmailOptions): Promise<Resu
});
}
const json = await emailableResponse.json();
if (json.state === 'undeliverable') {
console.log('emailableResponse', json);
if (json.state === 'undeliverable' || json.disposable) {
console.log('email not deliverable', to, json);
return null;
}

View File

@ -24,8 +24,8 @@ export function BackgroundShine() {
position: 'absolute',
top: '-10%',
left: '70%',
width: '20%',
height: '20%',
width: '20vw',
height: '20vh',
background: 'linear-gradient(to bottom, #4E61B3, #9196F4)',
borderRadius: '100%',
filter: 'blur(100px)',