The condition remains from the time when expired messages were hidden
instead of being moved into trash chat. As a result, old hidden
messages, such as location messages, were not deleted.
This function should only return temporary errors, e.g. database errors,
as precheck_imf() and dc_receive_imf::add_parts() treat them as such,
retrying the fetch on failure. When permanent errors, like missing
Message-ID, are bubbled up, they cause infinite fetch loop.
If error is ignored, the message will never be fetched again, even if
there was a database write error.
dc_receive_imf itself is modified to ignore unrecoverable errors, to
prevent endless refetching of incorrect messages.
Let the thread load new messages. This may happen when user switches
the setting to delete messages on the server on and there are a lot of
messages to delete.
This prevents generation of a large number of jobs when IMAP deletion
setting is enabled for the first time. Writing jobs to the database
locks it for readers and may cause UI freezing, because chatlist and
messages can't be read until all jobs are written.
Note that on failure job will be written to the database, to make sure
it is postponed instead of being retried immediately.
Job::new() can be used to create jobs in-memory
Job.update() is replaced with Job.save() which can create new database
entries and consumes Job to avoid the need to update job ID after saving
it to the database.
If precheck_imf fails to check if message with the same rfc724_mid
already exists, the same message may be downloaded twice. Instead,
abort the whole operation and retry later.
For hidden messages, blobs are not deleted during housekeeping. To
actually free the space used by media files, messages should be moved to
trash instead of being hidden.
Some mobile email clients, such as apple mail, attach or inline images
after description, just like Delta Chat. It is better to display them
instead of ignoring.
Since introduction of server message deletion, message may not have
server UID even when it is not a draft or pending message. To handle
such messages correctly, we explicitly check message state.
Now there is only one function: hide_device_expired_messages().
If any messages are hidden event DC_EVENT_MSGS_CHANGED(0,0) is emitted
now, which is more correct than DC_EVENT_CHAT_MODIFIED and also triggers
chatlist reload.
In contrast to get_config_delete_server_after(), value 1 does not mean
"delete at once", because it does not make sense to delete messages
immediately after receivning them.
MarkseenMdnOnImap stored server folder and UID which are never updated
by update_server_uid. Now hidden entries are created for MDNs, so they
should be handled as ordinary messages.
Sometimes message deletion job marks message as unlinked without
actually deleting it. It is possible if the message was already moved
into another folder, possibly by second device, but not detected there
yet. It should be detected later in the other folder, and the
server_uid in the database should be set.
Since introduction of add_imap_deletion_jobs() any expired message
record will be marked as unlinked eventually, because another message
deletion job will be scheduled even if update_server_uid() resurrects
the message once.
This may result in messages not being deleted. Optimization and
traffic-saving is postponed for later, one idea is to optimize message
deletion to avoid checking if Message-ID on the server matches
Message-ID in the database.
If job returns Status::Finished, it will be deleted. Then
add_imap_deletion_jobs will recreate it immediately if the message is
expired. To actually backoff the job, we should postpone it instead of
removing.
This is to avoid creating thousands of jobs when user enables
"delete_server_after" setting for the first time.
If device is offline for more than 2 weeks, some messages may not be
deleted.
When "delete_server_after" setting is configured, postponed
DeleteMsgOnImap jobs are created for incoming messages.
This commit adds job::add_imap_deletion_jobs function which creates
DeleteMsgOnImap jobs right before performing IMAP jobs. This way even
messages that expired when the setting was disabled are going to be
deleted.
Job creation on message reception is unnecessary now, and even harmful
because it will create jobs with an expiration time which may later be
reduced. It is planned to be removed in following commits.
Now 0 means "never delete", 1 means "delete at once" and other values
indicate the number of seconds after which them message should be
deleted from the server.
Configuration value interpretation is moved into
Context.get_config_delete_server_after() function.
At least one entry is required for DeleteMsgOnImap job. Additionally,
adding a hidden entry makes it possible to avoid redownloading the
message if it gets a new UID on the server.
DeleteMsgOnImap deletes files from the server only when the last part
is deleted. Removing only the first part of the hidden or trashed
message does not result in message deletion.
Currently only trashed or hidden messages are deleted by
DeleteMsgOnImap, so it is safe to remove database records.
It is planned to delete messages on IMAP server after
user-configurable time to cleanup the server even for messages
displayed in chats. For such messages, we unlink them from the
Message-ID, but keep the database record to display them.
Mutable UID reference is removed. Instead, ImapActionResult is
returned immediately.
If message has changed and UID does not correspond to expected
message, ImapActionResult::Failed is returned. Temprorary IMAP errors
result in ImapActionResult::RetryLater.
On the job side, ImapActionResult::RetryLater does not result in
immediate job retry anymore. Instead, job is retried with a backoff.
In addition to moving the message into trash chat, this function
removes message text to make sure the message does not remain in the
database. Only the information necessary to delete message from the
server and avoid redownloading it should be kept, such as Message-Id
and IMAP UID.