by #2001, processing of protection-enabled and protection-disabled
messages is only done if verification-checks pass.
unfortunately, these verification checks
were only applied on already protected chats,
so that enabling via a protection-enabled message was not possible.
this is fixed by this pr.
moreover, when inner_set_protection() fails,
the error is shown in the chat.
this avoids confusion - as long the current core
does not communicate with a UI that enables/disables protection,
everything looks just the same as in the past :)
update_device_chats() takes about 2 seconds on a modern device (Android) because the
welcome image file has to be written to the disk as a blob. The problem
was that this was done after the progress bar had vanished and before
anything else happened so that I thought that something had gone wrong
multiple times.
The UIs have to remove update_device_chats(), too..
this would exclude non-deltas from protected-chats
(where they could participate in verified-groups in the past)
and makes migration a bit harder when using a fuzzy multi-device-setup.
however, the test still takes place
when a group is created or protection is enabled/disabled.
should_encrypt() shall return Ok(false)
on peerstate=EncryptPreference::Reset
only for opportunistic groups.
for verified/protected groups (e2ee_guaranteed set),
Ok(true) or Error() should be returned.
this bug was introduced by #1946 (Require quorum to enable encryption).
a draft may contain only a quote,
without any text set yet.
these drafts cannot be sent, however, appear in the summary -
currently with the summary-text "", which results to sth.
as "Draft: " - which looks like an error or at least a bit weird.
this pr sets the summary text to "Reply" - similar to "Image", "Video" etc. -
the UI just expects some text here, not an empty string.
the result are summaries as "Draft: Reply" on all UIs -
which, btw. is also roughly the same what Signal does in this case.
the constant comes from c-core
and was used to define the size of the string-array that time.
this is no longer needed in core
and also the UIs seems not to use it
(they will treat DC_STR* like an id,
there should be no need to know the max. DC_STR* value)
Read all of an e-mail accounts messages and extract all To/CC addresses
if the From was from our own account.
Then, fetch existing messages from the server and show them.
Also, I fixed two other things:
- just by chance my test failed because of an completely unrelated bug.
The bug: bcc_self messages were not marked as read if mvbox_move was set
to true.
- add some color to the test output (minor change)
Sticky encryption rule, requiring that all replies to encrypted messages
are encrypted, applies only to messages with a quote now.
Co-Authored-By: B. Petersen <r10s@b44t.com>
This code is inconsistent with EncryptHelper::should_encrypt, which uses
quorum rule.
UI does not display or use encryption state in-between preparing and
sending message anyway.
In addition, "sticky encryption" rule, which required all replies to
encrypted messages to be encrypted, is dropped. It is going to be
restored with the introduction of quoting.
both are not used in productive:
- chat-id "in-creation" was dropped completely already in core-c
as it does not allow assigning messages to chats in time.
- message flag "starred" was added at some point and never used.
ux-wise, "disappearing messages" promises to clean up a chat -
this does not fit well with "starring" messages.
"saved messages" chat seems to be superior in that regard.
but anyway, it is not used but comes at maintainance costs,
so it is better to delete its functionality for now.
(the db entries, however, are left for now,
that might be more tricky to remove)
Address is used to generate Message-Id.
Previously error toast was shown, but MsgId was returned from
chat::prepare_msg anyway. Now chat::prepare_msg returns an error.
error!() is removed, because FFI library shows errors via
.unwrap_or_log_default().
When run against host that is not in the provider database or has multiple
IMAP servers listed, this test fails because one error is returned for
each server.
* Mention in dc_event_get_data2_str method that it can also return 0
* Update deltachat-ffi/deltachat.h
Co-authored-by: bjoern <r10s@b44t.com>
Co-authored-by: bjoern <r10s@b44t.com>
Previously, standard Autocrypt rule was used to determine whether
encryption is enabled: if at least one recipient does not prefer
encryption, encryption is disabled.
This rule has been problematic in large groups, because the larger
is the group, the higher is the chance that one of the users does not
prefer encryption.
New rule requires a majority of users to prefer encryption. Note that it
does not affect 1:1 chats, because it is required that *strictly* more
than a half users in a chat prefer encryption.
partly, we wrote '@return None.' for void functions,
however, some linter complain about that (recently swift)
and they're right, it does not make much sense.
On Android, there is to /tmp directory, so SQLite may throw
SQLITE_IOERR_GETTEMPPATH when trying to find a place for temporary
files. Storing temporary files in memory is a workaround that always
works (until out of memory).
See https://github.com/mozilla/mentat/issues/505 for discussion of a
similar issue.
In the current design the dc_receive_imf() pipeline calls
handle_securejoin_handshake() before it creates the group. However
handle_securejoin_handshake() already signals to securejoin() that the
chat exists, which is not true.
The proper fix would be to re-desing how group-creation works,
potentially allowinng handle_securejoin_handshake() to already create
the group and no longer require any further processing by
dc_receive_imf().
'Delete emails from server' was an experimental ad-hoc function
that was added before 'Automatically delete old messages' was introduced
to allow at least some way to cleanup.
'Delete emails from server'-UI was already removed from android/ios in june
(see https://github.com/deltachat/deltachat-android/pull/1406)
and the function never exists on desktop at all.
This currently tests the setup-contact full flow and the shortcut
flow. More securejoin tests are needed but this puts some
infrastructure in place to start writing these.
This commit fixes condition which ignores reordered autocrypt messages.
If a plaintext message resetting peerstate has been received, autocrypt
header should only be applied if it has higher timestamp.
Previously, timestamp of the last received autocrypt header was used,
which may be lower than last_seen timestamp.
# Conflicts:
# src/peerstate.rs
Previously DC_EVENT_ERROR_NETWORK events were emitted for each failed
attempt during autoconfiguration, even if eventually configuration
succeeded. Such error reports are not useful and often confusing,
especially if they report failures to connect to domains that don't
exist, such as imap.example.org when mail.example.org should be used.
Now DC_EVENT_ERROR_NETWORK is only emitted when attempting to connect
with existing IMAP and SMTP configuration already stored in the
database.
Configuration failure is still indicated by DC_EVENT_CONFIGURE_PROGRESS
with data1 set to 0. Python tests from TestOnlineConfigurationFails
group are changed to only wait for this event.
This turns the Bob::expects field into an enum, removing the old
constants. It also makes the field private, nothi0ng outside the
securejoin module uses it.
Finally it documents stuff, including a seemingly-unrelated Param.
But that param is used by the securejoin module... It's nice to have
doc tooltips be helpful.
LoginParamNew structure, which contained possible IMAP and SMTP
configurations to try is replaced with uniform vectors of ServerParams
structures. These vectors are initialized from provider database, online
Mozilla or Outlook XML configuration or user entered parameters.
During configuration, vectors of ServerParams are expanded to replace
unknown values with all possible variants, which are tried one by one
until configuration succeeds or all variants for a particular protocol
(IMAP or SMTP) are exhausted.
ServerParams structure is moved into configure submodule, and all
dependencies on it outside of this submodule are removed.
in general, Viewtypes other than File should be used only
when the added file type is tested on all platforms -
including Android4 currently.
as this is easily overseen,
i've added a comment.
this partly reverts Viewtype changes done by
https://github.com/deltachat/deltachat-core-rust/pull/1818
Fix#1791 and show all group messages if the user already is in the group, even if the sender is blocked
Also fix a comment
Co-authored-by: link2xt <ilabdsf@gmail.com>
This fixes#1804 in two ways: First, it removes a <!doctype html> from
the start of the mail, if there is any.
Then, it parses the html itself it quick-xml fails, just stripping
everything between < and >.
Both of these would have fixed this specific issue.
Also, add tests for both fixes.
threading was broken in core43 as this flags unencrypted messages as errors
and errors are not replied-to.
the fix is not to mark missing signatures for unencrypted messages as errors.
.tgs files are Telegram stickers. Internally they are gzipped JSON files,
containing a single Lottie animation.
MIME type application/x-tgsticker is commonly used for telegram documents
containing such stickers.
An EphemeralTimerChanged message with the same timer as already set can
be received when there are large delays or lost messages. Even though
inner_set_ephemeral_timer should not be called in this case, because it
emits an event indicating timer change, system message will be added to
the chat, so it should be translated with set_better_msg in any case.
Normally NULL is used when there is no fingerprint, but default value
for fingerprint columns is an empty string.
In this case, loading should not fail with an "invalid length" error,
but treat the fingerprint as missing.
Strict check was introduced in commit ca95f25639
Since try_decrypt does not check if the message has valid signatures
anymore, it may return empty signatures set, which means the message is
not a valid autocrypt message.
this pr allows prefixing custom jitsi urls with `jitsi:`
so that clients have a chance to detect these custom instances
and may start the corresponding app.
introduce the qr-code-type `DCWEBRTC:[webrtc_instance]`.
dc_check_qr() returns this as the type DC_QR_WEBRTC
and these qr-codes can be passed to dc_set_config_from_qr() then;
this finally sets `webrtc_instance` using dc_set_config().
needed for how node/js handles the chatlist currently
(it convertes the ffi-object to an js-object and throws ffi-object away directly,
this makes it hard to access dc_chatlist_get_summary() later.
Since introduction of provider database, these certificate checks are
enabled for test servers anyway, but this setting prevents usage of
local servers with self-signed certificates.
It presents no security issue, because properly configured servers will
only serve passwords on HTTPS and distribute only HTTPS QR codes, but
makes testing easier when HTTPS is not easy to deploy.
If attacker can control the URL used, they can change the URL to another
HTTPS URL controlled by them and act as a proxy between the client and
original server anyway.
Adhoc groups for group messages that don't have Chat-Group-ID are already
created above in another create_or_lookup_adhoc_group.
At this point it could be that there is a valid Chat-Group-ID header,
but no group was created because removed_id was non-zero i.e. received
message removes some group member.
If group was not explicitly left, current code creates an adhoc group
instead of trashing late or reordered messages that remove group
members. Such groups have adhoc group IDs locally, but proper group
message-IDs. Attempts to reply to such groups or leave them creates
"split groups" for all other members of original group. The solution is
not to create adhoc groups in this case.
Permanent error 550 5.1.1 is no longer considered temporary.
Enhanced status code is checked now, so only 550 5.5.0 is an exception
for misconfigured Postfix servers.
Yandex error 554 5.7.1 was handled correctly, but only because it had
response code 554, while the comment talks about enhanced status code
5.7.1. The comments are corrected.
Failed messages are now marked as such with message::set_msg_failed.
Previously they were left in a pending state.
If info message cannot be added to the chat, the error is displayed with
error! instead of being logged with warn!.
when seeing our own profile image send from other devices,
we use them as Selfavatar on the current device as well.
as there is no special message sent on avatar changes,
this is a simple approach to sync the avatar across devices.
Now MarkseenMsgOnImap sends MDN even if it can't mark the message as
seen on the server.
To prevent multiple MDNs from being sent, MarkseenMsgOnImap is postponed
until the message is detected in a folder from which it is not going to
be moved.
Mimeparser.was_encrypted() checks if the message is an Autocrypt encrypted
message. It already means the message has a valid signature.
This commit documents a few functions to make it clear that signatures
stored in Mimeparser must be valid and must always come from encrypted
messages.
Also one unwrap() is eliminated in encrypted_and_signed(). It is possible
to further simplify encrypted_and_signed() by skipping the was_encrypted()
check, because the function only returns true if there is a matching
signature, but it is helpful for debugging to distinguish between
non-Autocrypt messages and messages whose fingerprint does not match.
Add a mutex to prevent a race condition when a "your pw is wrong" warning is sent, resulting in multiple messeges being sent.
Do not mute the device chat but "only" send MsgsChanged event when no
notification shall be shown.
More logging.
Parallel processing of messages results in bugs such as messages sent by
a new member being processed before the message that adds this member to
the chat, even when it has lower UID. In this case, messages are shown as
"[Unknown sender for this chat. See 'info' for more details.]", while
there is a message "Member ... added" right before, because writing the
information about new member to the database takes longer then reading
old index from the database.
With this change, API user does not need to look at the timestamp of
the next message to display the day marker, but can get the timestamp
directly from the marker. This way there is no database query and no
risk of error as a result of database being busy or message being deleted.
instead of applying all config_defaults unconditionally
after the first configure, a config_defaults for a given key
is now applied when this key has never been set before.
this way, you can set some keys before calling configure()
and also, later versions can add new defaults for new keys
(that would require another call to configure() then, however)
for "fresh" messages, calc_sort_timestamp() makes sure,
the sorting timestamp is not less than the last-non-fresh message.
this commit fixes the "fresh" state we give to calc_sort_timestamp(),
it just uses the message-state we've already calculated.
the old assumption, that unseen messages are always fresh
is wrong as this "seen" flag just comes from an imap-flag
that is not set for self-sent messages.
therefore, in a multi-device-setup, things are totally messed up.
(the bug was probably in there since a long time,
however did not came to light until the async-move)
This tidies up our testing tools a little bit. We had several
functions which through various changes ended up doing the same and
some more which did very similar stuff, so I merged them to have
things simpler. Also moved towards methods on the TestContext struct
while cleaning this up anyway, seems like this structure is going to
stay around for a bit anyway.
The intersting change is in `test_utils.rs`, everything else is just
updating callers. A few tests used example.org which I moved to
example.com to be able to re-use more configuration of the test
context.
the last message shown in a chatlist
is the one with the largets timestamp that is not hidden.
in the past, we calcualted the last timestamp using a subquery
and uses that timestamp to finally get the message.
this may fail when there are two messages with the same max. timestamp.
with this fix, we return the id from the subquery and use that
(the subquery already filters by hidden etc.)
in practise, by time-smearing,
usually delta-chat avoids messages from the same device
having the same timestamp - however, this may not be true for multi-device
and/or read-receipts.
i have not seen this error all the years, however, it happens with
the async move several times - maybe because things are just sent faster
and things become more probabe.
Fix #1478
I changed my original plans a little because I had so many extra ideas and then sorted that I should rather look at actual NDNs and look what is necessary to parse them:
- Recognize NDNs by ~the sender address, which is in a regex the providers database. The problem with heuristics would be that someone could send fake-NDNs and mark messages as failed.~ the standard ("report/delivery-status") and heuristics ("subject contains 'fail' and sender contains 'daemon'"). If there is a valid Message-ID, then rely on that this is an NDN (of course, generally someone might try to find out a Message-ID and send a fake NDN).
- ~Look for `In-Reply-To`~ (only Gmail did this and Gmail uses rfc822 anyway.)
- ~Look for a mimepart `message/delivery-status`, which might contain a `X-Original-Message-ID`~ (only Gmail did this and Gmail uses rfc822, too, anyway.).
- Search through the body and look for a line `Message-ID: *` (remember to remove `<`, `>`), in the hope that that's the original header
- Look for a mime-part containing the string `rfc822`, which will contain the original header. Parse them with Mailparse and look for `Message-ID`.
CLOSE, which was used previously, only expunges messages and deselects
folder, and it should only be called if some folder is selected. For that,
Imap.close_folder() method is used.
This adds functionality to the cffi build script to also extract
defines so that we can ask the compiler to figure out what the correct
values are. To do this we need to be able to locate the header file
used in the first place, for which we add a small utility in the
header file itself guarded to only be compiled for this specific case.
Reply to group messages assigned to 1:1 chat on ac4 and see where they
end up on ac1 and ac2. Currently they contain group ID in Reply-To field
and go to group chat, so the test is failing.
The code in dc_receive_imf.rs looks a bit funny, an alternative would be a function:
fn upcate_chat_last_subject(context: &Context, chat_id: &ChatId, mime_parser: &mut MimeMessage) -> Result<()> {
let mut chat = Chat::load_from_db(context, *chat_id)?;
chat.param.set(Param::LastSubject, mime_parser.get_subject().ok_or_else(||Error::Message("No subject in email".to_string()))?);
chat.update_param(context)?;
Ok(())
}
get_rowid should not return 0, as we have inserted a row right above.
And using is_error() instead of comparing row_id to 0 is a strange way
to check this condition.
As all functions that actually returned 0 chat ID to indicate error have
been removed, the function is gone too.
Both methods do the same: compare chat_id to 0. However, in these cases
0 refers to the state when chat_id is not determined yet, because no
corresponding chat has been found.
All functions that returned 0 to indicate error have already been
resultified.
This uses the Fingerprint type more consistenly when handling
fingerprits rather then have various string representations passed
around and sometimes converted back and forth with slight differences
in strictness.
It fixes an important bug in the existing, but until now unused,
parsing behaviour of Fingerprint. It also adds a default length check
on the fingerprint as that was checked in some existing places.
Fially generating keys is no longer expensive, so let's not ignore
these tests.
the advanced options are not used anyway later,
but prevent imap/smtp connections from being altered.
nb: we want to stop altering when some advanced options
are entered, however, we want to do this probaby
not depending on autoconfig.
Fix#1474 "Sending message to contact with < or > in Recipient gets treated as "Sent" but is not received".
As I was at it, I also extracted the correct name and address from addresses like Mueller, Dave <dave@domain.com>.
This means all key conversions/serialisation/deserialisation can be
done with DcKey rather than Key. Also migrate all key conversion
tests to DcKey rather than Key.
This moves both the Keyring and the fingerprints to the DcKey trait,
unfortunately I was not able to disentangle these two changes. The
Keyring now ensures only the right kind of key is added to it.
The keyring now uses the DcKey::load_self method rather than
re-implement the SQL to load keys from the database. This vastly
simpliefies the use and fixes an error where a failed key load or
unconfigured would result in the message being treated as plain text
and benefits from the in-line key generation path.
For the fingerprint a new type representing it is introduced. The aim
is to replace more fingerpring uses with this type as now there are
various string representations being passed around and converted
between. The Display trait is used for the space-separated and
multiline format, which is perhaps not the most obvious but seems
right together with FromStr etc.
the document standards.md exist since a long time
to get an overview but also a nice reference to get some links.
however, its placement in the android-repo is a bit unlogical,
probably comes from a time where there was only one implementation :)
as ios and desktop use the same standards and as
all acutal implementations are in the core,
we move it to the core repo.
android can have a link to the new place.
journal_mode is persisted, it is sufficient to change it only for one handle.
with_init() is called for a bunch of handles directly on pool-creation,
so changing to WAL here easily results in busy-errors.
search for the sentbox in two passes:
- first check the folder attributes
- only if that fails, check for some known names
this way, the sent-attribute always has precedence
over the name; this was not the case before.
moreover, this fixes an possibly wrong early exist
when the attribute list is completely empty.
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.
* First try making get_recipients use MailHeader (nice and functional)
* Get it to compile by using not-so-functional style
* Add "empty-from" test, drop unnecessary check for error; continue using addrparse_header() instead of addrparse()
* Try to use functional style, unfortunately, I can't get the compiler to accept it
* Do it imperative-style: Do not overwrite To with Cc and vice versa
* Use addrparse_header() once more
* Still addrparse_header()
* Clippy
* Fix compile errors in tests
* Fix typo
* Fix tests again ;-)
* Code style
* Code style; try a HashMap<addr: String, display_name: String> as an address list but I am not convinced
* Code style; Use Vec<SingleInfo> as address list
* Clippy
* Add tests
* Add another test
* Remove stale comments
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.
these events take the message-id as parameter and might be used
to update an existing list (although to recommended)
if the event is issued for hidden messages,
this might led to "empty" messages flashing up -
the ui tries to get the message from the event,
after a moment, on the next update, the message disappears again
as hidden messages are of course not returned eg. by dc_get_chat_msgs().
the effect was probably always visible for secure-join-messages on ios,
however, become much more visible recently when read-receipts are added
as hidden messages as well (to make them auto-deletable).
the footer mark normally used in email-conversations is `-- `,
note the trailing space, see RFC 3676, §4.3
unfortunately, the final space is removed by some providers,
which lead to footers showing up on delta-to-delta-conversations
(on nondc-to-delta, this is not an issue as we cannot be sure anyway
and show a [...] therefore)
this change accepts lines with only `--` as a footer separator
if there is no other footer separator
and if the line before is empty and the line after is not.
as there is still some chance to remove text accidentally,
see tests, some protection against that is needed in another commit.
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.
This moves the loading of the keys from the database to the trait and
thus with types differing between public and secret keys. This
fetches the Config::ConfiguredAddr (configured_addr) directly from the
database in the SQL to simplify the API and consistency instead of
making this the responsiblity of all callers to get this right.
Since anyone invoking these methods also wants to be sure the keys
exist, move key generation here as well. This already simplifies some
code in contact.rs and will eventually replace all manual checks for
existing keys.
To make errors more manageable this gives EmailAddress it's own error
type and adds some conversions for it. Otherwise the general error
type leaks to far. The EmailAddress type also gets its ToSql trait impl
to be able to save it to the database directly.
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.
CString::yolo was still used in the ffi, this was an unsafe
transitional thing. To remove it there were two choices: 1. make
errors in creating CStrings hard errors or 2. try and be as lenient as
possible. Given the to_string_lossy() convention adopted in the ffi
this choose the lenient option and simply skips over embedded null
bytes, leaving the rest of the strings intact.
Thus now CString::new_lossy(). It's only used for .strdup() however
so no longer a public trait.
This also cleans up the public visibility of things in the strings.rs
file:
- Rename StrExt/OptStrExt traits to what they actually do: provide
.strdup() -> Strdup/OptStrdup.
- dc_strdup() should be an implementation detail, replace all usages
with Strdup.strdup() method.
- Only allow visibility inside the crate for all things.
- Reduce visibility to only the module for things not used in lib.rs.
after fixing some issues wrt ecc keys, see #1319,
and waiting some time (three core releases, two ios/android/desktop releases),
it is now the time to switch again to ecc keys again,
after the first attempt was stopped in #1319
before, the list was empty
and trying to send to groups that only contain SELF lead to a crash.
in theory, this happens for both, bcc_self enabled or not, however,
if bcc_self was disabled (default setting),
things worked as the whole mimerendering was skipped on a higher level.
also, the saved-messages-chat was not affected as this was checked explicitly.
this pr changes the mimerendering so that From: is used as To:
if there is no recipient-list and the messasge will be sent to SELF only.
the currently released versions fail sometimes in encrypting to ecc keys,
see #1313, the issue is about to be fixed,
however, we should not generate ecc keys until the
fix is rolled out - otherwise new users will get encryption errors every some
messages if their counterpart is not yet using the most recent version.
we can start generating ecc keys a few weeks after the fix is rolled out.
up to now, Chat-Group-Member-Added and -Removed commands
result in a complete recreation of the memberlist
by collecting all addresses from the From: and To: headers.
this easily results in missed and accidentally removed members,
esp. when several people at the same time scan a qr code to join a group.
this commit changes the behavior of adding members by
not removing members on the Chat-Group-Member-Added command.
instead the existing memberlist is conjuncted
with the memberlist seen in the message.
only adding the member from the Chat-Group-Member-Added
seems not to be sufficient - imaging a group of Alice and Bob:
- Alice adds Claire
- Bob adds Dave _before_ seeing that Alice added Claire
- Dave would never get the information that Claire is in the group
wrt Chat-Group-Member-Removed: this command
does no longer recreate the memberlist but just remove _exactly_ the member
mentioned in the header. there are situations, where a just removed member
will be readded by out-of-order-messages, however, compared to missed
members, this is seems to be acceptable - also as this is more visible
and easier to fix (just remove the member again).
might be that, in practise, this is not a big issue. while adding members
is typically done in masses on bootstraping a group,
this is typically not true for removing members.
Instead, use last_insert_rowid() function to find the row.
There is no race condition in using last_insert_rowid(), because
last_insert_rowid() returns row id last inserted in this connection. As
we hold the connection during the whole transaction, it is impossible
that some other thread will execute INSERT statement in parallel.
This commit is part of the effort to get rid of sql::get_rowid hack and
use transactions more for related SQL statements.
Existing public methods that use these functions, like sql::execute, are
only suitable for executing a single statement.
Sometimes it is useful to execute multiple statements within one
connection, for example to begin a transaction, execute mutliple SELECT
and INSERT queries and commit or rollback the whole transaction.
We already have a .strdup() method on AsRef<str>, this adds this
method also to an option of this. In case the option is None a NULL
pointer is returned.
This is done by using a new trait, as the type system otherwise
considers such an implementation conflicting with the existing one.
Now configure module is no longer public. Users should call
Context.configure() and Context.is_configured() methods.
Configure module is completely hidden from documentation unless
--document-private-items option is specified.
RFC 2183 specifically allows filenames to be specified for MIME parts
with "inline" Content-Disposition.
Previously we treated such attachments as an error, causing the whole
message parsing to fail. Now it is only an error if Content-Disposition
cannot be parsed.
MIME parts with filename are now considered to be attachments
regardless of their Content-Disposition type. However, "attachment"
Content-Disposition is still processed differently: we generate a
filename for it even if it is not specified.
I had a look for two mintues at converting things to .try_inner() and
I don't think this is currently worth the effort or would increase
readability a lot. So let's leave this for now.
There is no need to have both a .log_warn() and .log_err(), even their
names are confusing by now. Let's just have the most liberal one and
reduce one more thing we need to know about.
Also, these traits don't need to be pub.
Using peek_online_config() results in a message being sent to some
other account, used by previous test. If tests are run in parallel,
for example with pytest-xdist, we could be sending a message to a still
online DC client.
Envelope has the same Message-ID, but using other fields from the
envelope, such as From field, is error-prone. They may contain values
different from the message body. As we don't parse the envelope later on,
it is better not to fetch it during prefetch too.
This capability is not used by Delta Chat. Moreover, XLIST is deprecated
in favor of https://tools.ietf.org/html/rfc6154, which should be
supported instead. Delta Chat already looks for \Sent attribute in
get_folder_meaning().
- Python should raise exceptions on error. Not return False.
- Negative durations are nonense.
- ChatID validity is already checked by the Rust API, let's not duplicate.
Configuring an online account generates a key, we would like this
code-path tested too. So add some functionality to the AccountManager
to not use the pre-generated keys.
Because this slows down interactively running the tests by hand add an
ignored marker which only runs if --ignored is used. This name was
chosen because this matches the naming used by rust/cargo #[ignored].
The difference however is that --ignored on cargo *only* runs ignored
tests while here it runs *all* tests.
To ensure the ignored/slow tests are run on CI we add it as an
argument to the tox configuration, which is used by the CI to run the
tests.
This changes the AccountMaker to use pre-generated keys when
available, speeding up test runs.
As a side-effect we no longer need to compile the integration tests in
release mode with debug symbols. Losing debug symbols (-g) means
cargo no longer wants to recompile everything all the time too.
Tested locally and seems to works.
The imex code was deleting the key if it was already used. Turns out
none of the callers would not want this behaviour, so let's just
handle this case generally.
I guess this is a little neater. Note that this does change all the
existing error logging to warning logging. I believe this is correct
as these error log messages are really programming errors rather than
errors which need to be show to the user.
Also chose to make entire with_inner unsafe, there is little to be
gained from hiding the unsafe as this is only used from unsafe
functions in the first place.
The user-visible change here is that it allows the FFI API to save
keys in the database for a context. This is primarily intended for
testing purposes as it allows you to get a key without having to
generate it.
Internally the most important change is to start using the
SignedPublicKey and SignedPrivateKey types from rpgp instead of
wrapping them into a single Key object. This allows APIs to be
specific about which they want instead of having to do runtime checks
like .is_public() or so. This means some of the functionality of the
Key impl now needs to be a trait.
A thid API change is to introduce the KeyPair struct, which binds
together the email address, public and private key for a keypair.
All these changes result in a bunch of cleanups, though more more
should be done to completely replace the Key type with the
SignedPublicKye/SignedPrivateKey + traits. But this change is large
enough already.
Testing-wise this adds two new keys which can be loaded from disk and
and avoids a few more key-generating tests. The encrypt/decrypt tests
are moved from the stress tests into the pgp tests and split up.
This should prevent accidental sending of unencrypted messages when
parent_is_encrypted returns an error. For example, if the database is
busy due to other thread activity, parent_is_encrypted should not return
false. Instead, message sending job should retry later.
error!() will show the error directly to the user,
this is not useful in this case,
and also the message with the function-name is not for the end-user.
instead, the ui shall (and already does)
show some explaining text if dc_has_import() returns false;
the error!() is disturbing here as this results in two hints shown to the user.
this changes the behavior when scanning a setup-contact qr-code.
instead of waiting, until the whole protocol is finished,
which may take something between 10 seconds and several minutes,
the dc_join_secure_join() returns instantly;
the uis typically show the created chat then.
the returned chat-id is the same than if we wait for the protocol to finish,
it is the opportunistic one-to-one chat-id, so no changes there.
all this works even when both devices are offline.
after dc_join_secure_join() returns, however,
the usual setup-contact continues. ux-wise, once the protocol finishes,
a system-info-messages is added to the chat (also unchanged),
this is directly visible, in the chat as well as in the chatlist.
while the prococol runs, the user can alredy send message to the chat,
or do other things in the app.
if the user scans a new qr-code while an existing protocol is not finished yet,
the old join will be aborted (however, of course, created chats are kept).
we could also allow multiple joins at the same time,
however, this would be much more effort that this little change
and i am not sure if it is worth the effort.
finally, if a verified-group shall be joined,
this is not possible instantly, this is not affected by this pr.
same for unverified-groups, however, this could maybe be improved,
but also here, not sure if it is worth the effort
(i think most scans are setup-contact scans)
oauth2 crashes in beta23
because we did not let Serde remove the quotes from a parsed JSON email-address.
for autoconfig, we try to get a well-known URL
containing the domain of the used address - with the quote that is
https://autoconfig.gmail.com"/mail/config-v1.1.xml?...
unfortunately, instead of just returning an error,
(the url does not exist anyway)
reqwest crashes on the attempt to get this URL.
the Serde-thing is not obvious to me:
while serde_json::Value.as_str() removes the quotes,
serde_json::Value.to_string() does not.
.truncate() is not safe because it panics if string length does not
lie on character boundary. We convert the string to characters and take
first n character instead.
before a message is actually deleted,
we verify that server_folder+server_uid matches the Message-ID,
so that we do not delete the wrong message by accident.
the reason for that is that, to my knowledge, server_folder+server_uid
are not necessarily stable but Message-ID is.
anyway, this check was broken and set the server_uid to 0 in all cases -
where it should be set to 0 _only_ on mismatches.
As a result of job, other jobs can be added or deleted. To avoid
processing deleted jobs and to process other jobs in the correct order,
we should reload them after performing each job.
However, we don't use "LIMIT 1" in SQL queries, because we want to be
able to skip over invalid jobs, and checking if job is invalid can only
be done in Rust.
This may or may not send a combined MDN out. We don't test for it,
but the test ensures that *if combined MDNs are sent in this case*,
then we receive them correctly.
This return value was very complicated to understand. Some failure
returns were returned as Err and some as Ok with no consistency, but
resulting in the same behaviour.
This refactor makes the handle_securejoin_handshake the sole place
responsible for maintaining the state of the secure join
process (context.bob) and also in charge of terminating the ongoing
process. This is none of receive_imf's business.
The remaining returns are now cleanly classified in application-errors
and protocol errors:
Applications errors result in an Err and mean there is a bug or
something else serious went wrong, like database access suddenly
failed or so. In this case receive_imf is still responsible for
clearing the state and resetting ongoing-process. It may be possible
this should still be moved back to securejoin.rs so that recieve_imf
doesn't need to know anything about this either.
Protocol errors are not failures for receive_imf, it just means the
received message didn't follow the protocol. Receive_imf in this case
is told to ignore the message: that is hide it but not delete it.
Other Ok returns also only say what needs to happen to the message:
- It's fully processed and needs no further processing, instead should
be removed
- It should still be processed as a normal received message.
This changes some behaviour: if the chat creation/lookup for the
contact fails this is treated as an application error. Previously
this was silently ignored and send_msg() would be called with a 0
chat_id without checking the response. This resulted in the protocol
quitely being blocked.
This all shhould now make it easier to resultify more of the functions
called by this function, instead of having to deal with very
complicated application logic hidden in the return code.
this commit sets the subject of groups to the name of the group.
if the message is a reply in the group, also the prefix `Re:` is added.
the Chat: prefix is removed for groups,
also the Fwd: prefix, as it this would be expected to be set to the
group name of the forwarded message, which is not really compatible with the
rule "group-name = subject" (forwarded messages are detected by the body,
not by the subject)
rusqlite already checks that SQLite is safe to use in multi-threaded mode when it opens the database and returns rusqlite::Error::SqliteSingleThreadedMode otherwise.
Also create a common parent_query() function to make sure we use the
same message as a parent when determining if it is encrypted and when
actually replying to it.
The struct really represents a parsed MIME message and is not used as
a parser itself. After the from_bytes() call (which should arguably
use the FromStr trait instead) the struct is fully populated.
This is a new feature in Rust 1.40, it means users outside the crate
will not be able to create these structs, allowing us to add fields
without breaking the public API.
Normally it happens in addr_cmp function, but update_gossip_peerstates
forms a HashSet of addresses, so they should be lowercased beforehand.
Also adjust the mail_with_cc.txt to test for non-lowercase addresses.
According to Rust documentation, usize is "The pointer-sized unsigned
integer type".
This change removes unnecessary libc dependency and makes top_evil_rs
script happier.
Since stock string callback has been deprecated, all event callbacks
return 0.
For compatibility, C declarations are not changed and FFI users are
expected to return 0 from their callbacks.
in the very beginning, we allowed using the cmdline partly from the ui
via a special function; this made info!() handy.
however, this is long gone and no longer needed.
It was used when timeout was set on the whole smtp.send() operation.
Now only the operations inside smtp.send() can timeout, and such timeout
errors result in SendError, so SendTimeout is unused.
-Moved wheels installation below source installation and added comment that they are outdated and not working atm
-Updated source compilation/installation to a more step by step process as current one was outdated and not working due to Rust now needing nightly build else failing to compile (subtle v2.2.2 do not work without nightly)
This is the first experiment towards using structs to define the API.
It adds it as a new method on the existing Chat struct.
The types in this struct could improve as well as many other things.
But this is a straight forward translation of the existing json! macro
into a struct.
15 minute timeout was used because it applied to the whole send()
operation. Now timeout applies to each I/O operation, such as read()
or write(), so it can be made much shorter. In particular, this timeout
applies to read() call right after connection to plain or STARTTLS server,
in which case it is not reasonable to wait 15 minutes to receive one
line of data.
The timeout is triggered only if no progress is made within 30 seconds. It
likely indicates a network failure anyway.
* Remove Simplify structure.
* Match for lines starting with 5 markers, not consisting of exactly 5 markers.
This is a regression from C to Rust conversion, see
2bb1c280d5/src/dc_simplify.c (L154)
* Add tests.
we change the name on the wire as the old Chat-Group-Image header
could not be used on random mails, it was the marker for a "Changed" message,
if we would keep this names, things will fail for exising installations
as messages are dropped and a "Group image changed" message is shown instead.
* add-action-rs-clippy-action
just to try this action out
* add --all argument
* rm --all argument again
* add cargo check and fmt
* disable circle ci counterparts(fetch, clippy, fmt)
- recreate the group list more carefully, fixes#985
- resultify a few functions in the dc_receive pipeline
- don't quote displaynames in email-addresses, use utf8, preliminrarily addresses #976
This effectively reverts
https://github.com/deltachat/deltachat-core-rust/pull/964 for chat.rs,
which in that PR was thought to fix something. So maybe something is
still broken? But after improving tests the previous code seems to be
correct.
- Update Python bindings to not always use dc_prepare_msg path when
sending messages with attachements. When using dc_prepare_msg the
blobs need to be created in the blobdir since they will not get
copied and many tests where not doing this.
- Add a test that ensures that calling dc_prepare_msg with a
file **not** in the blobdir fails.
- Add a test that ensures that calling dc_send_msg directly with a
file **not** in the blobdir copies the file to the blobdir. This
test cheats a little by knowing what the filename in the blobdir
will be which is implementation-dependent and thus a bit brittle.
But for now it proves correct behaviour so let's go with this.
- Improve the test_forward_increation test to ensure that the
in-creation file only has it's final state before calling
dc_send_msg. This checks the correct file data is sent out and not
the preparing data, this fails with the chat.rs changes in
#964 (reverted here to make this work again). Also fix the test to
actually create the in-creation file in the blobdir.
- Fix test_send_file_twice_unicode_filename_mangling to not use
in-creation. It was not creating it's files in the blobdir and that
is an error when using in-creation and it didn't seem it was trying
to test something about the in-creation logic (which is tested in
test_increation.py already).
- Fix Message._msgtate code which presumably was not used before?
- Rename `BlobObject::create_from_path` to
`BlobObject::new_from_path`. All the `BlobObject::create*` calls
now always create new files which is much more consistent. APIs
should do what is obious.
Rustls does not offer a documented way to accept valid certificates with
invalid hostnames. Implementation of certificate verification in Rustls
does not have a public API and reimplementing it is error-prone.
Previously, if any of a chat's peers set prefer_encrypt to false
(i.e. "e2ee_enabled=0" in the config, a misnomer btw) then a
previously encrypted chat would drop to cleartext easily.
eg. android relies on that and fallsback to wrong aspect ratios otherwise.
also, this makes job.rs a little more readable
as some things are moved to message.rs :)
This deletes a lot of code and complexity. Though comes at some cost:
- The type no longer fits in a register and will always be on the
stack.
- Constructing the errors is more verbose, no more auto Into casting.
this reverts the logical changes done in #811
but keeps the improvements done later eg. in #911.
the reason for the revert is that it is too hard to
find a started draft in a larget chatlist.
also the shown date would not be just descending.
Reset is an internal value that received messages should not be able to set.
Also return an error on any value other than "mutual" and "nopreference", errors are converted to NoPreference by the caller.
The ongoing process of dc_join_securejoin() was stopped before the
corresponding chat was created. This resulted in a race-condition
between the sqlite threads executing the creation and query
statements, thus sometimes the query would not find the group and
mysteriously fail.
Tripple-programming with hpk & r10s.
Be more defensive: if somehow we got corrupt jobs in the database skip
over them rather than fail to do anything.
This only modifies the query_map() call, the rest is only split off
into it's own function to make it testable. Smaller functions are
good anyway.
When a new Selfavatar is set the file needs to be copied into the
blobdir and as a proper blob it should be stored in the database as
$BLOBDIR/$filename.
This should fix#868.
First, try to use subkeys, because they are usually
short-term encryption keys. If none of the subkeys
are encryption keys, try to use the primary key.
rPGP is updated to the master branch because the
latest release does not have .is_encryption_key() yet.
Double extensions are sometimes used to identify files correctly,
e.g. .tar.gz or .html.zip. Breaking those extensions is not very
nice.
This fixes#865.
if two messages have the same time,
this results i all kinds of sorting failures,
esp. in non-delta-muas and on forwarding messages.
so, no two messages sent out from delta have the same timestamp.
normally, this is no problem, but when things are sent too fast,
eg. on forwarding, we lend us some time from the future.
however, all this did not work
because we forgot to write back the modified time,
this is fixed by this commit, as well as some cleanup.
resorting the chatlist on changing drafts has some ux issues.
eg. when the chatlist is visible together with the input field,
if may come to flickering resorting during input
or to a resorting just when the user leave the chat
as this might trigger set_draft().
but also on mobiles, the resorting is visible and a bit unexpected.
also it is unclear what happens when a chat with a draft is entered
and left without modifications.
the solution proposed here is to ignore draft on sorting
while still showing them in the chatlist
if they're newer as the last message.
a possible disadvantage is
that the date for the chat with a draft does not follow the ordering
(the ordering is by the last message),
however, the date is not shown as a "primary sort" criterion or so,
so it might be that this is completely okay.
also, of course, it affects only draft :)
the point of this pr is to get an overview
how and where DC_CONTACT_ID_DEVICE is used,
to prepare introducing a device-"chat".
i did not change the sql statements for now
as this would require some more refactoring
and has the potential to introduce bugs.
Before we created an empty file and asked the OS to copy the file.
The OS is very good at this so this is a good idea generally. However
it seems that in some cases, possibly an Android Dowload folder, we
might be able to create a file but not overwrite it. Thus refactor
this a bit so we are copying the file ourselves.
There are no new tests here since the behaviour remains identical.
The good news is that the existing tests were good enough to catch
some bugs already.
the error led to unusable contact requests,
at least on android and ios (probably also desktop)
because msg_id=dc_chatlist_get_msg_id() always returns 0
and create_chat_by_msg_id(msg_id)
or dc_marknoticed_contact(<get sender from msg_id>)
failed therefore.
This more strongly types the ubiquitous message id type by no longer
making it an integer. It keeps the actual ID opaque. Only for the
generic job API the number keeps being used. Some locations also need
to create it from an integer and call MsgId::new().
Turns out that anyone that uses these either justs wants a file or
wants a blob. Consolidate those patterns into one place and simplify
all the callers.
This creates a specific type for blobs, with well defined conversions
at the borders. It also introduces a strong type for the Param::File
value since that param is often used used by the public API to set
filenames using absolute paths, but then core changes the param to a
blob before it gets to the database.
This eliminates a few more functions with very mallable C-like
arguments behaviour which combine a number of operations in one.
Because blob filenames are stored so often in arbitrary strings this
does add more code when receiving those, until the storage is fixed.
File name sanitisation is now deletated to the sanitize-filename crate
which should do a slightly better job at this.
Previously, "flags" argument of Sql.open was of type libc::c_int, but
only one bit was used: whether to open database read-only. This commit
makes it explicit by changing type to bool and renaming argument.
if the past we had lots of crashes because of unexpected unwrap failures,
mostly related to string.
this commit avoids them eg. for string-conversions that may panic
eg. when encountering a null-byte or by logical programming errors
where an object is assumed to be set but is not under unexpected circumstances.
- increase the number of simultan database-connections handled by the r2d2 pool.
currently we have already at least 5 threads threads,
but also the ui may call from any thread.
- the busy-timeout for all connections is set to 10 seconds.
this means, if a connection-A wants to write,
but connection B-is already writing,
connection-A waits multiple times a few ms and tries over.
this is repeated until the 10 seconds are accumulated.
contact-requests of non-blocked senders are shown in the chatlist,
so that the user gets aware of them without opening the contact-request-chat.
however, for that, the contact-request virtual-chat-id
must be added to the beginning of the list,
otherwise it won't get noticed by the user.
* add sticker type
this pr adds the message type 'sticker'.
stickers are handled as normal images
but tagged with the header `Chat-Content: sticker`
it's up to the ui to render these stickers appropriate.
* cargo fmt
there are 3 key blobs in the database, gossip_key, public_key and verified_key.
the verification_key should not change if, for any reasons,
the public_key or the gossip_key changes.
Since Rust strings operations are assumed to never fail, this commit
removes a lot of checking, whether appending to mmapstring fails. Now it
is Rust runtime burden.
core-c has truncated messages in the contact requests.
this is questionable in general, as
- all messages, including contact requests,
are already truncated, unquoted, simplified etc.
- the ui should be capable of showing the full text anyway
(when the contact request is accepted, the whole messase is shown)
- also, all current ui show the contact requests by name only in the
chatlist; the user often does not even come to the contact request view.
- if the ui wants to show the contact request is a special way,
it is probably better to leave this truncation up to the ui
There is very little API guarantees about this, but clients seem to
expect *something* to work on a closed context. So split this up into
static info an more dynamic context-related info, but let's not
provide any guarantees about what keys are available when.
Fixes#599
Function "quote_word" accepts display charset argument, but on only call
site it is string constant. Change function to always use "utf-8"
display charset, and remove useless argument.
Note: I strongly suggest reviewing this commit in side-by-side mode.
Note: This commit fails CI due incorrect formatting. It is done
deliberately to simplify review process.
Previously, "set_draft_raw" function was used with "msg = None" only for
side-effect of removing current draft message in chat.
After draft removal functionality was factored into separate
"maybe_delete_draft" function, it is used directly in only call site,
which used to invoke "set_draft_raw" with optional message.
This function is private, and this refactoring does not change FFI
interface.
Note: This commit fails CI due incorrect formatting. It is done
deliberately to simplify review process.
* src/dc_mimefactory.rs(new): add factory method to have verbose
initialization of all (more than 10) MimeFactory fields only in one place.
* src/dc_mimefactory.rc(dc_mimefactory_load_msg, dc_mimefactory_load_mdn):
simplify code (and reduce linecount) using Mimefactory::new
* src/dc_mimefactory.rs(MimeFactory): change type of `loaded` field
* src/dc_mimefactory.rs(Loaded): new enum, describing possible
values of `loaded` field of `MimeFactory` structure
* src/dc_mimefactory.rs(dc_mimefactory_loaded_t): remove unused type alias
* src/job.rs(add_smtp_job): adjust call site by removing multiple casts
* src/dc_mimefactory.rs(dc_mimefactory_render): ditto
Replace named constants with enum to improve type-safety and make
exhausiveness checks possible.
Note, that since this enum never pass FFI border, its numeric values
does not need to be specified explicitly and can be left on compiler's
discretion.
Previously, this function accepted both key id (integer) and is_default
(boolean). If `is_default` flag was set, value `id` parameter wasn't
used. This commit compresses two argument into single `id: Option<i64>`.
For consistency with other tests that use example public and private
keys, replace use of `concat!` macro with `include_str!`. This way, key
data embedded into source with single line of code.
(@dignifiedquire and @hpk42)
- introduce rust-caching to python test runs
- skip release and ffi runs, they are check using python bindings
- shuffle files such that ci_scripts/ contains all the ci scripts
- partly parallelize python tox runs
as c is top-down, we start with the typedefs
so that functions can use them freely.
after that, the functions are declared
and finally the #defines (for less noise in the function sections).
grouping is done by classes.
A lot of work from @Hocuri and @Simon-Laux mostly.
This exposes the API of the deltachat-provider-overview crate on the
deltachat FFI API, allowing clients to use it to help users set up
their accounts.
Previously, `dc_get_oauth2_access_token` accepted "flags" argument,
that actually had only one possible field: 0x1 == DC_REGENERATE.
This change replaces "flags" argument with single boolean argument
"regenerate".
Current commit on deltachat/deltachat-core: `12ef73c8e76185f9b78e844ea673025f56a959ab`.
## Installing Rust and Cargo
To download and install the official compiler for the Rust programming language, and the Cargo package manager, run the command in your user environment:
```
curl https://sh.rustup.rs -sSf | sh
$ curl https://sh.rustup.rs -sSf | sh
```
## Using the CLI client
Compile and run Delta Chat Core using `cargo`:
Compile and run Delta Chat Core command line utility, using `cargo`:
```
cargo run --example repl -- /path/to/db
$ RUST_LOG=info cargo run --example repl --features repl -- ~/deltachat-db
```
where ~/deltachat-db is the database file. Delta Chat will create it if it does not exist.
Configure your account (if not already configured):
@@ -89,6 +88,16 @@ $ cargo test --all
$ cargo build -p deltachat_ffi --release
```
## Debugging environment variables
-`DCC_IMAP_DEBUG`: if set IMAP protocol commands and responses will be
printed
-`DCC_MIME_DEBUG`: if set outgoing and incoming message will be printed
-`RUST_LOG=info,async_imap=trace,async_smtp=trace`: enable IMAP and
SMTP tracing in addition to info messages.
### Expensive tests
Some tests are expensive and marked with `#[ignore]`, to run these
@@ -101,9 +110,29 @@ $ cargo test -- --ignored
-`vendored`: When using Openssl for TLS, this bundles a vendored version.
-`nightly`: Enable nightly only performance and security related features.
-`ringbuf`: Enable the use of [`slice_deque`](https://github.com/gnzlbg/slice_deque) in pgp.
d="M 13.5,7.5 V 39 h 0.08654 L 22.533801,29.370239 31.482419,39 h 0.01758 V 7.5 Z m 9.004056,4.108698 1.879508,4.876388 5.039514,0.359779 -3.879358,3.363728 1.227764,5.095749 -4.276893,-2.796643 -4.280949,2.788618 1.237229,-5.093073 -3.873949,-3.371754 5.040866,-0.350417 z"
For reference, please see https://github.com/deltachat/deltachat-core-rust/blob/master/spec.md#add-and-remove-members how MemberAdded/Removed messages are shaped.
- All Chat-Group-Member-Added/Removed messages are recorded in their
full raw (signed and encrypted) mime-format in the DB
- If an incoming member-add/member-delete messages has a member list
which is, apart from the added/removed member, not consistent
with our own view, broadcast a "Chat-Group-Member-Correction" message to
all members, attaching the original added/removed mime-message for all mismatching
contacts. If we have no relevant add/del information, don't send a
correction message out.
- Upong receiving added/removed attachments we don't do the
check_consistency+correction message dance.
This avoids recursion problems and hard-to-reason-about chatter.
Notes:
- mechanism works for both encrypted and unencrypted add/del messages
- we already have a "mime_headers" column in the DB for each incoming message.
We could extend it to also include the payload and store mime unconditionally
for member-added/removed messages.
- multiple member-added/removed messages can be attached in a single
correction message
- it is minimal on the number of overall messages to reach group consistency
(best-case: no extra messages, the ABCD case above: max two extra messages)
- somewhat backward compatible: older clients will probably ignore
messages which are signed by someone who is not the outer From-address.
- the correction-protocol also helps with dropped messages. If a member
did not see a member-added/removed message, the next member add/removed
message in the group will likely heal group consistency for this member.
- we can quite easily extend the mechanism to also provide the group-avatar or
other meta-information.
Discussions of variants
++++++++++++++++++++++++
- instead of acting on MemberAdded/Removed message we could send
corrections for any received message that addresses inconsistent group members but
a) this would delay group-membership healing
b) could lead to a lot of members sending corrections
- instead of broadcasting correction messages we could only send it to
the sender of the inconsistent member-added/removed message.
A receiver of such a correction message would then need to forward
the message to the members it thinks also have an inconsistent view.
This sounds complicated and error-prone. Concretely, if Alice
receives Bob's "Member-added: Doris" message, then Alice
broadcasting the correction message with "Member-added: Carol"
would reach all four members, healing group consistency in one step.
If Bob meanwhile receives Alice's "Member-Added: Carol" message,
Bob would broadcast a correction message to all four members as well.
(Imagine a situation where Alice/Bob added Carol/Doris
while both being in an offline or bad-connection situation).
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 03cab93c6d1f3a8245f63cf84dacb307944294fe6333c1e38f078a6600659c7a # shrinks to data = "a\t0aA\ta\t0 \ta\t0 \ta a\t\ta A\tAA0a0a 0\t a\t aA \t a\t A0\t AAa\taA0\taAAaA\t0\taa0a\ta Aa Aaaa A0A\t a aA 0\t A\t0\t0\t\t\t\t\t\tA \t\t a\tA Aa aAA0A0AA0aaA A\t\t aa0\ta\t \tAa\taA\t00 AA A a\tA a aAAa \t 00\t0 \t\t a A 0\t\t\t aAA Aa \taAAAA0a A0A\t\t1\\E$\t$R\tc\t^=\t\"\tQ<Uk\t\t>A\t\t&\t}v&\tM^\'|\tW5?dn\t\t+\t\tP\te`\t\t>:Brlq--?\t$#Q\tK=zJ\tb\"9*.\"\t`\tF&T*\tBs,\tg\'*\\\t:\t?l$\t\t|A\"HR:Hk\t\\KkV\t\t{=&!^e%:|_*0wV\t[$`\t:\t$%f\t\t[!\"Y. \tP\t\th\'?\'/?%:++NfQo#@\"+?\t(\\??{\t\'\'$Dzj\t0.?{s4?&?Y=/yj]Z=\t4n\t?Ja\"\t{I\t$\t;I}_8V\t&\t?N\'\tI2/\t9.\tFT%9%`\'\tz\to7Y\t|AXP&@G12g\t\'w\t\t%??\t\"h$?F\"\"6%q\\\\{\tT\t\"]$87$}h\'\t<\t$\tc%U:mT2:<v\t#Rl!;U\t\t\"^D\tRZ(BZ{n\t%[$fgH`\t{B}:*\t\t%%*F`%W\t//B}PQ\t\tsu2\tLz<1*!p-X\tnKv&&0\thm4<n\\.\\/.w\'\t<)E1g3#ood\t`?\t\\({N?,8_?h\ty\t0%\t*$A\t\t*w-ViQUj\tTiH\t%\t%&0p\'\'\tA%r**Fo\'Z\\\tNI*ely4=I?}$.o`\t$\ts\'<\t\",:~=Nv/0O%=+<LS\t%P\'\t$r%d.\t{G{/L:\t&I&8-`cy*\"{\t/%fP9.P<\t\t\'/`\t\t`\t\t`!t:\t::\t\tW\'X^\t@.uL&a\tN\t\t\t.\t?0*\tvUK>UJ\\\tQbj%w]P=Js\t\"R\t&s^?</=%\t\'VI:\" kT`{b*<\t\tF&?Y\t\t:/\t!C\'e0`\t\t\tx-\t*\\N\\wwu.I4\tb/y\t\"P:P%\"\t\tQ][\\\t^x\t\t):\t\t&s\t$1-\t\t\tXt`0\t;\t/UeCP*\"G\t\t\':\tk@91Hf&#\t(Uzz&`p2;\t{]\t\"I_%=\\%,XD\"\'06QfCd<;$:q^\t8:\"*\"H\t\to\t&xK/\t\ty0/<}<j<|*`~::b\t=S.=}=Ki\t<Y.\'{\tf\t{Ub*H%(_4*?*\tn2\t/\'\t\t\t/,4]\tt\t<y\t\t\tWi\t\tT&\"\t\t\t\t\t=/1Wu?\t\'A\"W-P\t$?e\\\t`\t6`vD\t8`\t\tccD J\tY&jI//?_\t\\j\t_\tsiq$\t?9\tQ\t.^%&..?%Jm??A%+<\tN&*\t.g\tS$W\"\"\tMpq\t\t:&\\\thTz&<iz%/%T&\'F\t\\]&\t\t}\t\t\tXr=dtp`:+<,\t%60Y*<(&K*kJ\todO\t=<V?&\tMU/\"\t= Y!)<\tV\t9\t)\t&v8q{\t\t&pT\t3\ttB,qcq\'i$;gv%j_%M_{[\"&;\t\t\t.B;6Y\\%\t\"\tY/a\t\\`:?\t<\t?]\taNwD;\\\t%l*74%5T?QS :~yR/E*R\t\t=u\t\\\t\t.Q<;\\\t_S/{&F$^\tw_>\'h=|%\t\t:W!\\<U2\'$\tb&`\t=|=L9\t\t\t\\WZ:! }{\t ;\t;\t\t 0.*\t.%\"\'r%{<Mh_t[[}\t-\tJo\"b/AC*-=`=T\tz$2\tC\t\t/k{47\"\t\t,q%\tZ\tT3\t\tf>%\t\'?%@^tx\t7\"1Bk{b{n\t\"Pj3\tHc\t\tt\tY<\t#?\tSh\\yk/N\\\t8 7=R4*9Cw&m\t\\-\'f\t|\'#t(Etu.Hdu(E\t%&v:\'aqW~A5\t\t w.s{J%lX<\"\t\'*%m<&:/B<&\':U}$&`.{)\t\t6S\t:/$*kQ-Z\t^\'t${/tH*\'v\t3\t=\t\tDyp:B\t`I_R&4SO\t\t&-j=*.\t87&\'e*( \t\t\t\'<$\\DJ<$p?{}\'&\tv\t\\Xk<Y:Y`!$K{\tF&\tzd\t\t*i$\tj\'\t<)R*\t%?\t!.\t=\"@#~:=*\t\tXO=_T,1\"\'.%%\"`{\\:\t\"\tfkeOb/\'$I~\ta\t|&\t[\\KK\"1&Z\t<k\t\t)%\'-~\"2n\tj\tW?*<@w{g%d\ta\\\'\'I\t;:ySR%ke:4\tc\t$=\t&9P]x4\tJ=\t6C6%a\t`0\tF\tm-\tTr\t}\t\tQum\t&@\typ|w2&\t\t3`i&t\t\tT5\"\t.&b&e*/==1.\'*\\[U*\tqPL%?$-0/}~|q`\t\t}\t$\tq==o+T$\'!H\t\ti&um\"?\"%%\t/\'p\tg>?{0{J{\t\t/\t\t{zKZ&>=\t[\"1h<H%z/8,/]s\tv{7\t\t:j*H,M//\t\t\td\'.)\t"
Meta data (at least the subject and all chat-headers) SHOULD be encrypted by the [Memoryhole](https://github.com/autocrypt/memoryhole) standard.
If Memoryhole is not used, the subject of encrypted messages SHOULD be replaced by the string
`Chat: Encrypted message` where the part after the colon MAY be localized.
Meta data (at least the subject and all chat-headers) SHOULD be encrypted
by the [Protected Headers](https://tools.ietf.org/id/draft-autocrypt-lamps-protected-headers-02.html) standard.
# Outgoing messages
Messengers MUST add a `Chat-Version: 1.0` header to outgoing messages.
For filtering and smart appearance of the messages in normal MUAs,
the `Subject` header SHOULD start with the characters `Chat:` and SHOULD be an excerpt of the message.
the `Subject` header SHOULD be `Message from <sender name>`.
Replies to messages MAY follow the typical `Re:`-format.
The body MAY contain text which MUST have the content type `text/plain`
@@ -41,29 +49,34 @@ The text MAY be divided into a user-text-part and a footer-part using the
line `-- ` (minus, minus, space, lineend).
The user-text-part MUST contain only user generated content.
User generated content are eg. texts a user has actually typed or pasted or
forwarded from another user.
User generated content are eg. texts a user has actually typed
or pasted or forwarded from another user.
Full quotes, footers or sth. like that MUST NOT go to the user-text-part.
From: sender@domain
To: rcpt@domain
Chat-Version: 1.0
Content-Type: text/plain
Subject: Chat: Hello ...
Subject: Message from sender@domain
Hello world!
# Incoming messages
The `Chat-Version` header MAY be used to detect if a messages comes from a compatible messenger.
The `Chat-Version` header MAY be used
to detect if a messages comes from a compatible messenger.
The `Subject` header MUST NOT be used to detect compatible messengers, groups or whatever.
The `Subject` header MUST NOT be used
to detect compatible messengers, groups or whatever.
Messenger SHOULD show the `Subject` if the message comes from a normal MUA together with the email-body.
The email-body SHOULD be converted to plain text, full-quotes and similar regions SHOULD be cut.
Messenger SHOULD show the `Subject`
if the message comes from a normal MUA together with the email-body.
The email-body SHOULD be converted
to plain text, full-quotes and similar regions SHOULD be cut.
Attachments SHOULD be shown where possible. If an attachment cannot be shown, a non-distracting warning SHOULD be printed.
Attachments SHOULD be shown where possible.
If an attachment cannot be shown, a non-distracting warning SHOULD be printed.
# Forwarded messages
@@ -90,21 +103,27 @@ which SHOULD be anonymized or just a placeholder.
Hello world!
Incoming forwarded messages are detected by the header.
The messenger SHOULD mark these messages in a way that it becomes obvious
that the message is not created by the sender.
Note that most messengers do not show the original sender with forwarded messages
The messenger SHOULD mark these messages in a way that
it becomes obvious that the message is not created by the sender.
Note that most messengers do not show the original sender of forwarded messages
but MUAs typically expose the sender in the UI.
# Groups
Groups are chats with usually more than one recipient, each defined by an email-address.
Groups are chats with usually more than one recipient,
each defined by an email-address.
The sender plus the recipients are the group members.
All group members form the member list.
To allow different groups with the same members, groups are identified by a group-id.
The group-id MUST be created only from the characters `0`-`9`, `A`-`Z`, `a`-`z``_` and `-`.
To allow different groups with the same members,
groups are identified by a group-id.
The group-id MUST be created only from the characters
`0`-`9`, `A`-`Z`, `a`-`z``_` and `-`
and MUST have a length of at least 11 characters.
Groups MUST have a group-name. The group-name is any non-zero-length UTF-8 string.
Groups MUST have a group-name.
The group-name is any non-zero-length UTF-8 string.
Groups MAY have a group-image.
@@ -113,57 +132,86 @@ Groups MAY have a group-image.
All group members MUST be added to the `From`/`To` headers.
The group-id MUST be written to the `Chat-Group-ID` header.
The group-name MUST be written to `Chat-Group-Name` header (the forced presence of this header makes it easier to join a group chat on a second device any time).
The group-name MUST be written to `Chat-Group-Name` header
(the forced presence of this header makes it easier
to join a group chat on a second device any time).
The `Subject` header of outgoing group messages SHOULD start with the characters `Chat:` followed by the group-name and a colon followed by an excerpt of the message.
The `Subject` header of outgoing group messages
SHOULD be set to the group-name.
To identify the group-id on replies from normal MUAs, the group-id MUST also be added to
the message-id of outgoing messages. The message-id MUST have the
format `Gr.<group-id>.<unique data>`.
To identify the group-id on replies from normal MUAs,
the group-id MUST also be added to the message-id of outgoing messages.
The message-id MUST have the format `Gr.<group-id>.<unique data>`.
From: member1@domain
To: member2@domain, member3@domain
Chat-Version: 1.0
Chat-Group-ID: 1234xyZ
Chat-Group-ID: 12345uvwxyZ
Chat-Group-Name: My Group
Message-ID: Gr.1234xyZ.0001@domain
Message-ID: Gr.12345uvwxyZ.0001@domain
Subject: Chat: My Group: Hello group ...
Hello group - this group contains three members
Messengers adding the member list in the form `Name <email-address>` MUST take care only to spread the names authorized by the contacts themselves.
Otherwise, names as _Daddy_ or _Honey_ may be spread (this issue is also true for normal MUAs, however, for more contact- and chat-centralized apps
Messengers adding the member list in the form `Name <email-address>`
MUST take care only to distribute the names authorized by the contacts themselves.
Otherwise, names as _Daddy_ or _Honey_ may be distributed
(this issue is also true for normal MUAs, however,
for more contact- and chat-centralized apps
such situations happen more frequently).
## Incoming group messages
The messenger MUST search incoming messages for the group-id in the following headers: `Chat-Group-ID`,
The messenger MUST search incoming messages for the group-id
in the following headers: `Chat-Group-ID`,
`Message-ID`, `In-Reply-To` and `References` (in this order).
If the messenger finds a valid and existent group-id, the message SHOULD be assigned to the given group.
If the messenger finds a valid but not existent group-id, the messenger MAY create a new group.
If no group-id is found, the message MAY be assigned to a normal single-user chat with the email-address given in `From`.
If the messenger finds a valid and existent group-id,
the message SHOULD be assigned to the given group.
If the messenger finds a valid but not existent group-id,
the messenger MAY create a new group.
If no group-id is found,
the message MAY be assigned
to a normal single-user chat with the email-address given in `From`.
## Add and remove members
Messenger clients MUST construct the member list from the `From`/`To` headers only on the first group message or if they see a `Chat-Group-Member-Added` or `Chat-Group-Member-Removed` action header.
Both headers MUST have the email-address of the added or removed member as the value.
Messenger clients MUST NOT construct the member list on other group messages (this is to avoid accidentally altered To-lists in normal MUAs; the user
does not expect adding a user to a _message_ will also add him to the _group_ "forever").
Messenger clients MUST init the member list
from the `From`/`To` headers on the first group message.
When a member is added later,
a `Chat-Group-Member-Added` action header must be sent
with the value set to the email-address of the added member.
When receiving a `Chat-Group-Member-Added` header, however,
_all missing_ members the `From`/`To` headers has to be added.
This is to mitigate problems when receiving messages
in different orders, esp. on creating new groups.
To remove a member, a `Chat-Group-Member-Removed` header must be sent
with the value set to the email-address of the member to remove.
When receiving a `Chat-Group-Member-Removed` header,
only exaxtly the given member has to be removed from the member list.
Messenger clients MUST NOT construct the member list
on other group messages
(this is to avoid accidentally altered To-lists in normal MUAs;
the user does not expect adding a user to a _message_
will also add him to the _group_ "forever").
The messenger SHOULD send an explicit mail for each added or removed member.
The body of the message SHOULD contain a localized description about what happened
The body of the message SHOULD contain
a localized description about what happened
and the message SHOULD appear as a message or action from the sender.
From: member1@domain
To: member2@domain, member3@domain, member4@domain
Chat-Version: 1.0
Chat-Group-ID: 1234xyZ
Chat-Group-ID: 12345uvwxyZ
Chat-Group-Name: My Group
Chat-Group-Member-Added: member4@domain
Message-ID: Gr.1234xyZ.0002@domain
Message-ID: Gr.12345uvwxyZ.0002@domain
Subject: Chat: My Group: Hello, ...
Hello, I've added member4@domain to our group. Now we have 4 members.
@@ -173,10 +221,10 @@ To remove a member:
From: member1@domain
To: member2@domain, member3@domain
Chat-Version: 1.0
Chat-Group-ID: 1234xyZ
Chat-Group-ID: 12345uvwxyZ
Chat-Group-Name: My Group
Chat-Group-Member-Removed: member4@domain
Message-ID: Gr.1234xyZ.0003@domain
Message-ID: Gr.12345uvwxyZ.0003@domain
Subject: Chat: My Group: Hello, ...
Hello, I've removed member4@domain from our group. Now we have 3 members.
@@ -190,16 +238,17 @@ with the value set to the old group name to all group members.
The new group name goes to the header `Chat-Group-Name`.
The messenger SHOULD send an explicit mail for each name change.
The body of the message SHOULD contain a localized description about what happened
The body of the message SHOULD contain
a localized description about what happened
and the message SHOULD appear as a message or action from the sender.
From: member1@domain
To: member2@domain, member3@domain
Chat-Version: 1.0
Chat-Group-ID: 1234xyZ
Chat-Group-ID: 12345uvwxyZ
Chat-Group-Name: Our Group
Chat-Group-Name-Changed: My Group
Message-ID: Gr.1234xyZ.0004@domain
Message-ID: Gr.12345uvwxyZ.0004@domain
Subject: Chat: Our Group: Hello, ...
Hello, I've changed the group name from "My Group" to "Our Group".
@@ -208,23 +257,27 @@ and the message SHOULD appear as a message or action from the sender.
## Set group image
A group MAY have a group-image.
To change or set the group-image, the messenger MUST attach an image file to a message and MUST add the header `Chat-Group-Image` with the
value set to the image name.
To change or set the group-image,
the messenger MUST attach an image file to a message
and MUST add the header `Chat-Group-Avatar`
with the value set to the image name.
To remove the group-image, the messenger MUST add the header `Chat-Group-Image: 0`.
To remove the group-image,
the messenger MUST add the header `Chat-Group-Avatar: 0`.
The messenger SHOULD send an explicit mail for each group image change.
The body of the message SHOULD contain a localized description about what happened
The body of the message SHOULD contain
a localized description about what happened
and the message SHOULD appear as a message or action from the sender.
The image format SHOULD be image/jpeg or image/png. Note that `Chat-Profile-Image` may appear together with all other headers, eg. there may be a
`Chat-Profile-Image` and a `Chat-Group-Image` header in the same message. To save data, it is RECOMMENDED to add a `Chat-Profile-Image` header only on image changes.
The image format SHOULD be image/jpeg or image/png.
Note that `Chat-User-Avatar` may appear together with all other headers,
eg. there may be a `Chat-User-Avatar` and a `Chat-Group-Avatar` header
in the same message.
To save data, it is RECOMMENDED to add a `Chat-User-Avatar` header
Messengers SHOULD use the header `Chat-Predecessor` instead of `In-Reply-To` as
the latter one results in infinite threads on typical MUAs.
Messengers SHOULD use the header `In-Reply-To` as usual.
Messengers SHOULD add a `Chat-Voice-message: 1` header if an attached audio file is a voice message.
Messengers SHOULD add a `Chat-Voice-message: 1` header
if an attached audio file is a voice message.
Messengers MAY add a `Chat-Duration` header to specify the duration of attached audio or video files.
Messengers MAY add a `Chat-Duration` header
to specify the duration of attached audio or video files.
The value MUST be the duration in milliseconds.
This allows the receiver to show the time without knowing the file format.
Chat-Predecessor: foo123@domain
In-Reply-To: Gr.12345uvwxyZ.0005@domain
Chat-Voice-Message: 1
Chat-Duration: 10000
Messengers MAY send and receive Message Disposition Notifications (MDNs, [RFC 8098](https://tools.ietf.org/html/rfc8098), [RFC 3503](https://tools.ietf.org/html/rfc3503))
using the `Chat-Disposition-Notification-To` header instead of the `Disposition-Notification-To` (which unfortunately forces many other MUAs to send weird mails not following any
standard).
Messengers MAY send and receive Message Disposition Notifications
using the `Chat-Disposition-Notification-To` header
instead of the `Disposition-Notification-To`
(which unfortunately forces many other MUAs
to send weird mails not following any standard).
## Sync messages
If some action is required by a message header, the action should only be performed if the _effective date_ is newer than the date the last action was performed.
If some action is required by a message header,
the action should only be performed if the _effective date_ is newer
than the date the last action was performed.
We define the effective date of a message as the sending time of the message as indicated by its Date header,
We define the effective date of a message
as the sending time of the message as indicated by its Date header,
or the time of first receipt if that date is in the future or unavailable.
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.