mirror of
https://github.com/chatmail/core.git
synced 2026-05-05 14:26:30 +03:00
Remove &Context from Peerstate and MimeParser
Passing Context around explicitly removes the need for explicit lifetimes.
This commit is contained in:
@@ -971,7 +971,7 @@ impl Contact {
|
|||||||
pub async fn is_verified_ex(
|
pub async fn is_verified_ex(
|
||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
peerstate: Option<&Peerstate<'_>>,
|
peerstate: Option<&Peerstate>,
|
||||||
) -> VerifiedStatus {
|
) -> VerifiedStatus {
|
||||||
// We're always sort of secured-verified as we could verify the key on this device any time with the key
|
// We're always sort of secured-verified as we could verify the key on this device any time with the key
|
||||||
// on this device
|
// on this device
|
||||||
|
|||||||
16
src/e2ee.rs
16
src/e2ee.rs
@@ -113,7 +113,7 @@ impl EncryptHelper {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
min_verified: PeerstateVerifiedStatus,
|
min_verified: PeerstateVerifiedStatus,
|
||||||
mail_to_encrypt: lettre_email::PartBuilder,
|
mail_to_encrypt: lettre_email::PartBuilder,
|
||||||
peerstates: Vec<(Option<Peerstate<'_>>, &str)>,
|
peerstates: Vec<(Option<Peerstate>, &str)>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let mut keyring: Keyring<SignedPublicKey> = Keyring::new();
|
let mut keyring: Keyring<SignedPublicKey> = Keyring::new();
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ pub async fn try_decrypt(
|
|||||||
peerstate.apply_header(header, message_time);
|
peerstate.apply_header(header, message_time);
|
||||||
peerstate.save_to_db(&context.sql, false).await?;
|
peerstate.save_to_db(&context.sql, false).await?;
|
||||||
} else {
|
} else {
|
||||||
let p = Peerstate::from_header(context, header, message_time);
|
let p = Peerstate::from_header(header, message_time);
|
||||||
p.save_to_db(&context.sql, true).await?;
|
p.save_to_db(&context.sql, true).await?;
|
||||||
peerstate = Some(p);
|
peerstate = Some(p);
|
||||||
}
|
}
|
||||||
@@ -497,14 +497,10 @@ Sent with my Delta Chat Messenger: https://delta.chat";
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_peerstates(
|
fn new_peerstates(prefer_encrypt: EncryptPreference) -> Vec<(Option<Peerstate>, &'static str)> {
|
||||||
ctx: &Context,
|
|
||||||
prefer_encrypt: EncryptPreference,
|
|
||||||
) -> Vec<(Option<Peerstate<'_>>, &str)> {
|
|
||||||
let addr = "bob@foo.bar";
|
let addr = "bob@foo.bar";
|
||||||
let pub_key = bob_keypair().public;
|
let pub_key = bob_keypair().public;
|
||||||
let peerstate = Peerstate {
|
let peerstate = Peerstate {
|
||||||
context: ctx,
|
|
||||||
addr: addr.into(),
|
addr: addr.into(),
|
||||||
last_seen: 13,
|
last_seen: 13,
|
||||||
last_seen_autocrypt: 14,
|
last_seen_autocrypt: 14,
|
||||||
@@ -531,17 +527,17 @@ Sent with my Delta Chat Messenger: https://delta.chat";
|
|||||||
|
|
||||||
// test with EncryptPreference::NoPreference:
|
// test with EncryptPreference::NoPreference:
|
||||||
// if e2ee_eguaranteed is unset, there is no encryption as not more than half of peers want encryption
|
// if e2ee_eguaranteed is unset, there is no encryption as not more than half of peers want encryption
|
||||||
let ps = new_peerstates(&t, EncryptPreference::NoPreference);
|
let ps = new_peerstates(EncryptPreference::NoPreference);
|
||||||
assert!(encrypt_helper.should_encrypt(&t, true, &ps).unwrap());
|
assert!(encrypt_helper.should_encrypt(&t, true, &ps).unwrap());
|
||||||
assert!(!encrypt_helper.should_encrypt(&t, false, &ps).unwrap());
|
assert!(!encrypt_helper.should_encrypt(&t, false, &ps).unwrap());
|
||||||
|
|
||||||
// test with EncryptPreference::Reset
|
// test with EncryptPreference::Reset
|
||||||
let ps = new_peerstates(&t, EncryptPreference::Reset);
|
let ps = new_peerstates(EncryptPreference::Reset);
|
||||||
assert!(encrypt_helper.should_encrypt(&t, true, &ps).unwrap());
|
assert!(encrypt_helper.should_encrypt(&t, true, &ps).unwrap());
|
||||||
assert!(!encrypt_helper.should_encrypt(&t, false, &ps).unwrap());
|
assert!(!encrypt_helper.should_encrypt(&t, false, &ps).unwrap());
|
||||||
|
|
||||||
// test with EncryptPreference::Mutual (self is also Mutual)
|
// test with EncryptPreference::Mutual (self is also Mutual)
|
||||||
let ps = new_peerstates(&t, EncryptPreference::Mutual);
|
let ps = new_peerstates(EncryptPreference::Mutual);
|
||||||
assert!(encrypt_helper.should_encrypt(&t, true, &ps).unwrap());
|
assert!(encrypt_helper.should_encrypt(&t, true, &ps).unwrap());
|
||||||
assert!(encrypt_helper.should_encrypt(&t, false, &ps).unwrap());
|
assert!(encrypt_helper.should_encrypt(&t, false, &ps).unwrap());
|
||||||
|
|
||||||
|
|||||||
@@ -488,7 +488,7 @@ impl Job {
|
|||||||
let msg = job_try!(Message::load_from_db(context, msg_id).await);
|
let msg = job_try!(Message::load_from_db(context, msg_id).await);
|
||||||
let mimefactory =
|
let mimefactory =
|
||||||
job_try!(MimeFactory::from_mdn(context, &msg, additional_rfc724_mids).await);
|
job_try!(MimeFactory::from_mdn(context, &msg, additional_rfc724_mids).await);
|
||||||
let rendered_msg = job_try!(mimefactory.render().await);
|
let rendered_msg = job_try!(mimefactory.render(context).await);
|
||||||
let body = rendered_msg.message;
|
let body = rendered_msg.message;
|
||||||
|
|
||||||
let addr = contact.get_addr();
|
let addr = contact.get_addr();
|
||||||
@@ -961,7 +961,7 @@ pub async fn send_msg_job(context: &Context, msg_id: MsgId) -> Result<Option<Job
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let rendered_msg = match mimefactory.render().await {
|
let rendered_msg = match mimefactory.render(context).await {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
message::set_msg_failed(context, msg_id, Some(err.to_string())).await;
|
message::set_msg_failed(context, msg_id, Some(err.to_string())).await;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ pub enum Loaded {
|
|||||||
|
|
||||||
/// Helper to construct mime messages.
|
/// Helper to construct mime messages.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MimeFactory<'a, 'b> {
|
pub struct MimeFactory<'a> {
|
||||||
from_addr: String,
|
from_addr: String,
|
||||||
from_displayname: String,
|
from_displayname: String,
|
||||||
selfstatus: String,
|
selfstatus: String,
|
||||||
@@ -49,11 +49,10 @@ pub struct MimeFactory<'a, 'b> {
|
|||||||
|
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
loaded: Loaded,
|
loaded: Loaded,
|
||||||
msg: &'b Message,
|
msg: &'a Message,
|
||||||
in_reply_to: String,
|
in_reply_to: String,
|
||||||
references: String,
|
references: String,
|
||||||
req_mdn: bool,
|
req_mdn: bool,
|
||||||
context: &'a Context,
|
|
||||||
last_added_location_id: u32,
|
last_added_location_id: u32,
|
||||||
attach_selfavatar: bool,
|
attach_selfavatar: bool,
|
||||||
}
|
}
|
||||||
@@ -71,12 +70,12 @@ pub struct RenderedEmail {
|
|||||||
pub rfc724_mid: String,
|
pub rfc724_mid: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> MimeFactory<'a, 'b> {
|
impl<'a> MimeFactory<'a> {
|
||||||
pub async fn from_msg(
|
pub async fn from_msg(
|
||||||
context: &'a Context,
|
context: &Context,
|
||||||
msg: &'b Message,
|
msg: &'a Message,
|
||||||
attach_selfavatar: bool,
|
attach_selfavatar: bool,
|
||||||
) -> Result<MimeFactory<'a, 'b>, Error> {
|
) -> Result<MimeFactory<'a>, Error> {
|
||||||
let chat = Chat::load_from_db(context, msg.chat_id).await?;
|
let chat = Chat::load_from_db(context, msg.chat_id).await?;
|
||||||
|
|
||||||
let from_addr = context
|
let from_addr = context
|
||||||
@@ -156,16 +155,15 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
req_mdn,
|
req_mdn,
|
||||||
last_added_location_id: 0,
|
last_added_location_id: 0,
|
||||||
attach_selfavatar,
|
attach_selfavatar,
|
||||||
context,
|
|
||||||
};
|
};
|
||||||
Ok(factory)
|
Ok(factory)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn from_mdn(
|
pub async fn from_mdn(
|
||||||
context: &'a Context,
|
context: &Context,
|
||||||
msg: &'b Message,
|
msg: &'a Message,
|
||||||
additional_msg_ids: Vec<String>,
|
additional_msg_ids: Vec<String>,
|
||||||
) -> Result<MimeFactory<'a, 'b>, Error> {
|
) -> Result<MimeFactory<'a>, Error> {
|
||||||
ensure!(!msg.chat_id.is_special(), "Invalid chat id");
|
ensure!(!msg.chat_id.is_special(), "Invalid chat id");
|
||||||
|
|
||||||
let contact = Contact::load_from_db(context, msg.from_id).await?;
|
let contact = Contact::load_from_db(context, msg.from_id).await?;
|
||||||
@@ -184,8 +182,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.unwrap_or(default_str);
|
.unwrap_or(default_str);
|
||||||
let timestamp = dc_create_smeared_timestamp(context).await;
|
let timestamp = dc_create_smeared_timestamp(context).await;
|
||||||
|
|
||||||
let res = MimeFactory::<'a, 'b> {
|
let res = MimeFactory::<'a> {
|
||||||
context,
|
|
||||||
from_addr,
|
from_addr,
|
||||||
from_displayname,
|
from_displayname,
|
||||||
selfstatus,
|
selfstatus,
|
||||||
@@ -206,9 +203,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn peerstates_for_recipients(&self) -> Result<Vec<(Option<Peerstate<'_>>, &str)>, Error> {
|
async fn peerstates_for_recipients(
|
||||||
let self_addr = self
|
&self,
|
||||||
.context
|
context: &Context,
|
||||||
|
) -> Result<Vec<(Option<Peerstate>, &str)>, Error> {
|
||||||
|
let self_addr = context
|
||||||
.get_config(Config::ConfiguredAddr)
|
.get_config(Config::ConfiguredAddr)
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| format_err!("Not configured"))?;
|
.ok_or_else(|| format_err!("Not configured"))?;
|
||||||
@@ -219,10 +218,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, addr)| addr != &self_addr)
|
.filter(|(_, addr)| addr != &self_addr)
|
||||||
{
|
{
|
||||||
res.push((
|
res.push((Peerstate::from_addr(context, addr).await?, addr.as_str()));
|
||||||
Peerstate::from_addr(self.context, addr).await?,
|
|
||||||
addr.as_str(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
@@ -290,11 +286,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn should_do_gossip(&self) -> bool {
|
async fn should_do_gossip(&self, context: &Context) -> bool {
|
||||||
match &self.loaded {
|
match &self.loaded {
|
||||||
Loaded::Message { chat } => {
|
Loaded::Message { chat } => {
|
||||||
// beside key- and member-changes, force re-gossip every 48 hours
|
// beside key- and member-changes, force re-gossip every 48 hours
|
||||||
let gossiped_timestamp = chat.get_gossiped_timestamp(self.context).await;
|
let gossiped_timestamp = chat.get_gossiped_timestamp(context).await;
|
||||||
if time() > gossiped_timestamp + (2 * 24 * 60 * 60) {
|
if time() > gossiped_timestamp + (2 * 24 * 60 * 60) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -335,11 +331,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn subject_str(&self) -> String {
|
async fn subject_str(&self, context: &Context) -> String {
|
||||||
match self.loaded {
|
match self.loaded {
|
||||||
Loaded::Message { ref chat } => {
|
Loaded::Message { ref chat } => {
|
||||||
if self.msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
if self.msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
||||||
stock_str::ac_setup_msg_subject(self.context).await
|
stock_str::ac_setup_msg_subject(context).await
|
||||||
} else if chat.typ == Chattype::Group {
|
} else if chat.typ == Chattype::Group {
|
||||||
let re = if self.in_reply_to.is_empty() {
|
let re = if self.in_reply_to.is_empty() {
|
||||||
""
|
""
|
||||||
@@ -371,22 +367,17 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let self_name = match self.context.get_config(Config::Displayname).await
|
let self_name = match context.get_config(Config::Displayname).await {
|
||||||
{
|
|
||||||
Some(name) => name,
|
Some(name) => name,
|
||||||
None => self
|
None => context.get_config(Config::Addr).await.unwrap_or_default(),
|
||||||
.context
|
|
||||||
.get_config(Config::Addr)
|
|
||||||
.await
|
|
||||||
.unwrap_or_default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
stock_str::subject_for_new_contact(self.context, self_name).await
|
stock_str::subject_for_new_contact(context, self_name).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loaded::MDN { .. } => stock_str::read_rcpt(self.context).await,
|
Loaded::MDN { .. } => stock_str::read_rcpt(context).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +388,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn render(mut self) -> Result<RenderedEmail, Error> {
|
pub async fn render(mut self, context: &Context) -> Result<RenderedEmail, Error> {
|
||||||
// Headers that are encrypted
|
// Headers that are encrypted
|
||||||
// - Chat-*, except Chat-Version
|
// - Chat-*, except Chat-Version
|
||||||
// - Secure-Join*
|
// - Secure-Join*
|
||||||
@@ -468,9 +459,9 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
let grpimage = self.grpimage();
|
let grpimage = self.grpimage();
|
||||||
let force_plaintext = self.should_force_plaintext();
|
let force_plaintext = self.should_force_plaintext();
|
||||||
let skip_autocrypt = self.should_skip_autocrypt();
|
let skip_autocrypt = self.should_skip_autocrypt();
|
||||||
let subject_str = self.subject_str().await;
|
let subject_str = self.subject_str(context).await;
|
||||||
let e2ee_guaranteed = self.is_e2ee_guaranteed();
|
let e2ee_guaranteed = self.is_e2ee_guaranteed();
|
||||||
let encrypt_helper = EncryptHelper::new(self.context).await?;
|
let encrypt_helper = EncryptHelper::new(context).await?;
|
||||||
|
|
||||||
let subject = if subject_str
|
let subject = if subject_str
|
||||||
.chars()
|
.chars()
|
||||||
@@ -496,7 +487,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
Loaded::MDN { .. } => dc_create_outgoing_rfc724_mid(None, &self.from_addr),
|
Loaded::MDN { .. } => dc_create_outgoing_rfc724_mid(None, &self.from_addr),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ephemeral_timer = self.msg.chat_id.get_ephemeral_timer(self.context).await?;
|
let ephemeral_timer = self.msg.chat_id.get_ephemeral_timer(context).await?;
|
||||||
if let EphemeralTimer::Enabled { duration } = ephemeral_timer {
|
if let EphemeralTimer::Enabled { duration } = ephemeral_timer {
|
||||||
protected_headers.push(Header::new(
|
protected_headers.push(Header::new(
|
||||||
"Ephemeral-Timer".to_string(),
|
"Ephemeral-Timer".to_string(),
|
||||||
@@ -522,15 +513,20 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
|
|
||||||
let (main_part, parts) = match self.loaded {
|
let (main_part, parts) = match self.loaded {
|
||||||
Loaded::Message { .. } => {
|
Loaded::Message { .. } => {
|
||||||
self.render_message(&mut protected_headers, &mut unprotected_headers, &grpimage)
|
self.render_message(
|
||||||
|
context,
|
||||||
|
&mut protected_headers,
|
||||||
|
&mut unprotected_headers,
|
||||||
|
&grpimage,
|
||||||
|
)
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
Loaded::MDN { .. } => (self.render_mdn().await?, Vec::new()),
|
Loaded::MDN { .. } => (self.render_mdn(context).await?, Vec::new()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let peerstates = self.peerstates_for_recipients().await?;
|
let peerstates = self.peerstates_for_recipients(context).await?;
|
||||||
let should_encrypt =
|
let should_encrypt =
|
||||||
encrypt_helper.should_encrypt(self.context, e2ee_guaranteed, &peerstates)?;
|
encrypt_helper.should_encrypt(context, e2ee_guaranteed, &peerstates)?;
|
||||||
let is_encrypted = should_encrypt && !force_plaintext;
|
let is_encrypted = should_encrypt && !force_plaintext;
|
||||||
|
|
||||||
let message = if parts.is_empty() {
|
let message = if parts.is_empty() {
|
||||||
@@ -553,7 +549,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
|
|
||||||
let outer_message = if is_encrypted {
|
let outer_message = if is_encrypted {
|
||||||
// Add gossip headers in chats with multiple recipients
|
// Add gossip headers in chats with multiple recipients
|
||||||
if peerstates.len() > 1 && self.should_do_gossip().await {
|
if peerstates.len() > 1 && self.should_do_gossip(context).await {
|
||||||
for peerstate in peerstates.iter().filter_map(|(state, _)| state.as_ref()) {
|
for peerstate in peerstates.iter().filter_map(|(state, _)| state.as_ref()) {
|
||||||
if peerstate.peek_key(min_verified).is_some() {
|
if peerstate.peek_key(min_verified).is_some() {
|
||||||
if let Some(header) = peerstate.render_gossip_header(min_verified) {
|
if let Some(header) = peerstate.render_gossip_header(min_verified) {
|
||||||
@@ -591,13 +587,13 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.fold(outer_message, |message, header| message.header(header));
|
.fold(outer_message, |message, header| message.header(header));
|
||||||
|
|
||||||
if std::env::var(crate::DCC_MIME_DEBUG).is_ok() {
|
if std::env::var(crate::DCC_MIME_DEBUG).is_ok() {
|
||||||
info!(self.context, "mimefactory: outgoing message mime:");
|
info!(context, "mimefactory: outgoing message mime:");
|
||||||
let raw_message = message.clone().build().as_string();
|
let raw_message = message.clone().build().as_string();
|
||||||
println!("{}", raw_message);
|
println!("{}", raw_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
let encrypted = encrypt_helper
|
let encrypted = encrypt_helper
|
||||||
.encrypt(self.context, min_verified, message, peerstates)
|
.encrypt(context, min_verified, message, peerstates)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
outer_message
|
outer_message
|
||||||
@@ -663,9 +659,9 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
Some(part)
|
Some(part)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_location_kml_part(&mut self) -> Result<PartBuilder, Error> {
|
async fn get_location_kml_part(&mut self, context: &Context) -> Result<PartBuilder, Error> {
|
||||||
let (kml_content, last_added_location_id) =
|
let (kml_content, last_added_location_id) =
|
||||||
location::get_kml(self.context, self.msg.chat_id).await?;
|
location::get_kml(context, self.msg.chat_id).await?;
|
||||||
let part = PartBuilder::new()
|
let part = PartBuilder::new()
|
||||||
.content_type(
|
.content_type(
|
||||||
&"application/vnd.google-earth.kml+xml"
|
&"application/vnd.google-earth.kml+xml"
|
||||||
@@ -687,11 +683,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
async fn render_message(
|
async fn render_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
context: &Context,
|
||||||
protected_headers: &mut Vec<Header>,
|
protected_headers: &mut Vec<Header>,
|
||||||
unprotected_headers: &mut Vec<Header>,
|
unprotected_headers: &mut Vec<Header>,
|
||||||
grpimage: &Option<String>,
|
grpimage: &Option<String>,
|
||||||
) -> Result<(PartBuilder, Vec<PartBuilder>), Error> {
|
) -> Result<(PartBuilder, Vec<PartBuilder>), Error> {
|
||||||
let context = self.context;
|
|
||||||
let chat = match &self.loaded {
|
let chat = match &self.loaded {
|
||||||
Loaded::Message { chat } => chat,
|
Loaded::Message { chat } => chat,
|
||||||
Loaded::MDN { .. } => bail!("Attempt to render MDN as a message"),
|
Loaded::MDN { .. } => bail!("Attempt to render MDN as a message"),
|
||||||
@@ -796,7 +792,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
unprotected_headers
|
unprotected_headers
|
||||||
.push(Header::new("Autocrypt-Setup-Message".into(), "v1".into()));
|
.push(Header::new("Autocrypt-Setup-Message".into(), "v1".into()));
|
||||||
|
|
||||||
placeholdertext = Some(stock_str::ac_setup_msg_body(self.context).await);
|
placeholdertext = Some(stock_str::ac_setup_msg_body(context).await);
|
||||||
}
|
}
|
||||||
SystemMessage::SecurejoinMessage => {
|
SystemMessage::SecurejoinMessage => {
|
||||||
let msg = &self.msg;
|
let msg = &self.msg;
|
||||||
@@ -848,7 +844,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(grpimage) = grpimage {
|
if let Some(grpimage) = grpimage {
|
||||||
info!(self.context, "setting group image '{}'", grpimage);
|
info!(context, "setting group image '{}'", grpimage);
|
||||||
let mut meta = Message {
|
let mut meta = Message {
|
||||||
viewtype: Viewtype::Image,
|
viewtype: Viewtype::Image,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -985,7 +981,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if location::is_sending_locations_to_chat(context, Some(self.msg.chat_id)).await {
|
if location::is_sending_locations_to_chat(context, Some(self.msg.chat_id)).await {
|
||||||
match self.get_location_kml_part().await {
|
match self.get_location_kml_part(context).await {
|
||||||
Ok(part) => parts.push(part),
|
Ok(part) => parts.push(part),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(context, "mimefactory: could not send location: {}", err);
|
warn!(context, "mimefactory: could not send location: {}", err);
|
||||||
@@ -1010,7 +1006,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Render an MDN
|
/// Render an MDN
|
||||||
async fn render_mdn(&mut self) -> Result<PartBuilder, Error> {
|
async fn render_mdn(&mut self, context: &Context) -> Result<PartBuilder, Error> {
|
||||||
// RFC 6522, this also requires the `report-type` parameter which is equal
|
// RFC 6522, this also requires the `report-type` parameter which is equal
|
||||||
// to the MIME subtype of the second body part of the multipart/report
|
// to the MIME subtype of the second body part of the multipart/report
|
||||||
//
|
//
|
||||||
@@ -1043,11 +1039,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.get_int(Param::GuaranteeE2ee)
|
.get_int(Param::GuaranteeE2ee)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
stock_str::encrypted_msg(self.context).await
|
stock_str::encrypted_msg(context).await
|
||||||
} else {
|
} else {
|
||||||
self.msg.get_summarytext(self.context, 32).await
|
self.msg.get_summarytext(context, 32).await
|
||||||
};
|
};
|
||||||
let p2 = stock_str::read_rcpt_mail_body(self.context, p1).await;
|
let p2 = stock_str::read_rcpt_mail_body(context, p1).await;
|
||||||
let message_text = format!("{}\r\n", p2);
|
let message_text = format!("{}\r\n", p2);
|
||||||
message = message.child(
|
message = message.child(
|
||||||
PartBuilder::new()
|
PartBuilder::new()
|
||||||
@@ -1500,7 +1496,7 @@ mod tests {
|
|||||||
\n", &t).await;
|
\n", &t).await;
|
||||||
let mf = MimeFactory::from_msg(&t, &new_msg, false).await.unwrap();
|
let mf = MimeFactory::from_msg(&t, &new_msg, false).await.unwrap();
|
||||||
// The subject string should not be "Re: message opened"
|
// The subject string should not be "Re: message opened"
|
||||||
assert_eq!("Re: Hello, Charlie", mf.subject_str().await);
|
assert_eq!("Re: Hello, Charlie", mf.subject_str(&t).await);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn first_subject_str(t: TestContext) -> String {
|
async fn first_subject_str(t: TestContext) -> String {
|
||||||
@@ -1519,14 +1515,14 @@ mod tests {
|
|||||||
|
|
||||||
let mf = MimeFactory::from_msg(&t, &new_msg, false).await.unwrap();
|
let mf = MimeFactory::from_msg(&t, &new_msg, false).await.unwrap();
|
||||||
|
|
||||||
mf.subject_str().await
|
mf.subject_str(&t).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn msg_to_subject_str(imf_raw: &[u8]) -> String {
|
async fn msg_to_subject_str(imf_raw: &[u8]) -> String {
|
||||||
let t = TestContext::new_alice().await;
|
let t = TestContext::new_alice().await;
|
||||||
let new_msg = incoming_msg_to_reply_msg(imf_raw, &t).await;
|
let new_msg = incoming_msg_to_reply_msg(imf_raw, &t).await;
|
||||||
let mf = MimeFactory::from_msg(&t, &new_msg, false).await.unwrap();
|
let mf = MimeFactory::from_msg(&t, &new_msg, false).await.unwrap();
|
||||||
mf.subject_str().await
|
mf.subject_str(&t).await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a `Message` that replies "Hi" to the incoming email in `imf_raw`.
|
// Creates a `Message` that replies "Hi" to the incoming email in `imf_raw`.
|
||||||
@@ -1581,7 +1577,7 @@ mod tests {
|
|||||||
let recipients = mimefactory.recipients();
|
let recipients = mimefactory.recipients();
|
||||||
assert_eq!(recipients, vec!["charlie@example.com"]);
|
assert_eq!(recipients, vec!["charlie@example.com"]);
|
||||||
|
|
||||||
let rendered_msg = mimefactory.render().await.unwrap();
|
let rendered_msg = mimefactory.render(context).await.unwrap();
|
||||||
|
|
||||||
let mail = mailparse::parse_mail(&rendered_msg.message).unwrap();
|
let mail = mailparse::parse_mail(&rendered_msg.message).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -1172,7 +1172,7 @@ async fn update_gossip_peerstates(
|
|||||||
peerstate.apply_gossip(header, message_time);
|
peerstate.apply_gossip(header, message_time);
|
||||||
peerstate.save_to_db(&context.sql, false).await?;
|
peerstate.save_to_db(&context.sql, false).await?;
|
||||||
} else {
|
} else {
|
||||||
let p = Peerstate::from_gossip(context, header, message_time);
|
let p = Peerstate::from_gossip(header, message_time);
|
||||||
p.save_to_db(&context.sql, true).await?;
|
p.save_to_db(&context.sql, true).await?;
|
||||||
peerstate = Some(p);
|
peerstate = Some(p);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ pub enum PeerstateVerifiedStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Peerstate represents the state of an Autocrypt peer.
|
/// Peerstate represents the state of an Autocrypt peer.
|
||||||
pub struct Peerstate<'a> {
|
pub struct Peerstate {
|
||||||
pub context: &'a Context,
|
|
||||||
pub addr: String,
|
pub addr: String,
|
||||||
pub last_seen: i64,
|
pub last_seen: i64,
|
||||||
pub last_seen_autocrypt: i64,
|
pub last_seen_autocrypt: i64,
|
||||||
@@ -47,7 +46,7 @@ pub struct Peerstate<'a> {
|
|||||||
pub fingerprint_changed: bool,
|
pub fingerprint_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PartialEq for Peerstate<'a> {
|
impl PartialEq for Peerstate {
|
||||||
fn eq(&self, other: &Peerstate) -> bool {
|
fn eq(&self, other: &Peerstate) -> bool {
|
||||||
self.addr == other.addr
|
self.addr == other.addr
|
||||||
&& self.last_seen == other.last_seen
|
&& self.last_seen == other.last_seen
|
||||||
@@ -65,9 +64,9 @@ impl<'a> PartialEq for Peerstate<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Eq for Peerstate<'a> {}
|
impl Eq for Peerstate {}
|
||||||
|
|
||||||
impl<'a> fmt::Debug for Peerstate<'a> {
|
impl fmt::Debug for Peerstate {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.debug_struct("Peerstate")
|
f.debug_struct("Peerstate")
|
||||||
.field("addr", &self.addr)
|
.field("addr", &self.addr)
|
||||||
@@ -94,10 +93,9 @@ pub enum ToSave {
|
|||||||
All = 0x02,
|
All = 0x02,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Peerstate<'a> {
|
impl Peerstate {
|
||||||
pub fn from_header(context: &'a Context, header: &Aheader, message_time: i64) -> Self {
|
pub fn from_header(header: &Aheader, message_time: i64) -> Self {
|
||||||
Peerstate {
|
Peerstate {
|
||||||
context,
|
|
||||||
addr: header.addr.clone(),
|
addr: header.addr.clone(),
|
||||||
last_seen: message_time,
|
last_seen: message_time,
|
||||||
last_seen_autocrypt: message_time,
|
last_seen_autocrypt: message_time,
|
||||||
@@ -114,9 +112,8 @@ impl<'a> Peerstate<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_gossip(context: &'a Context, gossip_header: &Aheader, message_time: i64) -> Self {
|
pub fn from_gossip(gossip_header: &Aheader, message_time: i64) -> Self {
|
||||||
Peerstate {
|
Peerstate {
|
||||||
context,
|
|
||||||
addr: gossip_header.addr.clone(),
|
addr: gossip_header.addr.clone(),
|
||||||
last_seen: 0,
|
last_seen: 0,
|
||||||
last_seen_autocrypt: 0,
|
last_seen_autocrypt: 0,
|
||||||
@@ -141,7 +138,7 @@ impl<'a> Peerstate<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn from_addr(context: &'a Context, addr: &str) -> Result<Option<Peerstate<'a>>> {
|
pub async fn from_addr(context: &Context, addr: &str) -> Result<Option<Peerstate>> {
|
||||||
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
|
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
|
||||||
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
|
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
|
||||||
verified_key, verified_key_fingerprint \
|
verified_key, verified_key_fingerprint \
|
||||||
@@ -151,10 +148,10 @@ impl<'a> Peerstate<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn from_fingerprint(
|
pub async fn from_fingerprint(
|
||||||
context: &'a Context,
|
context: &Context,
|
||||||
_sql: &Sql,
|
_sql: &Sql,
|
||||||
fingerprint: &Fingerprint,
|
fingerprint: &Fingerprint,
|
||||||
) -> Result<Option<Peerstate<'a>>> {
|
) -> Result<Option<Peerstate>> {
|
||||||
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
|
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
|
||||||
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
|
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
|
||||||
verified_key, verified_key_fingerprint \
|
verified_key, verified_key_fingerprint \
|
||||||
@@ -167,10 +164,10 @@ impl<'a> Peerstate<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn from_stmt(
|
async fn from_stmt(
|
||||||
context: &'a Context,
|
context: &Context,
|
||||||
query: &str,
|
query: &str,
|
||||||
params: Vec<&dyn crate::ToSql>,
|
params: Vec<&dyn crate::ToSql>,
|
||||||
) -> Result<Option<Peerstate<'a>>> {
|
) -> Result<Option<Peerstate>> {
|
||||||
let peerstate = context
|
let peerstate = context
|
||||||
.sql
|
.sql
|
||||||
.query_row_optional(query, params, |row| {
|
.query_row_optional(query, params, |row| {
|
||||||
@@ -181,7 +178,6 @@ impl<'a> Peerstate<'a> {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
let res = Peerstate {
|
let res = Peerstate {
|
||||||
context,
|
|
||||||
addr: row.get(0)?,
|
addr: row.get(0)?,
|
||||||
last_seen: row.get(1)?,
|
last_seen: row.get(1)?,
|
||||||
last_seen_autocrypt: row.get(2)?,
|
last_seen_autocrypt: row.get(2)?,
|
||||||
@@ -505,7 +501,6 @@ mod tests {
|
|||||||
let pub_key = alice_keypair().public;
|
let pub_key = alice_keypair().public;
|
||||||
|
|
||||||
let mut peerstate = Peerstate {
|
let mut peerstate = Peerstate {
|
||||||
context: &ctx.ctx,
|
|
||||||
addr: addr.into(),
|
addr: addr.into(),
|
||||||
last_seen: 10,
|
last_seen: 10,
|
||||||
last_seen_autocrypt: 11,
|
last_seen_autocrypt: 11,
|
||||||
@@ -549,7 +544,6 @@ mod tests {
|
|||||||
let pub_key = alice_keypair().public;
|
let pub_key = alice_keypair().public;
|
||||||
|
|
||||||
let peerstate = Peerstate {
|
let peerstate = Peerstate {
|
||||||
context: &ctx.ctx,
|
|
||||||
addr: addr.into(),
|
addr: addr.into(),
|
||||||
last_seen: 10,
|
last_seen: 10,
|
||||||
last_seen_autocrypt: 11,
|
last_seen_autocrypt: 11,
|
||||||
@@ -583,7 +577,6 @@ mod tests {
|
|||||||
let pub_key = alice_keypair().public;
|
let pub_key = alice_keypair().public;
|
||||||
|
|
||||||
let mut peerstate = Peerstate {
|
let mut peerstate = Peerstate {
|
||||||
context: &ctx.ctx,
|
|
||||||
addr: addr.into(),
|
addr: addr.into(),
|
||||||
last_seen: 10,
|
last_seen: 10,
|
||||||
last_seen_autocrypt: 11,
|
last_seen_autocrypt: 11,
|
||||||
@@ -644,13 +637,11 @@ mod tests {
|
|||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn test_peerstate_degrade_reordering() {
|
async fn test_peerstate_degrade_reordering() {
|
||||||
let context = crate::test_utils::TestContext::new().await.ctx;
|
|
||||||
let addr = "example@example.org";
|
let addr = "example@example.org";
|
||||||
let pub_key = alice_keypair().public;
|
let pub_key = alice_keypair().public;
|
||||||
let header = Aheader::new(addr.to_string(), pub_key, EncryptPreference::Mutual);
|
let header = Aheader::new(addr.to_string(), pub_key, EncryptPreference::Mutual);
|
||||||
|
|
||||||
let mut peerstate = Peerstate {
|
let mut peerstate = Peerstate {
|
||||||
context: &context,
|
|
||||||
addr: addr.to_string(),
|
addr: addr.to_string(),
|
||||||
last_seen: 0,
|
last_seen: 0,
|
||||||
last_seen_autocrypt: 0,
|
last_seen_autocrypt: 0,
|
||||||
|
|||||||
@@ -1124,7 +1124,6 @@ mod tests {
|
|||||||
// Ensure Bob knows Alice_FP
|
// Ensure Bob knows Alice_FP
|
||||||
let alice_pubkey = SignedPublicKey::load_self(&alice.ctx).await.unwrap();
|
let alice_pubkey = SignedPublicKey::load_self(&alice.ctx).await.unwrap();
|
||||||
let peerstate = Peerstate {
|
let peerstate = Peerstate {
|
||||||
context: &bob.ctx,
|
|
||||||
addr: "alice@example.com".into(),
|
addr: "alice@example.com".into(),
|
||||||
last_seen: 10,
|
last_seen: 10,
|
||||||
last_seen_autocrypt: 10,
|
last_seen_autocrypt: 10,
|
||||||
|
|||||||
Reference in New Issue
Block a user