Compare commits

...

9 Commits

Author SHA1 Message Date
B. Petersen
96e57e7ef3 bump version to 1.51.0 2021-03-23 18:51:26 +01:00
B. Petersen
02bc334af5 update changelog for 1.51 2021-03-23 18:51:26 +01:00
Simon Laux
c8fea9c577 Merge pull request #2303 from deltachat/add_cmake_build_to_gitignore
add /build directory to .gitignore
2021-03-21 17:12:03 +01:00
link2xt
cdc1063d83 Do not reset user status after receiving a read receipt
Read receipts never contain the signature, so previously receiving it
cleared the status.
2021-03-21 18:54:08 +03:00
Simon Laux
704a902cc5 add build directory to gitignore
(libdeltachat generated with cmake)
2021-03-20 18:23:30 +01:00
B. Petersen
36aef6499d update provider database 2021-03-18 21:55:33 +01:00
B. Petersen
4ba9c2fafa fix clippy error on generating rust code from python 2021-03-18 21:55:33 +01:00
Hocuri
0de8b6a7e5 Update uid_next if the server rewinded it
fix #2188

Also, if we notice that the server started reusing old UIDs, _also_ do a `ResyncFolders`, because the server likely forgot to change uid_validity
2021-03-18 16:14:56 +03:00
link2xt
04f816be31 qr: return QrFprMismatch on fingerprint mismatch
Previously QrFprWithoutAddr was returned incorrectly.

