"Send now" and "Reschedule" create a replacement submission and then
cancel the original. The server checks the recipients again for the
replacement, and a throttle used up since the original was taken ("452
4.4.5 Rate limit exceeded") can refuse some of them. The original was
kept only when every recipient was refused; on a partial refusal it was
cancelled, and a recipient the original had taken lost the message
without anyone being told.
- The original's delivery status is read with its envelope. When the
replacement refuses a recipient the original took, the replacement is
cancelled (its record only destroyed when it took nobody) and the
original goes at its old time. A recipient the original refused as
well loses nothing, so the reschedule goes ahead; checked live on
0.16.23 and 1.0 with a relay-refused recipient.
- The toast for a kept schedule leads with "The message is still
scheduled for ..." and says "Nothing was changed: the server refused
...". It used to open with "Not sent", which invited sending the
message a second time.
- Recipients refused while the others were taken are now named after
"Send now", a reschedule from the list or the viewer, and a quick
reply, which said "Email sent".
Files, from the review of d9ffe8a7:
- An own folder opened from search while Files showed a shared folder
opened the shared folder again: its link had no query, and the page
read `?shared=` from the address bar. The link now says it has none.
- The Pro shell kept only the path of a Files link across its redirect,
so a shared folder's link (`/files?shared=...`) didn't survive a
reload, and neither did `?preview=`. The query goes along now.
- A search hit for a file on a "Files from" page opened the first file
of that name there; it is found by the id the link names now.
- Undoing a paste of files cut on a "Files from" page moved them to
"*", the page's id; they go back to their own folders now.
Stalwart runs the SMTP RCPT stage while it creates a submission and
records a refused recipient as `delivered: "no"` with its reply: a relay
it doesn't allow ("550 5.1.2 Relay not allowed.") or a used-up throttle
("452 4.4.5 Rate limit exceeded, try again later."), on 0.16 and 1.0
alike. The create still succeeds and onSuccessUpdateEmail files the
message in Sent. Bulwark read only the new record's id and sendAt, said
"Email sent", and on Stalwart destroyed the record right after, the only
trace of the refusal. The message was lost without a bounce.
- the send reads the new submission's delivery status in the same
request (`EmailSubmission/get` by its creation id; the create's answer
has none), before the record is destroyed
- every recipient refused: the send fails with the server's reply per
address, the copy filed in Sent is removed and the user's draft kept,
so the address can be fixed in the composer; held sends (undo send,
scheduled) are refused when created, so this covers them too
- some recipients refused: the others get the message, and a warning
names the refused ones with their replies
- "Send now" and "Reschedule" keep the original when every recipient of
the replacement is refused, instead of cancelling it
- the submission prune leaves a shared account that refuses its records
alone for the session, without a warning: 0.16 lists an account that
only shared an address book or a calendar with the submission
capability
Several failures around scheduled and undoable sends said the wrong thing
or nothing at all:
- "Undo send failed" also appeared when the cancel went through and only
putting the message back in Drafts failed, suggesting the mail might
still go out. Now that case says the send was cancelled and the message
is still in Sent (or, for S/MIME, that its copy could not be removed);
a failed cancel keeps the old message.
- "Cancel and edit" had no error handling, so a failure ended as an
unhandled rejection. It now reports a failed cancel and a failed restore
the same way as undo.
- A failed "Send now" or reschedule at a full submission quota did not say
that the message is still scheduled. It now does, with its time.
- The reschedule retry after making room could send a message twice: the
prune and change-log walk take a while, and the original could go out
meanwhile. The original is read again first and nothing is resubmitted
unless it is still pending ("This message was already sent" otherwise),
and HOLDFOR is worked out again after the slow step.
- The List-Unsubscribe mailto path showed only a generic error at a full
quota; it now shows the quota explanation too.
- The Stalwart explanation of a full quota (Bulwark removed what it
could, an administrator has to raise the limit) was shown for any
server's `overQuota`. It now needs `urn:stalwart:jmap` on the
submission account; other servers get a generic sentence with their
own description.
- At a full quota every attempt, including each automatic read receipt,
ran the forced prune, the change-log walk and the gets again. When they
find nothing that can go, the account is left alone for five minutes.
Stalwart 1.0 counts every EmailSubmission record of an account against
`maxSubmissions` (500 by default), whatever its status or age, and its
own purge of old records never runs. Bulwark never destroyed a
submission, so after about 500 JMAP sends an account could not send at
all: every send, read receipt and reschedule failed with a raw "There
are too many email submissions" error, and each failed attempt left one
more copy of the message in Drafts.
Bulwark now removes the records that can no longer be cancelled.
Destroying a record never stops its delivery, but a pending one could
no longer be cancelled, so pending records are never touched:
- an immediate send (no hold, no undo window) destroys its own record
right after the send, riding along with the old-draft cleanup; only
where `urn:stalwart:jmap` is advertised, and never decided by the
created `undoStatus`, which 0.16.10-0.16.16 report as final for held
sends
- a throttled background prune destroys canceled records and final
records whose `sendAt` has passed, going by `EmailSubmission/get`, in
every submission account; it runs at startup, after sends, after
undo and on EmailSubmission state changes
- a confirmed cancel (undo, cancel, reschedule) destroys the canceled
record in a request of its own
- an `overQuota` on a submission create prunes at once, on Stalwart
walks the change log for records older than the query's three-day
window, retries once, and otherwise throws `SubmissionQuotaError`,
shown as a translated explanation in the composer, quick reply, read
receipts and the scheduled-send actions
Failed sends now clean up after themselves and say so:
- a failed send removes the Drafts copy it created and keeps the
user's draft; the raw send paths remove their import the same way
- a read receipt that did not go out is taken back out of Sent, a
method-level error counts as a failure, `$MDNSent` is only set after
a sent receipt, and the automatic receipt no longer retries on every
refresh of the open message
- quick-reply failures, "Send now", "Reschedule" and a failed undo are
shown instead of only logged
- the scheduled list reads every page of `EmailSubmission/query`; it
stopped after the first because `total` needs `calculateTotal`