[Refactor] Make all SMTP 4yz Errors Retryable (#1293)

### Context
The `emails-low-level.tsx` file is where the sending logic of an email
over smtp occurs. It tries to send an email, and if there is an issue it
has logic to mark the email as retryable or not. Then, the
`email-queue-step` itself handles the actual retry efforts based on this
flag and a few other factors (like if max retries have been attempted).
Currently, if an error code isn't explicitly accounted for, it falls
back to being an "unknown error while sending" and is marked as not
retryable.
However, SMTP [defines the 4yz class of error codes as being
retryable](https://www.iana.org/assignments/smtp-enhanced-status-codes/smtp-enhanced-status-codes.xhtml).

### Summary of Changes
We add fallback logic at the end of the `responseCode` specific block to
mark the 4yz class of error codes as retryable. While the message here
is less specific, that is okay since any codes we want to explicitly
account for are handled above it. The main thing here is that these
should be retried.
This commit is contained in:
Aman Ganapathy 2026-04-07 09:20:39 -07:00 committed by GitHub
parent 05036477ff
commit 3f01358f9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -18,6 +18,13 @@ export function isSecureEmailPort(port: number | string) {
return parsedPort === 465 || parsedPort === 2465;
}
function is4yzSMTPResponseCode(code: number | undefined) {
if (typeof code !== 'number') {
return false;
}
return code >= 400 && code < 500;
}
export type LowLevelEmailConfig = {
host: string,
port: number,
@ -168,6 +175,16 @@ async function _lowLevelSendEmailWithoutRetries(options: LowLevelSendEmailOption
message: 'Connection to email server was lost unexpectedly. This could be due to incorrect email server port configuration or a temporary network issue. Please verify your configuration and try again.',
} as const);
}
// 4yz error codes are considered temporary errors in SMTP, so they should be retried anyway
// This is fallback logic for a code we don't explicitly capture but should still be retryable and we have the code
if (is4yzSMTPResponseCode(responseCode)) {
return Result.error({
rawError: error,
errorType: 'TRANSIENT_NEGATIVE_COMPLETION_REPLY',
canRetry: true,
message: 'The email server returned a temporary error. Please try again later.' + getServerResponse(error),
} as const);
}
}
// ============ temporary error ============