mirror of
https://github.com/chatmail/core.git
synced 2026-04-02 05:22:14 +03:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2edd0b682a | ||
|
|
0d2aaec742 | ||
|
|
241a9c5990 | ||
|
|
2dd90c2509 | ||
|
|
0c70624e21 | ||
|
|
5ad85c52bc |
212
Cargo.lock
generated
212
Cargo.lock
generated
@@ -452,6 +452,27 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "base64-stream"
|
||||
version = "1.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6596cd4b981cb9e85a9bddf2d1c3a76ebffe64f9e6b0ea6f053d810aea7807c"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"educe",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.2"
|
||||
@@ -685,6 +706,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"parse-zoneinfo",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "circular"
|
||||
version = "0.3.0"
|
||||
@@ -812,7 +843,7 @@ dependencies = [
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"csv",
|
||||
"itertools",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"oorandom",
|
||||
@@ -834,7 +865,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
"itertools 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -991,6 +1022,12 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d0e2d24e5ee3b23a01de38eefdcd978907890701f08ffffd4cb457ca4ee8d6"
|
||||
|
||||
[[package]]
|
||||
name = "debug-helper"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8a5bb894f24f42c247f19b25928a88e31867c0f84552c05df41a9dd527435e"
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "0.8.6"
|
||||
@@ -1029,9 +1066,10 @@ dependencies = [
|
||||
"futures",
|
||||
"futures-lite",
|
||||
"hex",
|
||||
"ical",
|
||||
"image",
|
||||
"indexmap",
|
||||
"itertools",
|
||||
"itertools 0.9.0",
|
||||
"kamadak-exif",
|
||||
"lettre_email",
|
||||
"libc",
|
||||
@@ -1046,7 +1084,7 @@ dependencies = [
|
||||
"pretty_assertions",
|
||||
"pretty_env_logger",
|
||||
"proptest",
|
||||
"quick-xml",
|
||||
"quick-xml 0.18.1",
|
||||
"r2d2",
|
||||
"r2d2_sqlite",
|
||||
"rand",
|
||||
@@ -1067,6 +1105,7 @@ dependencies = [
|
||||
"toml",
|
||||
"url",
|
||||
"uuid",
|
||||
"vcard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1209,6 +1248,18 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "educe"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7260c7e6e656fc7702a1aa8d5b498a1a69aa84ac4ffcd5501b7d26939f368a93"
|
||||
dependencies = [
|
||||
"enum-ordinalize",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
@@ -1335,6 +1386,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-ordinalize"
|
||||
version = "3.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1676e1daadfd216bda88d3a6fedd1bf53b829a085f5cc4d81c6f3054f50ef983"
|
||||
dependencies = [
|
||||
"num-bigint 0.3.1",
|
||||
"num-traits",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.7.1"
|
||||
@@ -1363,6 +1427,28 @@ version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
@@ -1754,6 +1840,15 @@ dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ical"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a9f7215ad0d77e69644570dee000c7678a47ba7441062c1b5f918adde0d73cf"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@@ -1833,6 +1928,15 @@ dependencies = [
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.9.0"
|
||||
@@ -2161,6 +2265,17 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.6.0"
|
||||
@@ -2254,6 +2369,12 @@ version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
|
||||
|
||||
[[package]]
|
||||
name = "oncemutex"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.2"
|
||||
@@ -2374,6 +2495,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem"
|
||||
version = "0.8.1"
|
||||
@@ -2440,6 +2570,26 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phonenumber"
|
||||
version = "0.2.4+8.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "207b3a8b4b30da166f6d8175ad39b86aa84d190965be4533af3d5541754de358"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"either",
|
||||
"failure",
|
||||
"fnv",
|
||||
"itertools 0.8.2",
|
||||
"lazy_static",
|
||||
"nom 5.1.2",
|
||||
"quick-xml 0.17.2",
|
||||
"regex",
|
||||
"regex-cache",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "0.4.25"
|
||||
@@ -2600,6 +2750,15 @@ version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.18.1"
|
||||
@@ -2759,6 +2918,18 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-cache"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32c86351f6af6bbf23b4c5f73ee4fdfe92d298fdf28572ea4f69494cabe38699"
|
||||
dependencies = [
|
||||
"lru-cache",
|
||||
"oncemutex",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.18"
|
||||
@@ -3137,7 +3308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"num-bigint",
|
||||
"num-bigint 0.2.6",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
@@ -3617,6 +3788,37 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validators"
|
||||
version = "0.20.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9af4acf80e223db35334bfb3b09421c54ed259ca203b5189177e61e3b9e1c2a3"
|
||||
dependencies = [
|
||||
"debug-helper",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"phonenumber",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcard"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c988b5461430fd8d078237c8a9436c8e2f810f944cba3086e3ce99cd54652caf"
|
||||
dependencies = [
|
||||
"base64-stream",
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"idna",
|
||||
"lazy_static",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"regex",
|
||||
"validators",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.10"
|
||||
|
||||
@@ -61,6 +61,8 @@ url = "2.1.1"
|
||||
async-std-resolver = "0.19.5"
|
||||
async-tar = "0.3.0"
|
||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||
vcard = "0.4.6"
|
||||
ical = { version = "0.7.0", default-features = false, features = ["vcard"] }
|
||||
|
||||
pretty_env_logger = { version = "0.4.0", optional = true }
|
||||
log = {version = "0.4.8", optional = true }
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
use chrono::TimeZone;
|
||||
use lettre_email::{mime, Address, Header, MimeMultipartType, PartBuilder};
|
||||
use std::collections::HashSet;
|
||||
use vcard::properties::Photo;
|
||||
use vcard::values::image_value::ImageValue;
|
||||
use vcard::{Set, VCard};
|
||||
|
||||
use crate::blob::BlobObject;
|
||||
use crate::chat::{self, Chat};
|
||||
@@ -991,13 +995,24 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
||||
|
||||
if self.attach_selfavatar {
|
||||
match context.get_config(Config::Selfavatar).await {
|
||||
Some(path) => match build_selfavatar_file(context, &path) {
|
||||
Ok((part, filename)) => {
|
||||
parts.push(part);
|
||||
protected_headers.push(Header::new("Chat-User-Avatar".into(), filename))
|
||||
}
|
||||
Err(err) => warn!(context, "mimefactory: cannot attach selfavatar: {}", err),
|
||||
},
|
||||
Some(path) => {
|
||||
match build_selfavatar_file(context, &path) {
|
||||
Ok((part, filename)) => {
|
||||
parts.push(part);
|
||||
protected_headers.push(Header::new("Chat-User-Avatar".into(), filename))
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(context, "mimefactory: cannot attach selfavatar: {}", err)
|
||||
}
|
||||
};
|
||||
|
||||
match build_vcard_part(context, &path).await {
|
||||
Ok(part) => {
|
||||
parts.push(part);
|
||||
}
|
||||
Err(err) => warn!(context, "mimefactory: cannot build vCard: {}", err),
|
||||
};
|
||||
}
|
||||
None => protected_headers.push(Header::new("Chat-User-Avatar".into(), "0".into())),
|
||||
}
|
||||
}
|
||||
@@ -1199,6 +1214,40 @@ async fn build_body_file(
|
||||
Ok((mail, filename_to_send))
|
||||
}
|
||||
|
||||
async fn build_vcard_file(context: &Context, avatar_path: &str) -> Result<String, Error> {
|
||||
let avatar_blob = BlobObject::from_path(context, avatar_path)?;
|
||||
|
||||
let displayname = context
|
||||
.get_config(Config::Displayname)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let mut vcard = VCard::from_formatted_name_str(&displayname)?;
|
||||
// TODO: add KIND:individual
|
||||
let mut photos = HashSet::new();
|
||||
if let Ok(image_value) = ImageValue::from_file(avatar_blob.to_abs_path()) {
|
||||
let photo = Photo::from_image_value(image_value);
|
||||
photos.insert(photo);
|
||||
}
|
||||
vcard.photos = Set::from_hash_set(photos).ok();
|
||||
Ok(vcard.to_string())
|
||||
}
|
||||
|
||||
async fn build_vcard_part(context: &Context, avatar_path: &str) -> Result<PartBuilder, Error> {
|
||||
let body = build_vcard_file(context, avatar_path).await?;
|
||||
let encoded_body = wrapped_base64_encode(&body.as_bytes());
|
||||
|
||||
let part = PartBuilder::new()
|
||||
.content_type(&mime::TEXT_VCARD)
|
||||
.header((
|
||||
"Content-Disposition",
|
||||
"attachment; filename=\"{avatar.vcf}\"",
|
||||
))
|
||||
.header(("Content-Transfer-Encoding", "base64"))
|
||||
.body(encoded_body);
|
||||
|
||||
Ok(part)
|
||||
}
|
||||
|
||||
fn build_selfavatar_file(context: &Context, path: &str) -> Result<(PartBuilder, String), Error> {
|
||||
let blob = BlobObject::from_path(context, path)?;
|
||||
let filename_to_send = match blob.suffix() {
|
||||
|
||||
@@ -814,6 +814,26 @@ impl MimeMessage {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if mime_type.type_() == "text/x-vcard"
|
||||
|| mime_type.type_() == "text/vcard"
|
||||
|| filename.ends_with(".vcf")
|
||||
|| filename.ends_with(".vcard")
|
||||
{
|
||||
println!("Parsing vcard {:?}", String::from_utf8_lossy(decoded_data));
|
||||
for contact in ical::VcardParser::new(decoded_data) {
|
||||
println!("Parsing contact {:?}", contact);
|
||||
if let Ok(contact) = contact {
|
||||
for property in contact.properties {
|
||||
println!("Parsed property {:?}", property);
|
||||
if property.name == "email" {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* we have a regular file attachment,
|
||||
write decoded data to new blob object */
|
||||
|
||||
@@ -1632,6 +1652,22 @@ mod tests {
|
||||
assert_eq!(mimeparser.group_avatar, None);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_mimeparser_with_vcard() {
|
||||
let t = TestContext::new().await;
|
||||
|
||||
let raw = include_bytes!("../test-data/message/vcard.eml");
|
||||
let mimeparser = MimeMessage::from_bytes(&t.ctx, &raw[..]).await.unwrap();
|
||||
assert_eq!(mimeparser.parts.len(), 1);
|
||||
assert_eq!(mimeparser.parts[0].typ, Viewtype::Text);
|
||||
assert_eq!(
|
||||
mimeparser.parts[0].msg,
|
||||
"vCard example – An example of vCard sent from Thunderbird."
|
||||
);
|
||||
assert_eq!(mimeparser.user_avatar, None);
|
||||
assert_eq!(mimeparser.group_avatar, None);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_mimeparser_message_kml() {
|
||||
let context = TestContext::new().await;
|
||||
|
||||
38
test-data/message/vcard.eml
Normal file
38
test-data/message/vcard.eml
Normal file
@@ -0,0 +1,38 @@
|
||||
Return-Path: <alice@example.org>
|
||||
Delivered-To: bob@example.org
|
||||
To: bob@example.org
|
||||
From: Alice <alice@example.org>
|
||||
Subject: vCard example
|
||||
Message-ID: <foobar@example.org>
|
||||
Date: Sun, 22 Nov 2020 22:44:00 +0000
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
|
||||
Thunderbird/78.4.3
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="------------01973B3475205164D5F9F507"
|
||||
Content-Language: en-US
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------01973B3475205164D5F9F507
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
An example of vCard sent from Thunderbird.
|
||||
|
||||
--------------01973B3475205164D5F9F507
|
||||
Content-Type: text/x-vcard; charset=utf-8;
|
||||
name="alice.vcf"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: attachment;
|
||||
filename="alice.vcf"
|
||||
|
||||
begin:vcard
|
||||
fn:Alice Foobar
|
||||
n:Foobar;Alice
|
||||
email;internet:alice@example.org
|
||||
x-mozilla-html:FALSE
|
||||
version:2.1
|
||||
end:vcard
|
||||
|
||||
|
||||
--------------01973B3475205164D5F9F507--
|
||||
Reference in New Issue
Block a user