feat: switch to another SMTP transport when current one returns an error

Classic email servers sometimes start rejecting all messages and ask the user to solve web CAPTCHA, but still allow to connect.
In this case we want to switch to another SMTP server by moving the transport to the end of the list returned by smtp::sorted_transports.

We disconnect after any message sending failure, so next message or resent same message will be sent over another other transport.

Permanent SMTP error does not necessarily mean that switching to another server will help.
For example if the user tries to send a large message, any server will reject it, and it is not a failure of the server.
We do not try to distinguish between error messages, so it is expected that we may
sometimes switch to another server when it is unnecessary.
This commit is contained in:
link2xt
2026-10-13 00:43:51 +00:00
committed by l
parent 5510fb5a18
commit d766641ce2
4 changed files with 126 additions and 35 deletions
+13
View File
@@ -471,6 +471,19 @@ CREATE TABLE smtp_success (
FOREIGN KEY(transport_id) REFERENCES transports(id) ON DELETE CASCADE
) STRICT;
-- Similar to smtp_success, but records failures.
CREATE TABLE smtp_failure (
-- Sequentially increasing ID of the failure
-- Transport with the highest ID is to be used last.
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-- ID of the transport that was used to attempt sending a message.
transport_id INTEGER UNIQUE NOT NULL,
-- Delete `smtp_failure` rows when the transport is deleted.
FOREIGN KEY(transport_id) REFERENCES transports(id) ON DELETE CASCADE
) STRICT;
-- Table of "sync items" to be grouped into sync messages
-- and sent to own devices.
CREATE TABLE multi_device_sync (