-
-
Notifications
You must be signed in to change notification settings - Fork 110
feat: allow adding second transport #7348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a0f8c49
4d4d939
9f7162a
8e15a94
532d6f2
12dc8d2
001a8a2
12cdbec
81d2d52
45bb10a
08a9f58
abe3667
a5ecc4a
8643a82
8ceb42b
d74fa6d
61fce7c
cb870d4
b507da7
924ed28
ecfceff
3ed6484
bf20490
4a0dced
06cdde4
23bdbab
f746f15
52c8673
68c8f7c
da83ae7
c97938e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| import pytest | ||
|
|
||
| from deltachat_rpc_client.rpc import JsonRpcError | ||
|
|
||
|
|
||
| def test_add_second_address(acfactory) -> None: | ||
| account = acfactory.new_configured_account() | ||
| assert len(account.list_transports()) == 1 | ||
|
|
||
| # When the first transport is created, | ||
| # mvbox_move and only_fetch_mvbox should be disabled. | ||
| assert account.get_config("mvbox_move") == "0" | ||
| assert account.get_config("only_fetch_mvbox") == "0" | ||
| assert account.get_config("show_emails") == "2" | ||
|
|
||
| qr = acfactory.get_account_qr() | ||
| account.add_transport_from_qr(qr) | ||
| assert len(account.list_transports()) == 2 | ||
|
|
||
| account.add_transport_from_qr(qr) | ||
| assert len(account.list_transports()) == 3 | ||
|
|
||
| first_addr = account.list_transports()[0]["addr"] | ||
| second_addr = account.list_transports()[1]["addr"] | ||
|
|
||
| # Cannot delete the first address. | ||
| with pytest.raises(JsonRpcError): | ||
| account.delete_transport(first_addr) | ||
|
|
||
| account.delete_transport(second_addr) | ||
| assert len(account.list_transports()) == 2 | ||
|
|
||
| # Enabling mvbox_move or only_fetch_mvbox | ||
| # is not allowed when multi-transport is enabled. | ||
| for option in ["mvbox_move", "only_fetch_mvbox"]: | ||
| with pytest.raises(JsonRpcError): | ||
| account.set_config(option, "1") | ||
|
|
||
| with pytest.raises(JsonRpcError): | ||
| account.set_config("show_emails", "0") | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("key", ["mvbox_move", "only_fetch_mvbox"]) | ||
| def test_no_second_transport_with_mvbox(acfactory, key) -> None: | ||
| """Test that second transport cannot be configured if mvbox is used.""" | ||
| account = acfactory.new_configured_account() | ||
| assert len(account.list_transports()) == 1 | ||
|
|
||
| assert account.get_config("mvbox_move") == "0" | ||
| assert account.get_config("only_fetch_mvbox") == "0" | ||
|
|
||
| qr = acfactory.get_account_qr() | ||
| account.set_config(key, "1") | ||
|
|
||
| with pytest.raises(JsonRpcError): | ||
| account.add_transport_from_qr(qr) | ||
|
|
||
|
|
||
| def test_no_second_transport_without_classic_emails(acfactory) -> None: | ||
| """Test that second transport cannot be configured if classic emails are not fetched.""" | ||
| account = acfactory.new_configured_account() | ||
| assert len(account.list_transports()) == 1 | ||
|
|
||
| assert account.get_config("show_emails") == "2" | ||
|
|
||
| qr = acfactory.get_account_qr() | ||
| account.set_config("show_emails", "0") | ||
|
|
||
| with pytest.raises(JsonRpcError): | ||
| account.add_transport_from_qr(qr) | ||
|
|
||
|
|
||
| def test_change_address(acfactory) -> None: | ||
| """Test Alice configuring a second transport and setting it as a primary one.""" | ||
| alice, bob = acfactory.get_online_accounts(2) | ||
|
|
||
| bob_addr = bob.get_config("configured_addr") | ||
| bob.create_chat(alice) | ||
|
|
||
| alice_chat_bob = alice.create_chat(bob) | ||
| alice_chat_bob.send_text("Hello!") | ||
|
|
||
| msg1 = bob.wait_for_incoming_msg().get_snapshot() | ||
| sender_addr1 = msg1.sender.get_snapshot().address | ||
|
|
||
| alice.stop_io() | ||
| old_alice_addr = alice.get_config("configured_addr") | ||
| alice_vcard = alice.self_contact.make_vcard() | ||
| assert old_alice_addr in alice_vcard | ||
| qr = acfactory.get_account_qr() | ||
| alice.add_transport_from_qr(qr) | ||
| new_alice_addr = alice.list_transports()[1]["addr"] | ||
| with pytest.raises(JsonRpcError): | ||
| # Cannot use the address that is not | ||
| # configured for any transport. | ||
| alice.set_config("configured_addr", bob_addr) | ||
| alice.set_config("configured_addr", new_alice_addr) | ||
| alice_vcard = alice.self_contact.make_vcard() | ||
| assert old_alice_addr not in alice_vcard | ||
| assert new_alice_addr in alice_vcard | ||
| with pytest.raises(JsonRpcError): | ||
| alice.delete_transport(new_alice_addr) | ||
| alice.start_io() | ||
|
|
||
| alice_chat_bob.send_text("Hello again!") | ||
|
|
||
| msg2 = bob.wait_for_incoming_msg().get_snapshot() | ||
| sender_addr2 = msg2.sender.get_snapshot().address | ||
|
|
||
| assert msg1.sender == msg2.sender | ||
| assert sender_addr1 != sender_addr2 | ||
| assert sender_addr1 == old_alice_addr | ||
| assert sender_addr2 == new_alice_addr | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("is_chatmail", ["0", "1"]) | ||
| def test_mvbox_move_first_transport(acfactory, is_chatmail) -> None: | ||
| """Test that mvbox_move is disabled by default even for non-chatmail accounts. | ||
| Disabling mvbox_move is required to be able to setup a second transport. | ||
| """ | ||
| account = acfactory.get_unconfigured_account() | ||
|
|
||
| account.set_config("fix_is_chatmail", "1") | ||
| account.set_config("is_chatmail", is_chatmail) | ||
|
|
||
| # The default value when the setting is unset is "1". | ||
| # This is not changed for compatibility with old databases | ||
| # imported from backups. | ||
| assert account.get_config("mvbox_move") == "1" | ||
|
|
||
| qr = acfactory.get_account_qr() | ||
| account.add_transport_from_qr(qr) | ||
|
|
||
| # Once the first transport is set up, | ||
| # mvbox_move is disabled. | ||
| assert account.get_config("mvbox_move") == "0" | ||
| assert account.get_config("is_chatmail") == is_chatmail |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -466,7 +466,10 @@ impl Config { | |
|
|
||
| /// Whether the config option needs an IO scheduler restart to take effect. | ||
| pub(crate) fn needs_io_restart(&self) -> bool { | ||
| matches!(self, Config::MvboxMove | Config::OnlyFetchMvbox) | ||
| matches!( | ||
| self, | ||
| Config::MvboxMove | Config::OnlyFetchMvbox | Config::ConfiguredAddr | ||
| ) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -706,6 +709,16 @@ impl Context { | |
| pub async fn set_config(&self, key: Config, value: Option<&str>) -> Result<()> { | ||
| Self::check_config(key, value)?; | ||
|
|
||
| let n_transports = self.count_transports().await?; | ||
| if n_transports > 1 | ||
| && matches!( | ||
| key, | ||
| Config::MvboxMove | Config::OnlyFetchMvbox | Config::ShowEmails | ||
| ) | ||
| { | ||
| bail!("Cannot reconfigure {key} when multiple transports are configured"); | ||
| } | ||
|
|
||
| let _pause = match key.needs_io_restart() { | ||
| true => self.scheduler.pause(self).await?, | ||
| _ => Default::default(), | ||
|
|
@@ -791,10 +804,11 @@ impl Context { | |
| .await?; | ||
| } | ||
| Config::ConfiguredAddr => { | ||
| if self.is_configured().await? { | ||
| bail!("Cannot change ConfiguredAddr"); | ||
| } | ||
| if let Some(addr) = value { | ||
| let Some(addr) = value else { | ||
| bail!("Cannot unset configured_addr"); | ||
| }; | ||
|
|
||
| if !self.is_configured().await? { | ||
| info!( | ||
| self, | ||
| "Creating a pseudo configured account which will not be able to send or receive messages. Only meant for tests!" | ||
|
|
@@ -805,6 +819,33 @@ impl Context { | |
| .save_to_transports_table(self, &EnteredLoginParam::default()) | ||
| .await?; | ||
| } | ||
| self.sql | ||
| .transaction(|transaction| { | ||
| if transaction.query_row( | ||
| "SELECT COUNT(*) FROM transports WHERE addr=?", | ||
| (addr,), | ||
| |row| { | ||
| let res: i64 = row.get(0)?; | ||
| Ok(res) | ||
| }, | ||
| )? == 0 | ||
| { | ||
| bail!("Address does not belong to any transport."); | ||
| } | ||
| transaction.execute( | ||
| "UPDATE config SET value=? WHERE keyname='configured_addr'", | ||
| (addr,), | ||
| )?; | ||
|
|
||
| // Clean up SMTP queue. | ||
| // | ||
| // The messages in the queue have a different | ||
| // From address so we cannot send them over | ||
| // the new SMTP transport. | ||
| transaction.execute("DELETE FROM smtp", ())?; | ||
|
Comment on lines
+840
to
+845
|
||
| Ok(()) | ||
| }) | ||
| .await?; | ||
| } | ||
| _ => { | ||
| self.sql.set_raw_config(key.as_ref(), value).await?; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.