mirror of
https://github.com/chatmail/core.git
synced 2026-04-21 15:36:30 +03:00
Merge remote-tracking branch 'origin/master' into feat/async-jobs
This commit is contained in:
@@ -1742,8 +1742,7 @@ pub async fn delete_device_expired_messages(context: &Context) -> Result<bool, E
|
||||
WHERE timestamp < ? \
|
||||
AND chat_id > ? \
|
||||
AND chat_id != ? \
|
||||
AND chat_id != ? \
|
||||
AND NOT hidden",
|
||||
AND chat_id != ?",
|
||||
paramsv![
|
||||
DC_CHAT_ID_TRASH,
|
||||
threshold_timestamp,
|
||||
|
||||
@@ -84,6 +84,7 @@ impl Context {
|
||||
let (_s, r) = async_std::sync::channel(1);
|
||||
let mut imap = Imap::new(r);
|
||||
let mut is_imap_connected = false;
|
||||
let was_configured_before = self.is_configured().await;
|
||||
|
||||
while !self.shall_stop_ongoing().await {
|
||||
step_counter += 1;
|
||||
@@ -121,6 +122,15 @@ impl Context {
|
||||
}
|
||||
|
||||
if let Some(provider) = provider::get_provider_info(¶m.addr) {
|
||||
if !was_configured_before {
|
||||
if let Some(config_defaults) = &provider.config_defaults {
|
||||
for def in config_defaults.iter() {
|
||||
info!(self, "apply config_defaults {}={}", def.key, def.value);
|
||||
self.set_config(def.key, Some(def.value)).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !provider.after_login_hint.is_empty() {
|
||||
let mut msg = Message::new(Viewtype::Text);
|
||||
msg.text = Some(provider.after_login_hint.to_string());
|
||||
|
||||
@@ -252,7 +252,11 @@ impl Context {
|
||||
.get_raw_config_int(self, "dbversion")
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
let journal_mode = self
|
||||
.sql
|
||||
.query_get_value(self, "PRAGMA journal_mode;", paramsv![])
|
||||
.await
|
||||
.unwrap_or_else(|| "unknown".to_string());
|
||||
let e2ee_enabled = self.get_config_int(Config::E2eeEnabled).await;
|
||||
let mdns_enabled = self.get_config_int(Config::MdnsEnabled).await;
|
||||
let bcc_self = self.get_config_int(Config::BccSelf).await;
|
||||
@@ -299,6 +303,7 @@ impl Context {
|
||||
res.insert("number_of_contacts", contacts.to_string());
|
||||
res.insert("database_dir", self.get_dbfile().display().to_string());
|
||||
res.insert("database_version", dbversion.to_string());
|
||||
res.insert("journal_mode", journal_mode);
|
||||
res.insert("blobdir", self.get_blobdir().display().to_string());
|
||||
res.insert("display_name", displayname.unwrap_or_else(|| unset.into()));
|
||||
res.insert(
|
||||
|
||||
@@ -134,7 +134,7 @@ impl async_imap::Authenticator for OAuth2 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum FolderMeaning {
|
||||
Unknown,
|
||||
SentObjects,
|
||||
@@ -1124,7 +1124,8 @@ impl Imap {
|
||||
|
||||
if sentbox_folder.is_none() {
|
||||
if let FolderMeaning::SentObjects = get_folder_meaning(&folder) {
|
||||
info!(context, "sentbox folder is {:?}", folder);
|
||||
sentbox_folder = Some(folder);
|
||||
} else if let FolderMeaning::SentObjects = get_folder_meaning_by_name(&folder) {
|
||||
sentbox_folder = Some(folder);
|
||||
}
|
||||
}
|
||||
@@ -1133,6 +1134,7 @@ impl Imap {
|
||||
break;
|
||||
}
|
||||
}
|
||||
info!(context, "sentbox folder is {:?}", sentbox_folder);
|
||||
|
||||
drop(folders);
|
||||
|
||||
@@ -1258,7 +1260,7 @@ impl Imap {
|
||||
// CAVE: if possible, take care not to add a name here that is "sent" in one language
|
||||
// but sth. different in others - a hard job.
|
||||
fn get_folder_meaning_by_name(folder_name: &Name) -> FolderMeaning {
|
||||
let sent_names = vec!["sent", "sent objects", "gesendet"];
|
||||
let sent_names = vec!["sent", "sentmail", "sent objects", "gesendet"];
|
||||
let lower = folder_name.name().to_lowercase();
|
||||
|
||||
if sent_names.into_iter().any(|s| s == lower) {
|
||||
@@ -1269,27 +1271,18 @@ fn get_folder_meaning_by_name(folder_name: &Name) -> FolderMeaning {
|
||||
}
|
||||
|
||||
fn get_folder_meaning(folder_name: &Name) -> FolderMeaning {
|
||||
if folder_name.attributes().is_empty() {
|
||||
return FolderMeaning::Unknown;
|
||||
}
|
||||
|
||||
let mut res = FolderMeaning::Unknown;
|
||||
let special_names = vec!["\\Spam", "\\Trash", "\\Drafts", "\\Junk"];
|
||||
|
||||
for attr in folder_name.attributes() {
|
||||
if let NameAttribute::Custom(ref label) = attr {
|
||||
if special_names.iter().any(|s| *s == label) {
|
||||
res = FolderMeaning::Other;
|
||||
return FolderMeaning::Other;
|
||||
} else if label == "\\Sent" {
|
||||
res = FolderMeaning::SentObjects
|
||||
return FolderMeaning::SentObjects;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match res {
|
||||
FolderMeaning::Unknown => get_folder_meaning_by_name(folder_name),
|
||||
_ => res,
|
||||
}
|
||||
FolderMeaning::Unknown
|
||||
}
|
||||
|
||||
async fn precheck_imf(
|
||||
|
||||
@@ -18,6 +18,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: STARTTLS, hostname: "newyear.aktivix.org", port: 143, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "newyear.aktivix.org", port: 25, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// aol.md: aol.com
|
||||
@@ -28,6 +29,7 @@ lazy_static::lazy_static! {
|
||||
overview_page: "https://providers.delta.chat/aol",
|
||||
server: vec![
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// autistici.org.md: autistici.org
|
||||
@@ -40,6 +42,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "mail.autistici.org", port: 993, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: SSL, hostname: "smtp.autistici.org", port: 465, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// bluewin.ch.md: bluewin.ch
|
||||
@@ -52,6 +55,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "imaps.bluewin.ch", port: 993, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: SSL, hostname: "smtpauths.bluewin.ch", port: 465, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// comcast.md: xfinity.com, comcast.net
|
||||
@@ -73,6 +77,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "imap.example.com", port: 1337, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "smtp.example.com", port: 1337, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// fastmail.md: fastmail.com
|
||||
@@ -83,6 +88,7 @@ lazy_static::lazy_static! {
|
||||
overview_page: "https://providers.delta.chat/fastmail",
|
||||
server: vec![
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// freenet.de.md: freenet.de
|
||||
@@ -95,6 +101,7 @@ lazy_static::lazy_static! {
|
||||
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,
|
||||
};
|
||||
|
||||
// gmail.md: gmail.com, googlemail.com
|
||||
@@ -107,6 +114,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "imap.gmail.com", port: 993, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: SSL, hostname: "smtp.gmail.com", port: 465, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// gmx.net.md: gmx.net, gmx.de, gmx.at, gmx.ch, gmx.org, gmx.eu, gmx.info, gmx.biz, gmx.com
|
||||
@@ -120,6 +128,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: SMTP, socket: SSL, hostname: "mail.gmx.net", port: 465, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "mail.gmx.net", port: 587, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// i.ua.md: i.ua
|
||||
@@ -135,6 +144,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "imap.mail.me.com", port: 993, username_pattern: EMAILLOCALPART },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "smtp.mail.me.com", port: 587, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// kolst.com.md: kolst.com
|
||||
@@ -159,6 +169,15 @@ lazy_static::lazy_static! {
|
||||
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" },
|
||||
]),
|
||||
};
|
||||
|
||||
// outlook.com.md: hotmail.com, outlook.com, office365.com, outlook.com.tr, live.com
|
||||
@@ -171,6 +190,7 @@ lazy_static::lazy_static! {
|
||||
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 },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// posteo.md: posteo.de
|
||||
@@ -183,6 +203,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: STARTTLS, hostname: "posteo.de", port: 143, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "posteo.de", port: 587, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// protonmail.md: protonmail.com, protonmail.ch
|
||||
@@ -193,6 +214,7 @@ lazy_static::lazy_static! {
|
||||
overview_page: "https://providers.delta.chat/protonmail",
|
||||
server: vec![
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// riseup.net.md: riseup.net
|
||||
@@ -201,6 +223,9 @@ lazy_static::lazy_static! {
|
||||
// rogers.com.md: rogers.com
|
||||
// - skipping provider with status OK and no special things to do
|
||||
|
||||
// systemli.org.md: systemli.org
|
||||
// - skipping provider with status OK and no special things to do
|
||||
|
||||
// t-online.md: t-online.de, magenta.de
|
||||
static ref P_T_ONLINE: Provider = Provider {
|
||||
status: Status::PREPARATION,
|
||||
@@ -209,6 +234,7 @@ lazy_static::lazy_static! {
|
||||
overview_page: "https://providers.delta.chat/t-online",
|
||||
server: vec![
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// testrun.md: testrun.org
|
||||
@@ -222,6 +248,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: STARTTLS, hostname: "testrun.org", port: 143, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "testrun.org", port: 587, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// tiscali.it.md: tiscali.it
|
||||
@@ -234,6 +261,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "imap.tiscali.it", port: 993, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: SSL, hostname: "smtp.tiscali.it", port: 465, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// ukr.net.md: ukr.net
|
||||
@@ -253,6 +281,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: STARTTLS, hostname: "imap.web.de", port: 143, username_pattern: EMAILLOCALPART },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "smtp.web.de", port: 587, username_pattern: EMAILLOCALPART },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// yahoo.md: yahoo.com, yahoo.de, yahoo.it, yahoo.fr, yahoo.es, yahoo.se, yahoo.co.uk, yahoo.co.nz, yahoo.com.au, yahoo.com.ar, yahoo.com.br, yahoo.com.mx, ymail.com, rocketmail.com, yahoodns.net
|
||||
@@ -265,6 +294,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "imap.mail.yahoo.com", port: 993, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: SSL, hostname: "smtp.mail.yahoo.com", port: 465, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// yandex.ru.md: yandex.ru, yandex.com
|
||||
@@ -275,6 +305,7 @@ lazy_static::lazy_static! {
|
||||
overview_page: "https://providers.delta.chat/yandex-ru",
|
||||
server: vec![
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
// ziggo.nl.md: ziggo.nl
|
||||
@@ -287,6 +318,7 @@ lazy_static::lazy_static! {
|
||||
Server { protocol: IMAP, socket: SSL, hostname: "imap.ziggo.nl", port: 993, username_pattern: EMAIL },
|
||||
Server { protocol: SMTP, socket: STARTTLS, hostname: "smtp.ziggo.nl", port: 587, username_pattern: EMAIL },
|
||||
],
|
||||
config_defaults: None,
|
||||
};
|
||||
|
||||
pub static ref PROVIDER_DATA: HashMap<&'static str, &'static Provider> = [
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
mod data;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::dc_tools::EmailAddress;
|
||||
use crate::provider::data::PROVIDER_DATA;
|
||||
|
||||
@@ -57,6 +58,12 @@ impl Server {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConfigDefault {
|
||||
pub key: Config,
|
||||
pub value: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Provider {
|
||||
pub status: Status,
|
||||
@@ -64,6 +71,7 @@ pub struct Provider {
|
||||
pub after_login_hint: &'static str,
|
||||
pub overview_page: &'static str,
|
||||
pub server: Vec<Server>,
|
||||
pub config_defaults: Option<Vec<ConfigDefault>>,
|
||||
}
|
||||
|
||||
impl Provider {
|
||||
|
||||
@@ -9,6 +9,9 @@ out_all = ""
|
||||
out_domains = ""
|
||||
domains_dict = {}
|
||||
|
||||
def camel(name):
|
||||
words = name.split("_")
|
||||
return "".join(w.capitalize() for i, w in enumerate(words))
|
||||
|
||||
def cleanstr(s):
|
||||
s = s.strip()
|
||||
@@ -31,6 +34,18 @@ def file2url(f):
|
||||
return "https://providers.delta.chat/" + f
|
||||
|
||||
|
||||
def process_config_defaults(data):
|
||||
if not "config_defaults" in data:
|
||||
return "None"
|
||||
defaults = "Some(vec![\n"
|
||||
config_defaults = data.get("config_defaults", "")
|
||||
for key in config_defaults:
|
||||
value = str(config_defaults[key])
|
||||
defaults += " ConfigDefault { key: Config::" + camel(key) + ", value: \"" + value + "\" },\n"
|
||||
defaults += " ])"
|
||||
return defaults
|
||||
|
||||
|
||||
def process_data(data, file):
|
||||
status = data.get("status", "")
|
||||
if status != "OK" and status != "PREPARATION" and status != "BROKEN":
|
||||
@@ -83,6 +98,8 @@ def process_data(data, file):
|
||||
server += (" Server { protocol: " + protocol + ", socket: " + socket + ", hostname: \""
|
||||
+ hostname + "\", port: " + str(port) + ", username_pattern: " + username_pattern + " },\n")
|
||||
|
||||
config_defaults = process_config_defaults(data)
|
||||
|
||||
provider = ""
|
||||
before_login_hint = cleanstr(data.get("before_login_hint", ""))
|
||||
after_login_hint = cleanstr(data.get("after_login_hint", ""))
|
||||
@@ -93,6 +110,7 @@ def process_data(data, file):
|
||||
provider += " after_login_hint: \"" + after_login_hint + "\",\n"
|
||||
provider += " overview_page: \"" + file2url(file) + "\",\n"
|
||||
provider += " server: vec![\n" + server + " ],\n"
|
||||
provider += " config_defaults: " + config_defaults + ",\n"
|
||||
provider += " };\n\n"
|
||||
else:
|
||||
raise TypeError("SMTP and IMAP must be specified together or left out both")
|
||||
@@ -103,7 +121,7 @@ def process_data(data, file):
|
||||
# finally, add the provider
|
||||
global out_all, out_domains
|
||||
out_all += " // " + file[file.rindex("/")+1:] + ": " + comment.strip(", ") + "\n"
|
||||
if status == "OK" and before_login_hint == "" and after_login_hint == "" and server == "":
|
||||
if status == "OK" and before_login_hint == "" and after_login_hint == "" and server == "" and config_defaults == "None":
|
||||
out_all += " // - skipping provider with status OK and no special things to do\n\n"
|
||||
else:
|
||||
out_all += provider
|
||||
|
||||
23
src/sql.rs
23
src/sql.rs
@@ -5,7 +5,6 @@ use async_std::sync::{Arc, RwLock};
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
use rusqlite::{Connection, Error as SqlError, OpenFlags};
|
||||
use thread_local_object::ThreadLocal;
|
||||
@@ -703,18 +702,13 @@ async fn open(
|
||||
open_flags.insert(OpenFlags::SQLITE_OPEN_READ_WRITE);
|
||||
open_flags.insert(OpenFlags::SQLITE_OPEN_CREATE);
|
||||
}
|
||||
|
||||
// this actually creates min_idle database handles just now.
|
||||
// therefore, with_init() must not try to modify the database as otherwise
|
||||
// we easily get busy-errors (eg. table-creation, journal_mode etc. should be done on only one handle)
|
||||
let mgr = r2d2_sqlite::SqliteConnectionManager::file(dbfile.as_ref())
|
||||
.with_flags(open_flags)
|
||||
.with_init(|c| {
|
||||
// Only one process can make changes to the database at one time.
|
||||
// busy_timeout defines, that if a second process wants write access,
|
||||
// this second process will wait some milliseconds
|
||||
// and try over until it gets write access or the given timeout is elapsed.
|
||||
// If the second process does not get write access within the given timeout,
|
||||
// sqlite3_step() will return the error SQLITE_BUSY.
|
||||
// (without a busy_timeout, sqlite3_step() would return SQLITE_BUSY _at once_)
|
||||
c.busy_timeout(Duration::from_secs(10))?;
|
||||
|
||||
c.execute_batch("PRAGMA secure_delete=on;")?;
|
||||
Ok(())
|
||||
});
|
||||
@@ -730,6 +724,15 @@ async fn open(
|
||||
}
|
||||
|
||||
if !readonly {
|
||||
// journal_mode is persisted, it is sufficient to change it only for one handle.
|
||||
// (nb: execute() always returns errors for this PRAGMA call, just discard it.
|
||||
// but even if execute() would handle errors more gracefully, we should continue on errors -
|
||||
// systems might not be able to handle WAL, in which case the standard-journal is used.
|
||||
// that may be not optimal, but better than not working at all :)
|
||||
sql.execute("PRAGMA journal_mode=WAL;", paramsv![])
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let mut exists_before_update = false;
|
||||
let mut dbversion_before_update: i32 = 0;
|
||||
/* Init tables to dbversion=0 */
|
||||
|
||||
Reference in New Issue
Block a user