Also fix spelling error ("Missmatch").
2021-03-15 21:39:10 +03:00
12 changed files with 336 additions and 87 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
/target
**/*.rs.bk
/build
# ignore vi temporaries
*~

View File

@@ -1,22 +1,23 @@
# Changelog
## UNRELEASED
## 1.51.0
- breaking change: You have to call dc_stop_io()/dc_start_io() before/after EXPORT_BACKUP:
fix race condition and db corruption when a message was received during backup #2253
- breaking change: You have to call `dc_stop_io()`/`dc_start_io()`
before/after `dc_imex(DC_IMEX_EXPORT_BACKUP)`:
fix race condition and db corruption
when a message was received during backup #2253
- save subject for messages:
new api `dc_msg_get_subject()`,
when quoting, use the subject of the quoted message as the new subject, instead of the
last subject in the chat
- save subject for messages: new api `dc_msg_get_subject()`,
when quoting, use the subject of the quoted message as the new subject,
instead of the last subject in the chat #2274 #2283
- new apis to get full or html message,
`dc_msg_has_html()` and `dc_get_msg_html()` #2125 #2151
`dc_msg_has_html()` and `dc_get_msg_html()` #2125 #2151 #2264 #2279
- new chat type and apis for the new mailing list support,
`DC_CHAT_TYPE_MAILINGLIST`, `dc_msg_get_real_chat_id()`,
`dc_msg_get_override_sender_name()` #1964 #2181 #2185 #2195 #2211 #2210 #2240
#2243
#2241 #2243 #2258 #2259 #2261 #2267 #2270 #2272 #2290
- new api `dc_decide_on_contact_request()`,
deprecated `dc_create_chat_by_msg_id()` and `dc_marknoticed_contact()` #1964
@@ -25,7 +26,7 @@
- new api `dc_get_chat_encrinfo()` #2186
- new api `dc_contact_get_status()`, returning the recent footer #2218
- new api `dc_contact_get_status()`, returning the recent footer #2218 #2307
- improve contact name update rules,
add api `dc_contact_get_auth_name()` #2206 #2212 #2225
@@ -38,6 +39,9 @@
- api removed: `dc_contact_get_first_name()` #2165 #2171
- improve compatibility with providers changing the Message-ID
(as Outlook.com) #2250 #2265
- implement Consistent Color Generation (XEP-0392),
that results in contact colors be be changed #2228 #2229 #2239
@@ -72,7 +76,7 @@
- enable strict TLS for known providers by default #2121
- improve and harden secure join #2154 #2161
- improve and harden secure join #2154 #2161 #2251
- update `dc_get_info()` to return more information #2156
@@ -100,10 +104,24 @@
- fix parsing quoted encoded words in From: header #2193 #2204
- fix ci #2217 #2226
- fix import/export race condition #2250
- fix: exclude muted chats from notified-list #2269 #2275
- fix: update uid_next if the server rewind it #2288
- fix: return error on fingerprint mismatch on qr-scan #2295
- fix ci #2217 #2226 #2244 #2245 #2249 #2277 #2286
- try harder on backup opening #2148
- trash messages more thoroughly #2273
- nicer logging #2284
- add CMakeLists.txt #2260
- switch to rust 1.50, update toolchains, deps #2150 #2155 #2165 #2107 #2262 #2271
- improve python bindings #2113 #2115 #2133 #2214
@@ -111,7 +129,9 @@
- improve documentation #2143 #2160 #2175 #2146
- refactorings #2110 #2136 #2135 #2168 #2178 #2189 #2190 #2198 #2197 #2201 #2196
#2200 #2230
#2200 #2230 #2262 #2203
- update provider-database #2299
## 1.50.0

4
Cargo.lock generated
View File

@@ -1063,7 +1063,7 @@ dependencies = [
[[package]]
name = "deltachat"
version = "1.51.0-alpha.0"
version = "1.51.0"
dependencies = [
"ansi_term 0.12.1",
"anyhow",
@@ -1141,7 +1141,7 @@ dependencies = [
[[package]]
name = "deltachat_ffi"
version = "1.51.0-alpha.0"
version = "1.51.0"
dependencies = [
"anyhow",
"async-std",

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat"
version = "1.51.0-alpha.0"
version = "1.51.0"
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
edition = "2018"
license = "MPL-2.0"

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat_ffi"
version = "1.51.0-alpha.0"
version = "1.51.0"
description = "Deltachat FFI"
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
edition = "2018"

View File

@@ -2187,9 +2187,25 @@ class TestOnlineAccount:
chat12 = acfactory.get_accepted_chat(ac1, ac2)
ac1.set_config("selfstatus", "New status")
chat12.send_text("hi")
msg = ac2._evtracker.wait_next_incoming_message()
assert msg.text == "hi"
assert msg.get_sender_contact().status == "New status"
msg_received = ac2._evtracker.wait_next_incoming_message()
assert msg_received.text == "hi"
assert msg_received.get_sender_contact().status == "New status"
# Send a reply from ac2 to ac1 so ac1 can send a read receipt.
reply_msg = msg_received.chat.send_text("reply")
reply_msg_received = ac1._evtracker.wait_next_incoming_message()
assert reply_msg_received.text == "reply"
# Send read receipt from ac1 to ac2.
# It does not contain the signature.
ac1.mark_seen_messages([reply_msg_received])
ev = ac2._evtracker.get_matching("DC_EVENT_MSG_READ")
assert ev.data1 == reply_msg.chat.id
assert ev.data2 == reply_msg.id
assert reply_msg.is_out_mdn_received()
# Test that the status is not cleared as a result of receiving a read receipt.
assert msg_received.get_sender_contact().status == "New status"
ac1.set_config("selfstatus", "")
chat12.send_text("hello")

View File

@@ -237,14 +237,18 @@ pub(crate) async fn dc_receive_imf_inner(
}
// Always update the status, even if there is no footer, to allow removing the status.
if let Err(err) = contact::set_status(
context,
from_id,
mime_parser.footer.clone().unwrap_or_default(),
)
.await
{
warn!(context, "cannot update contact status: {}", err);
//
// Ignore MDNs though, as they never contain the signature even if user has set it.
if mime_parser.mdn_reports.is_empty() {
if let Err(err) = contact::set_status(
context,
from_id,
mime_parser.footer.clone().unwrap_or_default(),
)
.await
{
warn!(context, "cannot update contact status: {}", err);
}
}
// Get user-configured server deletion

View File

@@ -575,6 +575,15 @@ impl Imap {
// new messages is only one command, just as a SELECT command)
true
} else if let Some(uid_next) = mailbox.uid_next {
if uid_next < old_uid_next {
warn!(
context,
"The server illegally decreased the uid_next of folder {} from {} to {} without changing validity ({}), resyncing UIDs...",
folder, old_uid_next, uid_next, new_uid_validity,
);
set_uid_next(context, folder, uid_next).await?;
job::schedule_resync(context).await;
}
uid_next != old_uid_next // If uid_next changed, there are new emails
} else {
true // We have no uid_next and if in doubt, return true

View File

@@ -87,7 +87,7 @@ pub enum LotState {
QrFprOk = 210,
/// id=contact
QrFprMissmatch = 220,
QrFprMismatch = 220,
/// test1=formatted fingerprint
QrFprWithoutAddr = 230,

View File

@@ -296,6 +296,35 @@ static P_DUBBY_ORG: Lazy<Provider> = Lazy::new(|| Provider {
oauth2_authorizer: None,
});
// e.email.md: e.email
static P_E_EMAIL: Lazy<Provider> = Lazy::new(|| Provider {
id: "e.email",
status: Status::OK,
before_login_hint: "",
after_login_hint: "",
overview_page: "https://providers.delta.chat/e-email",
server: vec![
Server {
protocol: IMAP,
socket: SSL,
hostname: "mail.ecloud.global",
port: 993,
username_pattern: EMAIL,
},
Server {
protocol: SMTP,
socket: STARTTLS,
hostname: "mail.ecloud.global",
port: 587,
username_pattern: EMAIL,
},
],
config_defaults: None,
strict_tls: true,
max_smtp_rcpt_to: None,
oauth2_authorizer: None,
});
// espiv.net.md: espiv.net
static P_ESPIV_NET: Lazy<Provider> = Lazy::new(|| Provider {
id: "espiv.net",
@@ -337,7 +366,29 @@ static P_FASTMAIL: Lazy<Provider> = Lazy::new(|| Provider {
"You must create an app-specific password for Delta Chat before you can log in.",
after_login_hint: "",
overview_page: "https://providers.delta.chat/fastmail",
server: vec![],
server: vec![
Server {
protocol: IMAP,
socket: SSL,
hostname: "imap.fastmail.com",
port: 993,
username_pattern: EMAIL,
},
Server {
protocol: SMTP,
socket: SSL,
hostname: "smtp.fastmail.com",
port: 465,
username_pattern: EMAIL,
},
Server {
protocol: SMTP,
socket: STARTTLS,
hostname: "smtp.fastmail.com",
port: 587,
username_pattern: EMAIL,
},
],
config_defaults: None,
strict_tls: true,
max_smtp_rcpt_to: None,
@@ -393,32 +444,22 @@ static P_FIVE_CHAT: Lazy<Provider> = Lazy::new(|| Provider {
});
// freenet.de.md: freenet.de
static P_FREENET_DE: Lazy<Provider> = Lazy::new(|| Provider {
static P_FREENET_DE: Lazy<Provider> = Lazy::new(|| {
Provider {
id: "freenet.de",
status: Status::OK,
before_login_hint: "",
status: Status::PREPARATION,
before_login_hint: "Um deine freenet.de E-Mail-Adresse mit Delta Chat zu benutzen, musst du erst auf der freenet.de-Webseite \"POP3/IMAP/SMTP\" aktivieren.",
after_login_hint: "",
overview_page: "https://providers.delta.chat/freenet-de",
server: vec![
Server {
protocol: IMAP,
socket: SSL,
hostname: "mx.freenet.de",
port: 993,
username_pattern: EMAIL,
},
Server {
protocol: SMTP,
socket: STARTTLS,
hostname: "mx.freenet.de",
port: 587,
username_pattern: EMAIL,
},
Server { protocol: IMAP, socket: SSL, hostname: "mx.freenet.de", port: 993, username_pattern: EMAIL },
Server { protocol: SMTP, socket: STARTTLS, hostname: "mx.freenet.de", port: 587, username_pattern: EMAIL },
],
config_defaults: None,
strict_tls: true,
max_smtp_rcpt_to: None,
oauth2_authorizer: None,
}
});
// gmail.md: gmail.com, googlemail.com, google.com
@@ -538,6 +579,20 @@ static P_I_UA: Lazy<Provider> = Lazy::new(|| Provider {
oauth2_authorizer: None,
});
// i3.net.md: i3.net
static P_I3_NET: Lazy<Provider> = Lazy::new(|| Provider {
id: "i3.net",
status: Status::OK,
before_login_hint: "",
after_login_hint: "",
overview_page: "https://providers.delta.chat/i3-net",
server: vec![],
config_defaults: None,
strict_tls: true,
max_smtp_rcpt_to: None,
oauth2_authorizer: None,
});
// icloud.md: icloud.com, me.com, mac.com
static P_ICLOUD: Lazy<Provider> = Lazy::new(|| Provider {
id: "icloud",
@@ -624,51 +679,124 @@ static P_MAILBOX_ORG: Lazy<Provider> = Lazy::new(|| Provider {
oauth2_authorizer: None,
});
// nauta.cu.md: nauta.cu
static P_NAUTA_CU: Lazy<Provider> = Lazy::new(|| {
Provider {
id: "nauta.cu",
// mailo.com.md: mailo.com
static P_MAILO_COM: Lazy<Provider> = Lazy::new(|| Provider {
id: "mailo.com",
status: Status::OK,
before_login_hint: "",
after_login_hint: "Atención - con nauta.cu, puede enviar mensajes sólo a un máximo de 20 personas a la vez. En grupos más grandes, no puede enviar mensajes o abandonar el grupo.",
overview_page: "https://providers.delta.chat/nauta-cu",
after_login_hint: "",
overview_page: "https://providers.delta.chat/mailo-com",
server: vec![
Server { protocol: IMAP, socket: STARTTLS, hostname: "imap.nauta.cu", port: 143, username_pattern: EMAIL },
Server { protocol: SMTP, socket: STARTTLS, hostname: "smtp.nauta.cu", port: 25, username_pattern: EMAIL },
],
config_defaults: Some(vec![
ConfigDefault { key: Config::DeleteServerAfter, value: "1" },
ConfigDefault { key: Config::BccSelf, value: "0" },
ConfigDefault { key: Config::SentboxWatch, value: "0" },
ConfigDefault { key: Config::MvboxWatch, value: "0" },
ConfigDefault { key: Config::MvboxMove, value: "0" },
ConfigDefault { key: Config::E2eeEnabled, value: "0" },
ConfigDefault { key: Config::MediaQuality, value: "1" },
ConfigDefault { key: Config::FetchExistingMsgs, value: "0" },
]),
strict_tls: false,
max_smtp_rcpt_to: Some(20),
oauth2_authorizer: None,
}
});
// outlook.com.md: hotmail.com, outlook.com, office365.com, outlook.com.tr, live.com
static P_OUTLOOK_COM: Lazy<Provider> = Lazy::new(|| {
Provider {
id: "outlook.com",
status: Status::BROKEN,
before_login_hint: "Outlook.com email addresses will not work as expected as these servers remove some important transport information. Hopefully sooner or later there will be a fix, for now we suggest to use another email address.",
after_login_hint: "Outlook.com email addresses will not work as expected as these servers remove some important transport information. Unencrypted 1-on-1 chats kind of work, but groups and encryption don't. Hopefully sooner or later there will be a fix, for now we suggest to use another email address.",
overview_page: "https://providers.delta.chat/outlook-com",
server: vec![
Server { protocol: IMAP, socket: SSL, hostname: "imap-mail.outlook.com", port: 993, username_pattern: EMAIL },
Server { protocol: SMTP, socket: STARTTLS, hostname: "smtp-mail.outlook.com", port: 587, username_pattern: EMAIL },
Server {
protocol: IMAP,
socket: SSL,
hostname: "imap.mailo.com",
port: 993,
username_pattern: EMAIL,
},
Server {
protocol: SMTP,
socket: SSL,
hostname: "smtp.mailo.com",
port: 465,
username_pattern: EMAIL,
},
],
config_defaults: None,
strict_tls: true,
max_smtp_rcpt_to: None,
oauth2_authorizer: None,
});
// nauta.cu.md: nauta.cu
static P_NAUTA_CU: Lazy<Provider> = Lazy::new(|| Provider {
id: "nauta.cu",
status: Status::OK,
before_login_hint: "",
after_login_hint: "",
overview_page: "https://providers.delta.chat/nauta-cu",
server: vec![
Server {
protocol: IMAP,
socket: STARTTLS,
hostname: "imap.nauta.cu",
port: 143,
username_pattern: EMAIL,
},
Server {
protocol: SMTP,
socket: STARTTLS,
hostname: "smtp.nauta.cu",
port: 25,
username_pattern: EMAIL,
},
],
config_defaults: Some(vec![
ConfigDefault {
key: Config::DeleteServerAfter,
value: "1",
},
ConfigDefault {
key: Config::BccSelf,
value: "0",
},
ConfigDefault {
key: Config::SentboxWatch,
value: "0",
},
ConfigDefault {
key: Config::MvboxWatch,
value: "0",
},
ConfigDefault {
key: Config::MvboxMove,
value: "0",
},
ConfigDefault {
key: Config::E2eeEnabled,
value: "0",
},
ConfigDefault {
key: Config::MediaQuality,
value: "1",
},
ConfigDefault {
key: Config::FetchExistingMsgs,
value: "0",
},
]),
strict_tls: false,
max_smtp_rcpt_to: Some(20),
oauth2_authorizer: None,
});
// outlook.com.md: hotmail.com, outlook.com, office365.com, outlook.com.tr, live.com
static P_OUTLOOK_COM: Lazy<Provider> = Lazy::new(|| Provider {
id: "outlook.com",
status: Status::OK,
before_login_hint: "",
after_login_hint: "",
overview_page: "https://providers.delta.chat/outlook-com",
server: vec![
Server {
protocol: IMAP,
socket: SSL,
hostname: "outlook.office365.com",
port: 993,
username_pattern: EMAIL,
},
Server {
protocol: SMTP,
socket: STARTTLS,
hostname: "smtp.office365.com",
port: 587,
username_pattern: EMAIL,
},
],
config_defaults: None,
strict_tls: true,
max_smtp_rcpt_to: None,
oauth2_authorizer: None,
}
});
// posteo.md: posteo.de, posteo.af, posteo.at, posteo.be, posteo.ch, posteo.cl, posteo.co, posteo.co.uk, posteo.com.br, posteo.cr, posteo.cz, posteo.dk, posteo.ee, posteo.es, posteo.eu, posteo.fi, posteo.gl, posteo.gr, posteo.hn, posteo.hr, posteo.hu, posteo.ie, posteo.in, posteo.is, posteo.jp, posteo.la, posteo.li, posteo.lt, posteo.lu, posteo.me, posteo.mx, posteo.my, posteo.net, posteo.nl, posteo.no, posteo.nz, posteo.org, posteo.pe, posteo.pl, posteo.pm, posteo.pt, posteo.ro, posteo.ru, posteo.se, posteo.sg, posteo.si, posteo.tn, posteo.uk, posteo.us
@@ -1057,6 +1185,7 @@ pub(crate) static PROVIDER_DATA: Lazy<HashMap<&'static str, &'static Provider>>
("dismail.de", &*P_DISMAIL_DE),
("disroot.org", &*P_DISROOT),
("dubby.org", &*P_DUBBY_ORG),
("e.email", &*P_E_EMAIL),
("espiv.net", &*P_ESPIV_NET),
("example.com", &*P_EXAMPLE_COM),
("example.org", &*P_EXAMPLE_COM),
@@ -1081,6 +1210,7 @@ pub(crate) static PROVIDER_DATA: Lazy<HashMap<&'static str, &'static Provider>>
("hermes.radio", &*P_HERMES_RADIO),
("hey.com", &*P_HEY_COM),
("i.ua", &*P_I_UA),
("i3.net", &*P_I3_NET),
("icloud.com", &*P_ICLOUD),
("me.com", &*P_ICLOUD),
("mac.com", &*P_ICLOUD),
@@ -1092,6 +1222,7 @@ pub(crate) static PROVIDER_DATA: Lazy<HashMap<&'static str, &'static Provider>>
("list.ru", &*P_MAIL_RU),
("mailbox.org", &*P_MAILBOX_ORG),
("secure.mailbox.org", &*P_MAILBOX_ORG),
("mailo.com", &*P_MAILO_COM),
("nauta.cu", &*P_NAUTA_CU),
("hotmail.com", &*P_OUTLOOK_COM),
("outlook.com", &*P_OUTLOOK_COM),
@@ -1230,6 +1361,7 @@ pub(crate) static PROVIDER_IDS: Lazy<HashMap<&'static str, &'static Provider>> =
("dismail.de", &*P_DISMAIL_DE),
("disroot", &*P_DISROOT),
("dubby.org", &*P_DUBBY_ORG),
("e.email", &*P_E_EMAIL),
("espiv.net", &*P_ESPIV_NET),
("example.com", &*P_EXAMPLE_COM),
("fastmail", &*P_FASTMAIL),
@@ -1241,11 +1373,13 @@ pub(crate) static PROVIDER_IDS: Lazy<HashMap<&'static str, &'static Provider>> =
("hermes.radio", &*P_HERMES_RADIO),
("hey.com", &*P_HEY_COM),
("i.ua", &*P_I_UA),
("i3.net", &*P_I3_NET),
("icloud", &*P_ICLOUD),
("kolst.com", &*P_KOLST_COM),
("kontent.com", &*P_KONTENT_COM),
("mail.ru", &*P_MAIL_RU),
("mailbox.org", &*P_MAILBOX_ORG),
("mailo.com", &*P_MAILO_COM),
("nauta.cu", &*P_NAUTA_CU),
("outlook.com", &*P_OUTLOOK_COM),
("posteo", &*P_POSTEO),
@@ -1271,4 +1405,4 @@ pub(crate) static PROVIDER_IDS: Lazy<HashMap<&'static str, &'static Provider>> =
});
pub static PROVIDER_UPDATED: Lazy<chrono::NaiveDate> =
Lazy::new(|| chrono::NaiveDate::from_ymd(2021, 1, 8));
Lazy::new(|| chrono::NaiveDate::from_ymd(2021, 3, 18));

View File

@@ -175,7 +175,7 @@ if __name__ == "__main__":
"use crate::provider::Protocol::*;\n"
"use crate::provider::Socket::*;\n"
"use crate::provider::UsernamePattern::*;\n"
"use crate::provider::*;\n"
"use crate::provider::{Config, ConfigDefault, Oauth2Authorizer, Provider, Server, Status};\n"
"use std::collections::HashMap;\n\n"
"use once_cell::sync::Lazy;\n\n")

View File

@@ -72,6 +72,7 @@ pub async fn check_qr(context: &Context, qr: impl AsRef<str>) -> Lot {
/// scheme: `OPENPGP4FPR:FINGERPRINT#a=ADDR&n=NAME&i=INVITENUMBER&s=AUTH`
/// or: `OPENPGP4FPR:FINGERPRINT#a=ADDR&g=GROUPNAME&x=GROUPID&i=INVITENUMBER&s=AUTH`
/// or: `OPENPGP4FPR:FINGERPRINT#a=ADDR`
#[allow(clippy::indexing_slicing)]
async fn decode_openpgp(context: &Context, qr: &str) -> Lot {
let payload = &qr[OPENPGP4FPR_SCHEME.len()..];
@@ -169,6 +170,14 @@ async fn decode_openpgp(context: &Context, qr: &str) -> Lot {
.unwrap_or_default();
chat::add_info_msg(context, id, format!("{} verified.", peerstate.addr)).await;
} else if let Some(addr) = addr {
lot.state = LotState::QrFprMismatch;
lot.id = match Contact::lookup_id_by_addr(context, &addr, Origin::Unknown).await {
Ok(contact_id) => contact_id.unwrap_or_default(),
Err(err) => {
return format_err!("Error looking up contact {:?}: {}", addr, err).into()
}
};
} else {
lot.state = LotState::QrFprWithoutAddr;
lot.text1 = Some(fingerprint.to_string());
@@ -436,7 +445,10 @@ fn normalize_address(addr: &str) -> Result<String, Error> {
mod tests {
use super::*;
use crate::test_utils::TestContext;
use crate::aheader::EncryptPreference;
use crate::key::DcKey;
use crate::peerstate::ToSave;
use crate::test_utils::{alice_keypair, TestContext};
#[async_std::test]
async fn test_decode_http() {
@@ -625,6 +637,59 @@ mod tests {
assert_eq!(contact.get_name(), "");
}
#[async_std::test]
async fn test_decode_openpgp_fingerprint() {
let ctx = TestContext::new().await;
let contact_id = Contact::create(&ctx, "Alice", "alice@example.com")
.await
.expect("failed to create contact");
let pub_key = alice_keypair().public;
let peerstate = Peerstate {
addr: "alice@example.com".to_string(),
last_seen: 1,
last_seen_autocrypt: 1,
prefer_encrypt: EncryptPreference::Mutual,
public_key: Some(pub_key.clone()),
public_key_fingerprint: Some(pub_key.fingerprint()),
gossip_key: None,
gossip_timestamp: 0,
gossip_key_fingerprint: None,
verified_key: None,
verified_key_fingerprint: None,
to_save: Some(ToSave::All),
fingerprint_changed: false,
};
assert!(
peerstate.save_to_db(&ctx.ctx.sql, true).await.is_ok(),
"failed to save peerstate"
);
let res = check_qr(
&ctx.ctx,
"OPENPGP4FPR:1234567890123456789012345678901234567890#a=alice@example.com",
)
.await;
assert_eq!(res.get_state(), LotState::QrFprMismatch);
assert_eq!(res.get_id(), contact_id);
let res = check_qr(
&ctx.ctx,
format!("OPENPGP4FPR:{}#a=alice@example.com", pub_key.fingerprint()),
)
.await;
assert_eq!(res.get_state(), LotState::QrFprOk);
assert_eq!(res.get_id(), contact_id);
let res = check_qr(
&ctx.ctx,
"OPENPGP4FPR:1234567890123456789012345678901234567890#a=bob@example.org",
)
.await;
assert_eq!(res.get_state(), LotState::QrFprMismatch);
assert_eq!(res.get_id(), 0);
}
#[async_std::test]
async fn test_decode_openpgp_without_addr() {
let ctx = TestContext::new().await;