Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions deltachat-rpc-client/src/deltachat_rpc_client/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ def add_transport_from_qr(self, qr: str):
"""Add a new transport using a QR code."""
yield self._rpc.add_transport_from_qr.future(self.id, qr)

def delete_transport(self, addr: str):
"""Delete a transport."""
self._rpc.delete_transport(self.id, addr)

@futuremethod
def list_transports(self):
"""Return the list of all email accounts that are used as a transport in the current profile."""
Expand Down
4 changes: 4 additions & 0 deletions deltachat-rpc-client/src/deltachat_rpc_client/pytestplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ def get_credentials(self) -> (str, str):
username = "ci-" + "".join(random.choice("2345789acdefghjkmnpqrstuvwxyz") for i in range(6))
return f"{username}@{domain}", f"{username}${username}"

def get_account_qr(self):
domain = os.getenv("CHATMAIL_DOMAIN")
return f"dcaccount:https://{domain}/new"

@futuremethod
def new_configured_account(self):
"""Create a new configured account."""
Expand Down
54 changes: 54 additions & 0 deletions deltachat-rpc-client/tests/test_multitransport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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

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


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)

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")
qr = acfactory.get_account_qr()
alice.add_transport_from_qr(qr)
new_alice_addr = alice.list_transports()[1]["addr"]
alice.set_config("configured_addr", 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
28 changes: 14 additions & 14 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::env;
use std::path::Path;
use std::str::FromStr;

use anyhow::{Context as _, Result, bail, ensure};
use anyhow::{Context as _, Result, ensure};
use base64::Engine as _;
use deltachat_contact_tools::{addr_cmp, sanitize_single_line};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -791,20 +791,20 @@ impl Context {
.await?;
}
Config::ConfiguredAddr => {
if self.is_configured().await? {
bail!("Cannot change ConfiguredAddr");
}
if let Some(addr) = value {
info!(
self,
"Creating a pseudo configured account which will not be able to send or receive messages. Only meant for tests!"
);
ConfiguredLoginParam::from_json(&format!(
r#"{{"addr":"{addr}","imap":[],"imap_user":"","imap_password":"","smtp":[],"smtp_user":"","smtp_password":"","certificate_checks":"Automatic","oauth2":false}}"#
))?
.save_to_transports_table(self, &EnteredLoginParam::default())
.await?;
if !self.is_configured().await? {
if let Some(addr) = value {
info!(
self,
"Creating a pseudo configured account which will not be able to send or receive messages. Only meant for tests!"
);
ConfiguredLoginParam::from_json(&format!(
r#"{{"addr":"{addr}","imap":[],"imap_user":"","imap_password":"","smtp":[],"smtp_user":"","smtp_password":"","certificate_checks":"Automatic","oauth2":false}}"#
))?
.save_to_transports_table(self, &EnteredLoginParam::default())
.await?;
}
}
self.sql.set_raw_config(key.as_ref(), value).await?;
}
_ => {
self.sql.set_raw_config(key.as_ref(), value).await?;
Expand Down
31 changes: 20 additions & 11 deletions src/configure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,6 @@ impl Context {
"cannot configure, database not opened."
);
param.addr = addr_normalize(&param.addr);
let old_addr = self.get_config(Config::ConfiguredAddr).await?;
if self.is_configured().await? && !addr_cmp(&old_addr.unwrap_or_default(), &param.addr) {
let error_msg = "Changing your email address is not supported right now. Check back in a few months!";
progress!(self, 0, Some(error_msg.to_string()));
bail!(error_msg);
}
let cancel_channel = self.alloc_ongoing().await?;

let res = self
Expand Down Expand Up @@ -209,11 +203,26 @@ impl Context {

/// Removes the transport with the specified email address
/// (i.e. [EnteredLoginParam::addr]).
#[expect(clippy::unused_async)]
pub async fn delete_transport(&self, _addr: &str) -> Result<()> {
bail!(
"Adding and removing additional transports is not supported yet. Check back in a few months!"
)
pub async fn delete_transport(&self, addr: &str) -> Result<()> {
self.sql
.transaction(|transaction| {
let current_addr = transaction.query_row(
"SELECT value FROM config WHERE keyname='configured_addr'",
(),
|row| {
let addr: String = row.get(0)?;
Ok(addr)
},
)?;

if current_addr == addr {
bail!("Cannot delete current transport");
}
transaction.execute("DELETE FROM transports WHERE addr=?", (addr,))?;
Ok(())
})
.await?;
Ok(())
}

async fn inner_configure(&self, param: &EnteredLoginParam) -> Result<()> {
Expand Down
10 changes: 2 additions & 8 deletions src/login_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

use std::fmt;

use anyhow::{Context as _, Result, bail, ensure, format_err};
use deltachat_contact_tools::{EmailAddress, addr_cmp, addr_normalize};
use anyhow::{Context as _, Result, bail, format_err};
use deltachat_contact_tools::{EmailAddress, addr_normalize};
use num_traits::ToPrimitive as _;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -807,12 +807,6 @@ impl ConfiguredLoginParam {
let addr = addr_normalize(&self.addr);
let provider_id = self.provider.map(|provider| provider.id);
let configured_addr = context.get_config(Config::ConfiguredAddr).await?;
if let Some(configured_addr) = &configured_addr {
ensure!(
addr_cmp(configured_addr, &addr),
"Adding a second transport is not supported right now."
);
}
context
.sql
.execute(
Expand Down