mirror of
https://github.com/chatmail/core.git
synced 2026-06-28 02:26:35 +03:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11b7a5c9d4 | ||
|
|
5ab107866a | ||
|
|
374a5ef687 | ||
|
|
1a2e355bb8 |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1367,6 +1367,7 @@ dependencies = [
|
||||
"tokio-tar",
|
||||
"tokio-util",
|
||||
"toml",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
"webpki-roots",
|
||||
|
||||
@@ -108,6 +108,7 @@ tokio-tar = { version = "0.3" } # TODO: integrate tokio into async-tar
|
||||
tokio-util = { workspace = true }
|
||||
tokio = { workspace = true, features = ["fs", "rt-multi-thread", "macros"] }
|
||||
toml = "0.8"
|
||||
tracing = "0.1.41"
|
||||
url = "2"
|
||||
uuid = { version = "1", features = ["serde", "v4"] }
|
||||
webpki-roots = "0.26.8"
|
||||
|
||||
@@ -53,6 +53,14 @@ impl Accounts {
|
||||
Accounts::open(dir, writable).await
|
||||
}
|
||||
|
||||
/// Get the ID used to log events.
|
||||
///
|
||||
/// Account manager logs events with ID 0
|
||||
/// which is not used by any accounts.
|
||||
fn get_id(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
/// Creates a new default structure.
|
||||
async fn create(dir: &Path) -> Result<()> {
|
||||
fs::create_dir_all(dir)
|
||||
|
||||
@@ -223,6 +223,10 @@ pub(crate) const WORSE_AVATAR_BYTES: usize = 20_000; // this also fits to Outloo
|
||||
pub const BALANCED_IMAGE_SIZE: u32 = 1280;
|
||||
pub const WORSE_IMAGE_SIZE: u32 = 640;
|
||||
|
||||
/// Limit for received images size. Bigger images become `Viewtype::File` to avoid excessive memory
|
||||
/// usage by UIs.
|
||||
pub const MAX_RCVD_IMAGE_PIXELS: u32 = 50_000_000;
|
||||
|
||||
// Key for the folder configuration version (see below).
|
||||
pub(crate) const DC_FOLDERS_CONFIGURED_KEY: &str = "folders_configured";
|
||||
// this value can be increased if the folder configuration is changed and must be redone on next program start
|
||||
|
||||
@@ -14,6 +14,7 @@ macro_rules! info {
|
||||
file = file!(),
|
||||
line = line!(),
|
||||
msg = &formatted);
|
||||
::tracing::event!(::tracing::Level::INFO, account_id = $ctx.get_id(), "{}", &formatted);
|
||||
$ctx.emit_event($crate::EventType::Info(full));
|
||||
}};
|
||||
}
|
||||
@@ -33,6 +34,7 @@ mod warn_macro_mod {
|
||||
file = file!(),
|
||||
line = line!(),
|
||||
msg = &formatted);
|
||||
::tracing::event!(::tracing::Level::WARN, account_id = $ctx.get_id(), "{}", &formatted);
|
||||
$ctx.emit_event($crate::EventType::Warning(full));
|
||||
}};
|
||||
}
|
||||
@@ -48,6 +50,7 @@ macro_rules! error {
|
||||
};
|
||||
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {{
|
||||
let formatted = format!($msg, $($args),*);
|
||||
::tracing::event!(::tracing::Level::ERROR, account_id = $ctx.get_id(), "{}", &formatted);
|
||||
$ctx.set_last_error(&formatted);
|
||||
$ctx.emit_event($crate::EventType::Error(formatted));
|
||||
}};
|
||||
@@ -113,6 +116,12 @@ impl<T, E: std::fmt::Display> LogExt<T, E> for Result<T, E> {
|
||||
);
|
||||
// We can't use the warn!() macro here as the file!() and line!() macros
|
||||
// don't work with #[track_caller]
|
||||
tracing::event!(
|
||||
::tracing::Level::WARN,
|
||||
account_id = context.get_id(),
|
||||
"{}",
|
||||
&full
|
||||
);
|
||||
context.emit_event(crate::EventType::Warning(full));
|
||||
};
|
||||
self
|
||||
|
||||
@@ -1393,6 +1393,20 @@ impl MimeMessage {
|
||||
} else {
|
||||
Viewtype::File
|
||||
}
|
||||
} else if msg_type == Viewtype::Image
|
||||
|| msg_type == Viewtype::Gif
|
||||
|| msg_type == Viewtype::Sticker
|
||||
{
|
||||
match get_filemeta(decoded_data) {
|
||||
// image size is known, not too big, keep msg_type:
|
||||
Ok((width, height)) if width * height <= constants::MAX_RCVD_IMAGE_PIXELS => {
|
||||
part.param.set_i64(Param::Width, width.into());
|
||||
part.param.set_i64(Param::Height, height.into());
|
||||
msg_type
|
||||
}
|
||||
// image is too big or size is unknown, display as file:
|
||||
_ => Viewtype::File,
|
||||
}
|
||||
} else {
|
||||
msg_type
|
||||
};
|
||||
@@ -1413,13 +1427,6 @@ impl MimeMessage {
|
||||
};
|
||||
info!(context, "added blobfile: {:?}", blob.as_name());
|
||||
|
||||
if mime_type.type_() == mime::IMAGE {
|
||||
if let Ok((width, height)) = get_filemeta(decoded_data) {
|
||||
part.param.set_int(Param::Width, width as i32);
|
||||
part.param.set_int(Param::Height, height as i32);
|
||||
}
|
||||
}
|
||||
|
||||
part.typ = msg_type;
|
||||
part.org_filename = Some(filename.to_string());
|
||||
part.mimetype = Some(mime_type);
|
||||
|
||||
@@ -835,15 +835,7 @@ Content-Transfer-Encoding: base64
|
||||
Content-Disposition: inline;
|
||||
filename="JPEG_filename.jpg"
|
||||
|
||||
ISVb1L3m7z15Wy5w97a2cJg6W8P8YKOYfWn3PJ/UCSFcvCPtvBhcXieiN3M3ljguzG4XK7BnGgxG
|
||||
acAQdY8e0cWz1n+zKPNeNn4Iu3GXAXz4/IPksHk54inl1//0Lv8ggZjljfjnf0q1SPftYI7lpZWT
|
||||
/4aTCkimRrAIcwrQJPnZJRb7BPSC6kfn1QJHMv77mRMz2+4WbdfpyPQQ0CWLJsgVXtBsSMf2Awal
|
||||
n+zZzhGpXyCbWTEw1ccqZcK5KaiKNqWv51N4yVXw9dzJoCvxbYtCFGZZJdx7c+ObDotaF1/9KY4C
|
||||
xJjgK9/NgTXCZP1jYm0XIBnJsFSNg0pnMRETttTuGbOVi1/s/F1RGv5RNZsCUt21d9FhkWQQXsd2
|
||||
rOzDgTdag6BQCN3hSU9eKW/GhNBuMibRN9eS7Sm1y2qFU1HgGJBQfPPRPLKxXaNi++Zt0tnon2IU
|
||||
8pg5rP/IvStXYQNUQ9SiFdfAUkLU5b1j8ltnka8xl+oXsleSG44GPz6kM0RmwUrGkl4z/+NfHSsI
|
||||
K+TuvC7qOah0WLFhcsXWn2+dDV1bXuAeC769TkqkpHhdXfUHnVgK3Pv7u3rVPT5AMeFUGxRB2dP4
|
||||
CWt6wx7fiLp0qS9RrX75g6Gqw7nfCs6EcBERcIPt7DTe8VStJwf3LWqVwxl4gQl46yhfoqwEO+I=
|
||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAAAAABoYUP1AAAAAXNSR0IArs4c6QAAAo1JREFUKJFdkdFuG0UUhr/szuxkxtlduzVx00jGUAhcI56CF0DiHXgFHqDiMfoCvAJC4gIJEBdVaZoGOY5dJ45r7zozmRlvzIVDm3Iu//PpP7/+s/OC/0+UREkEGZGr5N6mAX78MwISQEYJ6j6QYqZf7fzsYyRGJDISuQ9g6uMjW00WRCSRCP4DwNSEg496v828fC++B4yBGro7h+PliiiJHtR9B1vrmbtg359cOk+UqA8cDJm+eHu8yDfii6sAxK0u3hlsnPFn1WvT4XxYUqqtKu8cTMNKT8+nz3/aaWft3svKecBD/O9ETu2O//G7fXt5mHX2xwGP32aIEUNNvX/uh3z2pAkcKD+9XOLVNoMESw7YC+aPP8nqqSluyiuVaZRXCKLEQK3PxsP27UHe1lXV9eczCu2V8ippJA2gz+YTNTK9ttZOoYr+aeXwHp+k245cnFRNt1tmMJg3XV0dXQd3F5LcGn5fDnVQgwINRyFvtddnNmwBSW1qXfzNSDwoM+2A+aTbShfDd89Ka9ybiiLvGa33gK8THrWfVNUSSGLTALMRo/xBXnLbACu3QtRXY+sgkWnawKxCcLjPtr29gVZdPTidBUcSaXJeTfUL+mW4631Fmse+772xIGjSza/KTW/MYE/UCXPbEWs//Xxvqf8qZgYhG0jt8cnTnJpEgfDQ6rvE0n9tq66ICafil5OnOYt0hY94FUPoxI136uPpw4VIYNd+M5utrqvGpg0hc50bRl6BvLanX4pb/3347uWi/WgNHtYyyrdwszsX5fjZtwghy7C5sK2WgUoErcjIoEWr4fAHHhoRP+XZ86L/uMAarLFgsMBaAJhM8Ief9Ey7yHSmyXTp0GRoF7KQEdD/ArmtONKkgCleAAAAAElFTkSuQmCC
|
||||
|
||||
|
||||
----11019878869865180--
|
||||
@@ -908,15 +900,7 @@ Content-ID: <part1.9DFA679B.52A88D69@example.org>
|
||||
Content-Disposition: inline;
|
||||
filename="1.png"
|
||||
|
||||
ISVb1L3m7z15Wy5w97a2cJg6W8P8YKOYfWn3PJ/UCSFcvCPtvBhcXieiN3M3ljguzG4XK7BnGgxG
|
||||
acAQdY8e0cWz1n+zKPNeNn4Iu3GXAXz4/IPksHk54inl1//0Lv8ggZjljfjnf0q1SPftYI7lpZWT
|
||||
/4aTCkimRrAIcwrQJPnZJRb7BPSC6kfn1QJHMv77mRMz2+4WbdfpyPQQ0CWLJsgVXtBsSMf2Awal
|
||||
n+zZzhGpXyCbWTEw1ccqZcK5KaiKNqWv51N4yVXw9dzJoCvxbYtCFGZZJdx7c+ObDotaF1/9KY4C
|
||||
xJjgK9/NgTXCZP1jYm0XIBnJsFSNg0pnMRETttTuGbOVi1/s/F1RGv5RNZsCUt21d9FhkWQQXsd2
|
||||
rOzDgTdag6BQCN3hSU9eKW/GhNBuMibRN9eS7Sm1y2qFU1HgGJBQfPPRPLKxXaNi++Zt0tnon2IU
|
||||
8pg5rP/IvStXYQNUQ9SiFdfAUkLU5b1j8ltnka8xl+oXsleSG44GPz6kM0RmwUrGkl4z/+NfHSsI
|
||||
K+TuvC7qOah0WLFhcsXWn2+dDV1bXuAeC769TkqkpHhdXfUHnVgK3Pv7u3rVPT5AMeFUGxRB2dP4
|
||||
CWt6wx7fiLp0qS9RrX75g6Gqw7nfCs6EcBERcIPt7DTe8VStJwf3LWqVwxl4gQl46yhfoqwEO+I=
|
||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAAAAABoYUP1AAAAAXNSR0IArs4c6QAAAo1JREFUKJFdkdFuG0UUhr/szuxkxtlduzVx00jGUAhcI56CF0DiHXgFHqDiMfoCvAJC4gIJEBdVaZoGOY5dJ45r7zozmRlvzIVDm3Iu//PpP7/+s/OC/0+UREkEGZGr5N6mAX78MwISQEYJ6j6QYqZf7fzsYyRGJDISuQ9g6uMjW00WRCSRCP4DwNSEg496v828fC++B4yBGro7h+PliiiJHtR9B1vrmbtg359cOk+UqA8cDJm+eHu8yDfii6sAxK0u3hlsnPFn1WvT4XxYUqqtKu8cTMNKT8+nz3/aaWft3svKecBD/O9ETu2O//G7fXt5mHX2xwGP32aIEUNNvX/uh3z2pAkcKD+9XOLVNoMESw7YC+aPP8nqqSluyiuVaZRXCKLEQK3PxsP27UHe1lXV9eczCu2V8ippJA2gz+YTNTK9ttZOoYr+aeXwHp+k245cnFRNt1tmMJg3XV0dXQd3F5LcGn5fDnVQgwINRyFvtddnNmwBSW1qXfzNSDwoM+2A+aTbShfDd89Ka9ybiiLvGa33gK8THrWfVNUSSGLTALMRo/xBXnLbACu3QtRXY+sgkWnawKxCcLjPtr29gVZdPTidBUcSaXJeTfUL+mW4631Fmse+772xIGjSza/KTW/MYE/UCXPbEWs//Xxvqf8qZgYhG0jt8cnTnJpEgfDQ6rvE0n9tq66ICafil5OnOYt0hY94FUPoxI136uPpw4VIYNd+M5utrqvGpg0hc50bRl6BvLanX4pb/3347uWi/WgNHtYyyrdwszsX5fjZtwghy7C5sK2WgUoErcjIoEWr4fAHHhoRP+XZ86L/uMAarLFgsMBaAJhM8Ief9Ey7yHSmyXTp0GRoF7KQEdD/ArmtONKkgCleAAAAAElFTkSuQmCC
|
||||
--------------10CC6C2609EB38DA782C5CA9--
|
||||
|
||||
--------------779C1631600DF3DB8C02E53A--"#;
|
||||
@@ -979,15 +963,7 @@ Content-Type: image/jpeg;
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-ID: <image001.jpg@01D622B3.C9D8D750>
|
||||
|
||||
ISVb1L3m7z15Wy5w97a2cJg6W8P8YKOYfWn3PJ/UCSFcvCPtvBhcXieiN3M3ljguzG4XK7BnGgxG
|
||||
acAQdY8e0cWz1n+zKPNeNn4Iu3GXAXz4/IPksHk54inl1//0Lv8ggZjljfjnf0q1SPftYI7lpZWT
|
||||
/4aTCkimRrAIcwrQJPnZJRb7BPSC6kfn1QJHMv77mRMz2+4WbdfpyPQQ0CWLJsgVXtBsSMf2Awal
|
||||
n+zZzhGpXyCbWTEw1ccqZcK5KaiKNqWv51N4yVXw9dzJoCvxbYtCFGZZJdx7c+ObDotaF1/9KY4C
|
||||
xJjgK9/NgTXCZP1jYm0XIBnJsFSNg0pnMRETttTuGbOVi1/s/F1RGv5RNZsCUt21d9FhkWQQXsd2
|
||||
rOzDgTdag6BQCN3hSU9eKW/GhNBuMibRN9eS7Sm1y2qFU1HgGJBQfPPRPLKxXaNi++Zt0tnon2IU
|
||||
8pg5rP/IvStXYQNUQ9SiFdfAUkLU5b1j8ltnka8xl+oXsleSG44GPz6kM0RmwUrGkl4z/+NfHSsI
|
||||
K+TuvC7qOah0WLFhcsXWn2+dDV1bXuAeC769TkqkpHhdXfUHnVgK3Pv7u3rVPT5AMeFUGxRB2dP4
|
||||
CWt6wx7fiLp0qS9RrX75g6Gqw7nfCs6EcBERcIPt7DTe8VStJwf3LWqVwxl4gQl46yhfoqwEO+I=
|
||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAAAAABoYUP1AAAAAXNSR0IArs4c6QAAAo1JREFUKJFdkdFuG0UUhr/szuxkxtlduzVx00jGUAhcI56CF0DiHXgFHqDiMfoCvAJC4gIJEBdVaZoGOY5dJ45r7zozmRlvzIVDm3Iu//PpP7/+s/OC/0+UREkEGZGr5N6mAX78MwISQEYJ6j6QYqZf7fzsYyRGJDISuQ9g6uMjW00WRCSRCP4DwNSEg496v828fC++B4yBGro7h+PliiiJHtR9B1vrmbtg359cOk+UqA8cDJm+eHu8yDfii6sAxK0u3hlsnPFn1WvT4XxYUqqtKu8cTMNKT8+nz3/aaWft3svKecBD/O9ETu2O//G7fXt5mHX2xwGP32aIEUNNvX/uh3z2pAkcKD+9XOLVNoMESw7YC+aPP8nqqSluyiuVaZRXCKLEQK3PxsP27UHe1lXV9eczCu2V8ippJA2gz+YTNTK9ttZOoYr+aeXwHp+k245cnFRNt1tmMJg3XV0dXQd3F5LcGn5fDnVQgwINRyFvtddnNmwBSW1qXfzNSDwoM+2A+aTbShfDd89Ka9ybiiLvGa33gK8THrWfVNUSSGLTALMRo/xBXnLbACu3QtRXY+sgkWnawKxCcLjPtr29gVZdPTidBUcSaXJeTfUL+mW4631Fmse+772xIGjSza/KTW/MYE/UCXPbEWs//Xxvqf8qZgYhG0jt8cnTnJpEgfDQ6rvE0n9tq66ICafil5OnOYt0hY94FUPoxI136uPpw4VIYNd+M5utrqvGpg0hc50bRl6BvLanX4pb/3347uWi/WgNHtYyyrdwszsX5fjZtwghy7C5sK2WgUoErcjIoEWr4fAHHhoRP+XZ86L/uMAarLFgsMBaAJhM8Ief9Ey7yHSmyXTp0GRoF7KQEdD/ArmtONKkgCleAAAAAElFTkSuQmCC
|
||||
|
||||
------=_NextPart_000_0003_01D622B3.CA753E60--
|
||||
"#;
|
||||
@@ -2022,3 +1998,48 @@ async fn test_protected_date() -> Result<()> {
|
||||
assert_eq!(alice_msg.get_timestamp(), bob_msg.get_timestamp());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_huge_image_becomes_file() -> Result<()> {
|
||||
let t = TestContext::new_alice().await;
|
||||
let msg_id = receive_imf(
|
||||
&t,
|
||||
include_bytes!("../../test-data/message/image_huge_64M.eml"),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
.unwrap()
|
||||
.msg_ids[0];
|
||||
let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap();
|
||||
// Huge image should be treated as file:
|
||||
assert_eq!(msg.viewtype, Viewtype::File);
|
||||
assert!(msg.get_file(&t).is_some());
|
||||
assert_eq!(msg.get_filename().unwrap(), "huge_image.png");
|
||||
assert_eq!(msg.get_filemime().unwrap(), "image/png");
|
||||
// File has no width or height
|
||||
assert!(msg.param.get_int(Param::Width).is_none());
|
||||
assert!(msg.param.get_int(Param::Height).is_none());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_4k_image_stays_image() -> Result<()> {
|
||||
let t = TestContext::new_alice().await;
|
||||
let msg_id = receive_imf(
|
||||
&t,
|
||||
include_bytes!("../../test-data/message/image_4k.eml"),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
.unwrap()
|
||||
.msg_ids[0];
|
||||
let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap();
|
||||
// 4K image should be treated as image:
|
||||
assert_eq!(msg.viewtype, Viewtype::Image);
|
||||
assert!(msg.get_file(&t).is_some());
|
||||
assert_eq!(msg.get_filename().unwrap(), "4k_image.png");
|
||||
assert_eq!(msg.get_filemime().unwrap(), "image/png");
|
||||
assert_eq!(msg.param.get_int(Param::Width).unwrap_or_default(), 3840);
|
||||
assert_eq!(msg.param.get_int(Param::Height).unwrap_or_default(), 2160);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2899,17 +2899,17 @@ async fn apply_group_changes(
|
||||
}
|
||||
}
|
||||
|
||||
apply_chat_name_and_avatar_changes(
|
||||
context,
|
||||
mime_parser,
|
||||
from_id,
|
||||
chat,
|
||||
&mut send_event_chat_modified,
|
||||
&mut better_msg,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if is_from_in_chat {
|
||||
apply_chat_name_and_avatar_changes(
|
||||
context,
|
||||
mime_parser,
|
||||
from_id,
|
||||
chat,
|
||||
&mut send_event_chat_modified,
|
||||
&mut better_msg,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if chat.member_list_is_stale(context).await? {
|
||||
info!(context, "Member list is stale.");
|
||||
let mut new_members: HashSet<ContactId> =
|
||||
|
||||
@@ -4212,14 +4212,18 @@ async fn test_keep_member_list_if_possibly_nomember() -> Result<()> {
|
||||
let fiona_chat_id = fiona.recv_msg(&alice.pop_sent_msg().await).await.chat_id;
|
||||
fiona_chat_id.accept(&fiona).await?;
|
||||
|
||||
send_text_msg(&fiona, fiona_chat_id, "hi".to_string()).await?;
|
||||
SystemTime::shift(Duration::from_secs(60));
|
||||
chat::set_chat_name(&fiona, fiona_chat_id, "Renamed").await?;
|
||||
bob.recv_msg(&fiona.pop_sent_msg().await).await;
|
||||
|
||||
// Bob missed the message adding fiona, but mustn't recreate the member list.
|
||||
// Bob missed the message adding fiona, but mustn't recreate the member list or apply the group
|
||||
// name change.
|
||||
assert_eq!(get_chat_contacts(&bob, bob_chat_id).await?.len(), 2);
|
||||
assert!(is_contact_in_chat(&bob, bob_chat_id, ContactId::SELF).await?);
|
||||
let bob_alice_contact = bob.add_or_lookup_contact_id(&alice).await;
|
||||
assert!(is_contact_in_chat(&bob, bob_chat_id, bob_alice_contact).await?);
|
||||
let chat = Chat::load_from_db(&bob, bob_chat_id).await?;
|
||||
assert_eq!(chat.get_name(), "Group");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as _, Result, ensure};
|
||||
use deltachat_contact_tools::EmailAddress;
|
||||
@@ -1237,13 +1237,13 @@ CREATE INDEX gossip_timestamp_index ON gossip_timestamp (chat_id, fingerprint);
|
||||
|
||||
inc_and_check(&mut migration_version, 132)?;
|
||||
if dbversion < migration_version {
|
||||
let start = Instant::now();
|
||||
let start = Time::now();
|
||||
sql.execute_migration_transaction(|t| migrate_key_contacts(context, t), migration_version)
|
||||
.await?;
|
||||
info!(
|
||||
context,
|
||||
"key-contacts migration took {:?} in total.",
|
||||
start.elapsed()
|
||||
time_elapsed(&start),
|
||||
);
|
||||
// Schedule `msgs_to_key_contacts()`.
|
||||
context
|
||||
|
||||
@@ -14,7 +14,8 @@ use std::str::from_utf8;
|
||||
// `Instant` may use `libc::clock_gettime(CLOCK_MONOTONIC)`, e.g. on Android, and does not advance
|
||||
// while being in deep sleep mode, we use `SystemTime` instead, but add an alias for it to document
|
||||
// why `Instant` isn't used in those places. Also this can help to switch to another clock impl if
|
||||
// we find any.
|
||||
// we find any. Another reason is that `Instant` may reintroduce panics in the future versions:
|
||||
// https://doc.rust-lang.org/1.87.0/std/time/struct.Instant.html#method.elapsed.
|
||||
use std::time::Duration;
|
||||
pub use std::time::SystemTime as Time;
|
||||
#[cfg(not(test))]
|
||||
|
||||
28
test-data/message/image_4k.eml
Normal file
28
test-data/message/image_4k.eml
Normal file
@@ -0,0 +1,28 @@
|
||||
Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)
|
||||
From: Test Sender <sender@testrun.org>
|
||||
Subject: Large image test
|
||||
To: alice@example.org
|
||||
Message-ID: <big-image-test@testrun.org>
|
||||
Date: Thu, 17 Dec 2020 15:38:45 +0100
|
||||
User-Agent: Test-Agent/1.0
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="------------BIG_IMAGE_BOUNDARY"
|
||||
Content-Language: en-US
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------BIG_IMAGE_BOUNDARY
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Here is a 4k image
|
||||
|
||||
--------------BIG_IMAGE_BOUNDARY
|
||||
Content-Type: image/png;
|
||||
name="4k_image.png"
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment;
|
||||
filename="4k_image.png"
|
||||
|
||||
iVBORw0KGgoAAAANSUhEUgAADwAAAAhwCAIAAAAf3FwlAAAAEElEQVR4nAEFAPr/AP////8AAAAFCeiupAAAAABJRU5ErkJggg==
|
||||
--------------BIG_IMAGE_BOUNDARY--
|
||||
28
test-data/message/image_huge_64M.eml
Normal file
28
test-data/message/image_huge_64M.eml
Normal file
@@ -0,0 +1,28 @@
|
||||
Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)
|
||||
From: Test Sender <sender@testrun.org>
|
||||
Subject: Large image test
|
||||
To: alice@example.org
|
||||
Message-ID: <huge-image-test@testrun.org>
|
||||
Date: Thu, 17 Dec 2020 15:38:45 +0100
|
||||
User-Agent: Test-Agent/1.0
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="------------HUGE_IMAGE_BOUNDARY"
|
||||
Content-Language: en-US
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------HUGE_IMAGE_BOUNDARY
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Here is a huge image
|
||||
|
||||
--------------HUGE_IMAGE_BOUNDARY
|
||||
Content-Type: image/png;
|
||||
name="huge_image.png"
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment;
|
||||
filename="huge_image.png"
|
||||
|
||||
iVBORw0KGgoAAAANSUhEUgAAH0AAAB9ACAIAAACJkzqjAAAAEElEQVR4nAEFAPr/AP////8AAAAFCeiupAAAAABJRU5ErkJggg==
|
||||
--------------HUGE_IMAGE_BOUNDARY--
|
||||
Reference in New Issue
Block a user