mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Merge remote-tracking branch 'origin/master' into feat/async-jobs
This commit is contained in:
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,5 +1,19 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.28.0
|
||||||
|
|
||||||
|
- new flag DC_GCL_FOR_FORWARDING for dc_get_chatlist()
|
||||||
|
that will sort the "saved messages" chat to the top of the chatlist #1336
|
||||||
|
- mark mails as being deleted from server in dc_empty_server() #1333
|
||||||
|
- fix interaction with servers that do not allow folder creation on root-level;
|
||||||
|
use path separator as defined by the email server #1359
|
||||||
|
- fix group creation if group was created by non-delta clients #1357
|
||||||
|
- fix showing replies from non-delta clients #1353
|
||||||
|
- fix member list on rejoining left groups #1343
|
||||||
|
- fix crash when using empty groups #1354
|
||||||
|
- fix potential crash on special names #1350
|
||||||
|
|
||||||
|
|
||||||
## 1.27.0
|
## 1.27.0
|
||||||
|
|
||||||
- handle keys reliably on armv7 #1327
|
- handle keys reliably on armv7 #1327
|
||||||
|
|||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -650,7 +650,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deltachat"
|
name = "deltachat"
|
||||||
version = "1.27.0"
|
version = "1.28.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"async-imap 0.2.0 (git+https://github.com/async-email/async-imap?branch=feat/send)",
|
"async-imap 0.2.0 (git+https://github.com/async-email/async-imap?branch=feat/send)",
|
||||||
@@ -720,10 +720,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deltachat_ffi"
|
name = "deltachat_ffi"
|
||||||
version = "1.27.0"
|
version = "1.28.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"async-std 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"deltachat 1.27.0",
|
"deltachat 1.28.0",
|
||||||
"failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "deltachat"
|
name = "deltachat"
|
||||||
version = "1.27.0"
|
version = "1.28.0"
|
||||||
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "deltachat_ffi"
|
name = "deltachat_ffi"
|
||||||
version = "1.27.0"
|
version = "1.28.0"
|
||||||
description = "Deltachat FFI"
|
description = "Deltachat FFI"
|
||||||
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|||||||
@@ -76,6 +76,20 @@ class TestOfflineAccountBasic:
|
|||||||
with pytest.raises(KeyError):
|
with pytest.raises(KeyError):
|
||||||
ac1.get_config("123123")
|
ac1.get_config("123123")
|
||||||
|
|
||||||
|
def test_empty_group_bcc_self_enabled(self, acfactory):
|
||||||
|
ac1 = acfactory.get_configured_offline_account()
|
||||||
|
ac1.set_config("bcc_self", "1")
|
||||||
|
chat = ac1.create_group_chat(name="group1")
|
||||||
|
msg = chat.send_text("msg1")
|
||||||
|
assert msg in chat.get_messages()
|
||||||
|
|
||||||
|
def test_empty_group_bcc_self_disabled(self, acfactory):
|
||||||
|
ac1 = acfactory.get_configured_offline_account()
|
||||||
|
ac1.set_config("bcc_self", "0")
|
||||||
|
chat = ac1.create_group_chat(name="group1")
|
||||||
|
msg = chat.send_text("msg1")
|
||||||
|
assert msg in chat.get_messages()
|
||||||
|
|
||||||
|
|
||||||
class TestOfflineContact:
|
class TestOfflineContact:
|
||||||
def test_contact_attr(self, acfactory):
|
def test_contact_attr(self, acfactory):
|
||||||
|
|||||||
@@ -412,9 +412,11 @@ async fn exec_step(
|
|||||||
}
|
}
|
||||||
16 => {
|
16 => {
|
||||||
progress!(ctx, 900);
|
progress!(ctx, 900);
|
||||||
|
|
||||||
let create_mvbox = ctx.get_config_bool(Config::MvboxWatch).await
|
let create_mvbox = ctx.get_config_bool(Config::MvboxWatch).await
|
||||||
|| ctx.get_config_bool(Config::MvboxMove).await;
|
|| ctx.get_config_bool(Config::MvboxMove).await;
|
||||||
if let Err(err) = imap.ensure_configured_folders(ctx, create_mvbox).await {
|
|
||||||
|
if let Err(err) = imap.configure_folders(ctx, create_mvbox).await {
|
||||||
bail!("configuring folders failed: {:?}", err);
|
bail!("configuring folders failed: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,6 +214,9 @@ pub const DC_BOB_SUCCESS: i32 = 1;
|
|||||||
// max. width/height of an avatar
|
// max. width/height of an avatar
|
||||||
pub const AVATAR_SIZE: u32 = 192;
|
pub const AVATAR_SIZE: u32 = 192;
|
||||||
|
|
||||||
|
// this value can be increased if the folder configuration is changed and must be redone on next program start
|
||||||
|
pub const DC_FOLDERS_CONFIGURED_VERSION: i32 = 3;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Display,
|
Display,
|
||||||
|
|||||||
@@ -402,7 +402,11 @@ async fn add_parts(
|
|||||||
let (new_chat_id, new_chat_id_blocked) = create_or_lookup_group(
|
let (new_chat_id, new_chat_id_blocked) = create_or_lookup_group(
|
||||||
context,
|
context,
|
||||||
&mut mime_parser,
|
&mut mime_parser,
|
||||||
allow_creation,
|
if test_normal_chat_id.is_unset() {
|
||||||
|
allow_creation
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
},
|
||||||
create_blocked,
|
create_blocked,
|
||||||
from_id,
|
from_id,
|
||||||
to_ids,
|
to_ids,
|
||||||
@@ -1715,8 +1719,9 @@ fn dc_create_incoming_rfc724_mid(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::chatlist::Chatlist;
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
use crate::test_utils::dummy_context;
|
use crate::test_utils::{dummy_context, TestContext};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hex_hash() {
|
fn test_hex_hash() {
|
||||||
@@ -1811,4 +1816,179 @@ mod tests {
|
|||||||
assert!(is_msgrmsg_rfc724_mid(&t.ctx, &msg.rfc724_mid).await);
|
assert!(is_msgrmsg_rfc724_mid(&t.ctx, &msg.rfc724_mid).await);
|
||||||
assert!(!is_msgrmsg_rfc724_mid(&t.ctx, "nonexistant@message.id").await);
|
assert!(!is_msgrmsg_rfc724_mid(&t.ctx, "nonexistant@message.id").await);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn configured_offline_context() -> TestContext {
|
||||||
|
let t = dummy_context().await;
|
||||||
|
t.ctx
|
||||||
|
.set_config(Config::Addr, Some("alice@example.org"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
t.ctx
|
||||||
|
.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
t.ctx
|
||||||
|
.set_config(Config::Configured, Some("1"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
t
|
||||||
|
}
|
||||||
|
|
||||||
|
static MSGRMSG: &[u8] = b"From: Bob <bob@example.org>\n\
|
||||||
|
To: alice@example.org\n\
|
||||||
|
Chat-Version: 1.0\n\
|
||||||
|
Subject: Chat: hello\n\
|
||||||
|
Message-ID: <Mr.1111@example.org>\n\
|
||||||
|
Date: Sun, 22 Mar 2020 22:37:55 +0000\n\
|
||||||
|
\n\
|
||||||
|
hello\n";
|
||||||
|
|
||||||
|
static ONETOONE_NOREPLY_MAIL: &[u8] = b"From: Bob <bob@example.org>\n\
|
||||||
|
To: alice@example.org\n\
|
||||||
|
Subject: Chat: hello\n\
|
||||||
|
Message-ID: <2222@example.org>\n\
|
||||||
|
Date: Sun, 22 Mar 2020 22:37:56 +0000\n\
|
||||||
|
\n\
|
||||||
|
hello\n";
|
||||||
|
|
||||||
|
static GRP_MAIL: &[u8] = b"From: bob@example.org\n\
|
||||||
|
To: alice@example.org, claire@example.org\n\
|
||||||
|
Subject: group with Alice, Bob and Claire\n\
|
||||||
|
Message-ID: <3333@example.org>\n\
|
||||||
|
Date: Sun, 22 Mar 2020 22:37:57 +0000\n\
|
||||||
|
\n\
|
||||||
|
hello\n";
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_adhoc_group_show_chats_only() {
|
||||||
|
let t = configured_offline_context().await;
|
||||||
|
assert_eq!(t.ctx.get_config_int(Config::ShowEmails).await, 0);
|
||||||
|
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 0);
|
||||||
|
|
||||||
|
dc_receive_imf(&t.ctx, MSGRMSG, "INBOX", 1, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 1);
|
||||||
|
|
||||||
|
dc_receive_imf(&t.ctx, ONETOONE_NOREPLY_MAIL, "INBOX", 1, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 1);
|
||||||
|
|
||||||
|
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_adhoc_group_show_accepted_contact_unknown() {
|
||||||
|
let t = configured_offline_context().await;
|
||||||
|
t.ctx
|
||||||
|
.set_config(Config::ShowEmails, Some("1"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// adhoc-group with unknown contacts with show_emails=accepted is ignored for unknown contacts
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_adhoc_group_show_accepted_contact_known() {
|
||||||
|
let t = configured_offline_context().await;
|
||||||
|
t.ctx
|
||||||
|
.set_config(Config::ShowEmails, Some("1"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
Contact::create(&t.ctx, "Bob", "bob@example.org")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// adhoc-group with known contacts with show_emails=accepted is still ignored for known contacts
|
||||||
|
// (and existent chat is required)
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_adhoc_group_show_accepted_contact_accepted() {
|
||||||
|
let t = configured_offline_context().await;
|
||||||
|
t.ctx
|
||||||
|
.set_config(Config::ShowEmails, Some("1"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// accept Bob by accepting a delta-message from Bob
|
||||||
|
dc_receive_imf(&t.ctx, MSGRMSG, "INBOX", 1, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 1);
|
||||||
|
assert!(chats.get_chat_id(0).is_deaddrop());
|
||||||
|
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(!chat_id.is_special());
|
||||||
|
let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap();
|
||||||
|
assert_eq!(chat.typ, Chattype::Single);
|
||||||
|
assert_eq!(chat.name, "Bob");
|
||||||
|
assert_eq!(chat::get_chat_contacts(&t.ctx, chat_id).await.len(), 1);
|
||||||
|
assert_eq!(chat::get_chat_msgs(&t.ctx, chat_id, 0, None).await.len(), 1);
|
||||||
|
|
||||||
|
// receive a non-delta-message from Bob, shows up because of the show_emails setting
|
||||||
|
dc_receive_imf(&t.ctx, ONETOONE_NOREPLY_MAIL, "INBOX", 2, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(chat::get_chat_msgs(&t.ctx, chat_id, 0, None).await.len(), 2);
|
||||||
|
|
||||||
|
// let Bob create an adhoc-group by a non-delta-message, shows up because of the show_emails setting
|
||||||
|
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 3, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 2);
|
||||||
|
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap();
|
||||||
|
assert_eq!(chat.typ, Chattype::Group);
|
||||||
|
assert_eq!(chat.name, "group with Alice, Bob and Claire");
|
||||||
|
assert_eq!(chat::get_chat_contacts(&t.ctx, chat_id).await.len(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_adhoc_group_show_all() {
|
||||||
|
let t = configured_offline_context().await;
|
||||||
|
t.ctx
|
||||||
|
.set_config(Config::ShowEmails, Some("2"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// adhoc-group with unknown contacts with show_emails=all will show up in the deaddrop
|
||||||
|
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
|
||||||
|
assert_eq!(chats.len(), 1);
|
||||||
|
assert!(chats.get_chat_id(0).is_deaddrop());
|
||||||
|
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap();
|
||||||
|
assert_eq!(chat.typ, Chattype::Group);
|
||||||
|
assert_eq!(chat.name, "group with Alice, Bob and Claire");
|
||||||
|
assert_eq!(chat::get_chat_contacts(&t.ctx, chat_id).await.len(), 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,7 +187,6 @@ struct ImapConfig {
|
|||||||
/// True if the server has MOVE capability as defined in
|
/// True if the server has MOVE capability as defined in
|
||||||
/// https://tools.ietf.org/html/rfc6851
|
/// https://tools.ietf.org/html/rfc6851
|
||||||
pub can_move: bool,
|
pub can_move: bool,
|
||||||
pub imap_delimiter: char,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ImapConfig {
|
impl Default for ImapConfig {
|
||||||
@@ -205,7 +204,6 @@ impl Default for ImapConfig {
|
|||||||
selected_folder_needs_expunge: false,
|
selected_folder_needs_expunge: false,
|
||||||
can_idle: false,
|
can_idle: false,
|
||||||
can_move: false,
|
can_move: false,
|
||||||
imap_delimiter: '.',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1111,17 +1109,17 @@ impl Imap {
|
|||||||
.sql
|
.sql
|
||||||
.get_raw_config_int(context, "folders_configured")
|
.get_raw_config_int(context, "folders_configured")
|
||||||
.await;
|
.await;
|
||||||
if folders_configured.unwrap_or_default() >= 3 {
|
if folders_configured.unwrap_or_default() >= DC_FOLDERS_CONFIGURED_VERSION {
|
||||||
info!(context, "IMAP-folders already configured");
|
|
||||||
// the "3" here we increase if we have future updates to
|
|
||||||
// to folder configuration
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.configure_folders(context, create_mvbox).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn configure_folders(&mut self, context: &Context, create_mvbox: bool) -> Result<()> {
|
||||||
if !self.is_connected() {
|
if !self.is_connected() {
|
||||||
return Err(Error::NoConnection);
|
return Err(Error::NoConnection);
|
||||||
}
|
}
|
||||||
info!(context, "Configuring IMAP-folders.");
|
|
||||||
|
|
||||||
if let Some(ref mut session) = &mut self.session {
|
if let Some(ref mut session) = &mut self.session {
|
||||||
let mut folders = match session.list(Some(""), Some("*")).await {
|
let mut folders = match session.list(Some(""), Some("*")).await {
|
||||||
@@ -1133,7 +1131,17 @@ impl Imap {
|
|||||||
|
|
||||||
let mut sentbox_folder = None;
|
let mut sentbox_folder = None;
|
||||||
let mut mvbox_folder = None;
|
let mut mvbox_folder = None;
|
||||||
let delimiter = self.config.imap_delimiter;
|
|
||||||
|
let mut delimiter = ".".to_string();
|
||||||
|
if let Some(folder) = folders.next().await {
|
||||||
|
let folder = folder.map_err(|err| Error::Other(err.to_string()))?;
|
||||||
|
if let Some(d) = folder.delimiter() {
|
||||||
|
if !d.is_empty() {
|
||||||
|
delimiter = d.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!(context, "Using \"{}\" as folder-delimiter.", delimiter);
|
||||||
let fallback_folder = format!("INBOX{}DeltaChat", delimiter);
|
let fallback_folder = format!("INBOX{}DeltaChat", delimiter);
|
||||||
|
|
||||||
while let Some(folder) = folders.next().await {
|
while let Some(folder) = folders.next().await {
|
||||||
@@ -1221,9 +1229,14 @@ impl Imap {
|
|||||||
}
|
}
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.set_raw_config_int(context, "folders_configured", 3)
|
.set_raw_config_int(context, "folders_configured", DC_FOLDERS_CONFIGURED_VERSION)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
context
|
||||||
|
.sql
|
||||||
|
.set_raw_config_int(context, "folders_configured", 3)
|
||||||
|
.await?;
|
||||||
|
|
||||||
info!(context, "FINISHED configuring IMAP-folders.");
|
info!(context, "FINISHED configuring IMAP-folders.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
self.from_addr.clone(),
|
self.from_addr.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut to = Vec::with_capacity(self.recipients.len());
|
let mut to = Vec::new();
|
||||||
for (name, addr) in self.recipients.iter() {
|
for (name, addr) in self.recipients.iter() {
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
to.push(Address::new_mailbox(addr.clone()));
|
to.push(Address::new_mailbox(addr.clone()));
|
||||||
@@ -420,6 +420,10 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if to.is_empty() {
|
||||||
|
to.push(from.clone());
|
||||||
|
}
|
||||||
|
|
||||||
if !self.references.is_empty() {
|
if !self.references.is_empty() {
|
||||||
unprotected_headers.push(Header::new("References".into(), self.references.clone()));
|
unprotected_headers.push(Header::new("References".into(), self.references.clone()));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user