@tutao/node-mimimi 264.250127.0 → 264.250130.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +8 -23
- package/make.js +2 -12
- package/package.json +12 -15
- package/src/importer/importable_mail.rs +23 -48
- package/src/importer.rs +3 -10
- package/src/lib.rs +0 -1
- package/tests/resources/mimetools-testmsgs/faulty_multi_part_no_content_type-expected.json +34 -0
- package/tests/resources/mimetools-testmsgs/faulty_multi_part_no_content_type.msg +21 -0
- package/tests/resources/mimetools-testmsgs/faulty_multi_part_partial_content_type-expected.json +36 -0
- package/tests/resources/mimetools-testmsgs/faulty_multi_part_partial_content_type.msg +21 -0
- package/java/build.gradle.kts +0 -24
- package/java/settings.gradle.kts +0 -24
- package/java/src/main/java/greenmailserver/GreenMailServer.java +0 -63
- package/src/importer/imap_reader.rs +0 -166
- package/src/tuta_imap/client/tls_stream.rs +0 -109
- package/src/tuta_imap/client/types.rs +0 -37
- package/src/tuta_imap/client.rs +0 -559
- package/src/tuta_imap/testing/jvm_singeleton.rs +0 -21
- package/src/tuta_imap/testing/utils.rs +0 -5
- package/src/tuta_imap/testing.rs +0 -166
- package/src/tuta_imap/utils.rs +0 -1
package/Cargo.toml
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
edition = "2021"
|
|
3
3
|
name = "tutao_node-mimimi"
|
|
4
|
-
version = "264.
|
|
4
|
+
version = "264.250130.0"
|
|
5
5
|
|
|
6
6
|
[lib]
|
|
7
|
-
|
|
8
|
-
crate-type = ["cdylib", "lib"]
|
|
7
|
+
crate-type = ["cdylib"]
|
|
9
8
|
|
|
10
9
|
[profile.release]
|
|
11
10
|
lto = true
|
|
@@ -14,30 +13,20 @@ strip = "symbols"
|
|
|
14
13
|
|
|
15
14
|
[dependencies]
|
|
16
15
|
tuta-sdk = { path = "../../tuta-sdk/rust/sdk", features = ["net"] }
|
|
17
|
-
async-trait = "0.1.
|
|
16
|
+
async-trait = "0.1.85"
|
|
18
17
|
rand = { version = "0.8.5" }
|
|
19
18
|
mail-parser = { version = "0.9.4", features = ["full_encoding"] }
|
|
20
|
-
thiserror = { version = "
|
|
19
|
+
thiserror = { version = "2.0" }
|
|
21
20
|
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
|
|
22
|
-
napi = { version = "2.16.
|
|
23
|
-
napi-derive = { version = "2.16.
|
|
21
|
+
napi = { version = "2.16.13", default-features = false, features = ["napi9", "async", "tokio_rt"] }
|
|
22
|
+
napi-derive = { version = "2.16.13", optional = true }
|
|
24
23
|
base64 = "0.22.1"
|
|
25
24
|
log = { version = "0.4.22" }
|
|
26
|
-
|
|
27
|
-
# used for tuta-imap
|
|
28
|
-
serde = { version = "1.0.210", features = ["derive"] }
|
|
29
|
-
rustls = { version = "0.23.13", features = ["std"] }
|
|
30
25
|
regex = "1.11.1"
|
|
31
|
-
|
|
32
|
-
[dependencies.imap-codec]
|
|
33
|
-
git = "https://github.com/duesee/imap-codec.git"
|
|
34
|
-
rev = "16a5c182285c7a895b06276f68a116caf2cb294f"
|
|
35
|
-
features = ["serde", "starttls", "ext_id", "ext_metadata"]
|
|
36
|
-
|
|
26
|
+
serde = { version = "1.0.210", features = ["derive"] }
|
|
37
27
|
|
|
38
28
|
[build-dependencies]
|
|
39
|
-
|
|
40
|
-
napi-build = { version = "=2.1.3" }
|
|
29
|
+
napi-build = { version = "2.1.4" }
|
|
41
30
|
|
|
42
31
|
[dev-dependencies]
|
|
43
32
|
base64 = "0.22.1"
|
|
@@ -46,10 +35,6 @@ serde_json = "1"
|
|
|
46
35
|
tuta-sdk = { path = "../../tuta-sdk/rust/sdk", features = ["net", "testing"] }
|
|
47
36
|
mail-builder = { version = "0.3.2" }
|
|
48
37
|
|
|
49
|
-
# tuta-imap
|
|
50
|
-
j4rs = { version = "0.20.0" }
|
|
51
|
-
lazy_static = { version = "0.2.11" }
|
|
52
|
-
|
|
53
38
|
[features]
|
|
54
39
|
default = ["javascript"]
|
|
55
40
|
# needed to turn off the autogenerated ffi when using the tests
|
package/make.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Argument, program } from "commander"
|
|
2
|
-
import {
|
|
3
|
-
import path from "node:path"
|
|
4
|
-
import url from "node:url"
|
|
2
|
+
import { usePowerShell } from "zx"
|
|
5
3
|
import { rm } from "node:fs/promises"
|
|
6
4
|
import { NapiCli } from "@napi-rs/cli"
|
|
7
5
|
|
|
@@ -10,7 +8,6 @@ await program
|
|
|
10
8
|
.addArgument(new Argument("platform").choices(["win", "linux", "darwin", "native"]).default("native").argOptional())
|
|
11
9
|
.option("-c, --clean", "clean build artifacts")
|
|
12
10
|
.option("-r, --release", "run a release build")
|
|
13
|
-
.option("--greenmail", "also run the greenmail build")
|
|
14
11
|
.action(run)
|
|
15
12
|
.parseAsync(process.argv)
|
|
16
13
|
|
|
@@ -35,20 +32,13 @@ function getTargets(platform) {
|
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
|
|
38
|
-
async function run(platform, { clean, release
|
|
35
|
+
async function run(platform, { clean, release }) {
|
|
39
36
|
if (clean) {
|
|
40
37
|
await rm("./build", { recursive: true, force: true })
|
|
41
38
|
await rm("./target", { recursive: true, force: true })
|
|
42
39
|
await rm("./dist", { recursive: true, force: true })
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
if (greenmail) {
|
|
46
|
-
const currentPath = path.dirname(url.fileURLToPath(import.meta.url))
|
|
47
|
-
cd(path.join(currentPath, "java"))
|
|
48
|
-
await $`/opt/gradle-8.5/bin/gradle jar`
|
|
49
|
-
cd("..")
|
|
50
|
-
}
|
|
51
|
-
|
|
52
42
|
const targets = getTargets(platform)
|
|
53
43
|
|
|
54
44
|
for (const target of targets) {
|
package/package.json
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tutao/node-mimimi",
|
|
3
|
-
"version": "264.
|
|
3
|
+
"version": "264.250130.0",
|
|
4
4
|
"main": "./dist/binding.js",
|
|
5
5
|
"types": "./dist/binding.d.ts",
|
|
6
6
|
"napi": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"universal-apple-darwin"
|
|
14
|
-
]
|
|
15
|
-
}
|
|
7
|
+
"binaryName": "node-mimimi",
|
|
8
|
+
"targets": [
|
|
9
|
+
"x86_64-pc-windows-msvc",
|
|
10
|
+
"x86_64-unknown-linux-gnu",
|
|
11
|
+
"universal-apple-darwin"
|
|
12
|
+
]
|
|
16
13
|
},
|
|
17
14
|
"license": "MIT",
|
|
18
15
|
"devDependencies": {
|
|
19
|
-
"@tutao/otest": "264.
|
|
20
|
-
"@napi-rs/cli": "3.0.0-alpha.
|
|
16
|
+
"@tutao/otest": "264.250130.0",
|
|
17
|
+
"@napi-rs/cli": "3.0.0-alpha.68",
|
|
21
18
|
"typescript": "5.3.3",
|
|
22
19
|
"zx": "8.1.5"
|
|
23
20
|
},
|
|
@@ -33,8 +30,8 @@
|
|
|
33
30
|
"version": "napi version"
|
|
34
31
|
},
|
|
35
32
|
"optionalDependencies": {
|
|
36
|
-
"@tutao/node-mimimi-win32-x64-msvc": "264.
|
|
37
|
-
"@tutao/node-mimimi-linux-x64-gnu": "264.
|
|
38
|
-
"@tutao/node-mimimi-darwin-universal": "264.
|
|
33
|
+
"@tutao/node-mimimi-win32-x64-msvc": "264.250130.0",
|
|
34
|
+
"@tutao/node-mimimi-linux-x64-gnu": "264.250130.0",
|
|
35
|
+
"@tutao/node-mimimi-darwin-universal": "264.250130.0"
|
|
39
36
|
}
|
|
40
37
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
use crate::importer::ImportEssential;
|
|
2
|
-
use crate::tuta_imap::client::types::ImapMail;
|
|
3
2
|
use extend_mail_parser::MakeString;
|
|
4
3
|
use mail_parser::decoders::base64::base64_decode;
|
|
5
4
|
use mail_parser::decoders::quoted_printable::quoted_printable_decode;
|
|
@@ -251,15 +250,17 @@ impl ImportableMail {
|
|
|
251
250
|
.expect("Expected multipart part to be there?");
|
|
252
251
|
|
|
253
252
|
// for now, we can only decide between alternative between text/plain and text/html
|
|
254
|
-
|
|
253
|
+
// todo: handle other content type. example: choosing one image from list of alternatives?
|
|
254
|
+
let (is_text_plain, is_text_html) = alternative_part
|
|
255
255
|
.content_type()
|
|
256
|
-
.
|
|
256
|
+
.map(|content_type| {
|
|
257
|
+
let is_plain = content_type.c_type == "plain";
|
|
258
|
+
let is_text_plain = is_plain && content_type.subtype() == Some("text");
|
|
259
|
+
let is_text_html = is_plain && content_type.subtype() == Some("text");
|
|
257
260
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
let is_text_html = alternative_content_type.c_type == "text"
|
|
262
|
-
&& alternative_content_type.subtype() == Some("html");
|
|
261
|
+
(is_text_plain, is_text_html)
|
|
262
|
+
})
|
|
263
|
+
.unwrap_or((false, false));
|
|
263
264
|
|
|
264
265
|
if is_text_plain {
|
|
265
266
|
// always ignore plain. we can display html everytime
|
|
@@ -273,12 +274,9 @@ impl ImportableMail {
|
|
|
273
274
|
}
|
|
274
275
|
best_alternative_yet = Some(*multipart_id);
|
|
275
276
|
} else {
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
multipart_ignored_alternative.insert(last_choice);
|
|
280
|
-
}
|
|
281
|
-
best_alternative_yet = Some(*multipart_id);
|
|
277
|
+
// Can only choose multipart/alternative between text/plain and text/html
|
|
278
|
+
// if there is any other format, ignore it
|
|
279
|
+
multipart_ignored_alternative.insert(*multipart_id);
|
|
282
280
|
}
|
|
283
281
|
}
|
|
284
282
|
|
|
@@ -286,19 +284,17 @@ impl ImportableMail {
|
|
|
286
284
|
// don't have to do anything with chosen multipart,
|
|
287
285
|
// it will anyway be included in next iteration
|
|
288
286
|
if best_alternative_yet.is_none() {
|
|
289
|
-
let last_choice = multi_part_ids
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
"if we did not put last_choice in ignore list. why best_alternative_yet is none?"
|
|
301
|
-
);
|
|
287
|
+
if let Some(last_choice) = multi_part_ids.last() {
|
|
288
|
+
// do we remove the last_choice from ignored list?
|
|
289
|
+
// the problem is:
|
|
290
|
+
// will the same alternative part can be referenced by multiple multipart block?
|
|
291
|
+
// if so, if we remove last_choice now, and this was also ignored by another multipart,
|
|
292
|
+
// we will display it anyhow. probably this is right, right?
|
|
293
|
+
assert!(
|
|
294
|
+
multipart_ignored_alternative.remove(last_choice),
|
|
295
|
+
"if we did not put last_choice in ignore list. why best_alternative_yet is none?"
|
|
296
|
+
);
|
|
297
|
+
}
|
|
302
298
|
}
|
|
303
299
|
|
|
304
300
|
// ps: we assume that the order is:
|
|
@@ -658,27 +654,6 @@ enum ContentTransferEncoding {
|
|
|
658
654
|
Other,
|
|
659
655
|
}
|
|
660
656
|
|
|
661
|
-
impl TryFrom<ImapMail> for ImportableMail {
|
|
662
|
-
type Error = MailParseError;
|
|
663
|
-
fn try_from(imap_mail: ImapMail) -> Result<Self, Self::Error> {
|
|
664
|
-
let ImapMail { rfc822_full } = imap_mail;
|
|
665
|
-
|
|
666
|
-
// parse the full mime message
|
|
667
|
-
let imap_mail = mail_parser::MessageParser::default()
|
|
668
|
-
.parse(rfc822_full.as_slice())
|
|
669
|
-
.ok_or(MailParseError::InvalidMimeMessage)?;
|
|
670
|
-
|
|
671
|
-
let mut importable_mail = Self::convert_from(&imap_mail, None);
|
|
672
|
-
|
|
673
|
-
// example:
|
|
674
|
-
// add more details from imap if given,
|
|
675
|
-
importable_mail.is_phishing = false;
|
|
676
|
-
importable_mail.unread = true;
|
|
677
|
-
|
|
678
|
-
Ok(importable_mail)
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
|
|
682
657
|
#[derive(Debug, Clone, PartialEq)]
|
|
683
658
|
pub enum MailParseError {
|
|
684
659
|
InvalidMimeMessage,
|
package/src/importer.rs
CHANGED
|
@@ -5,7 +5,6 @@ use crate::reduce_to_chunks::{AttachmentUploadData, KeyedImportMailData};
|
|
|
5
5
|
use base64::prelude::BASE64_URL_SAFE_NO_PAD;
|
|
6
6
|
use base64::Engine;
|
|
7
7
|
use file_reader::FileImport;
|
|
8
|
-
use imap_reader::ImapImportConfig;
|
|
9
8
|
use importable_mail::ImportableMail;
|
|
10
9
|
use std::ffi::OsStr;
|
|
11
10
|
use std::fs;
|
|
@@ -37,7 +36,6 @@ pub mod messages;
|
|
|
37
36
|
|
|
38
37
|
pub mod file_reader;
|
|
39
38
|
mod filename_producer;
|
|
40
|
-
pub mod imap_reader;
|
|
41
39
|
pub mod importable_mail;
|
|
42
40
|
|
|
43
41
|
#[cfg(not(test))]
|
|
@@ -58,14 +56,9 @@ pub struct ImportMailStateId {
|
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
#[derive(Clone, PartialEq)]
|
|
61
|
-
pub
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
},
|
|
65
|
-
LocalFile {
|
|
66
|
-
file_path: String,
|
|
67
|
-
is_mbox: bool,
|
|
68
|
-
},
|
|
59
|
+
pub struct LocalFileImportParams {
|
|
60
|
+
file_path: String,
|
|
61
|
+
is_mbox: bool,
|
|
69
62
|
}
|
|
70
63
|
|
|
71
64
|
/// current state of the imap_reader import for this tuta account
|
package/src/lib.rs
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"exception" : null,
|
|
3
|
+
"result" : {
|
|
4
|
+
"id" : "CAP4CaRo=fQu-7TkamEOH87i2CQyNznk6tUoUsoHpV5aU-TMqKQ@mail.gmail.com",
|
|
5
|
+
"boundary" : null,
|
|
6
|
+
"alternativeBoundary" : "0000000000002f88560628478f99",
|
|
7
|
+
"sender" : {
|
|
8
|
+
"name" : "Bed: für Test!",
|
|
9
|
+
"mailAddress" : "this-is-a-test-email-address@gmail.com",
|
|
10
|
+
"valid" : true
|
|
11
|
+
},
|
|
12
|
+
"toRecipients" : [ {
|
|
13
|
+
"name" : "",
|
|
14
|
+
"mailAddress" : "this-is-a-test-email-address@tutao.de",
|
|
15
|
+
"valid" : true
|
|
16
|
+
} ],
|
|
17
|
+
"ccRecipients" : [ ],
|
|
18
|
+
"bccRecipients" : [ ],
|
|
19
|
+
"replyTo" : [ ],
|
|
20
|
+
"inReplyTo" : null,
|
|
21
|
+
"references" : [ ],
|
|
22
|
+
"autoSubmitted" : null,
|
|
23
|
+
"sentDate" : 1733137670000,
|
|
24
|
+
"subject" : "test",
|
|
25
|
+
"plainBodyText" : "\r\n<div dir=\"ltr\">test<br></div>\r\n",
|
|
26
|
+
"htmlBodyText" : null,
|
|
27
|
+
"attachedMessages" : [ ],
|
|
28
|
+
"attachedFiles" : [ ],
|
|
29
|
+
"mailHeaders" : "From 1817326565723760995@xxx Mon Dec 02 11:07:50 +0000 2024\nX-GM-THRID: 1817326560552955180\nX-Gmail-Labels: Archived,Sent\nMIME-Version: 1.0\nDate: Mon, 2 Dec 2024 12:07:50 +0100\nMessage-ID: <CAP4CaRo=fQu-7TkamEOH87i2CQyNznk6tUoUsoHpV5aU-TMqKQ@mail.gmail.com>\nSubject: test\nFrom: \"Bed: für Test!\" <this-is-a-test-email-address@gmail.com>\nTo: this-is-a-test-email-address@tutao.de\nContent-Type: multipart/alternative; boundary=\"0000000000002f88560628478f99\"",
|
|
30
|
+
"spfResult" : "None",
|
|
31
|
+
"listUnsubscribe" : false,
|
|
32
|
+
"mailAuthenticationResult" : null
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
From 1817326565723760995@xxx Mon Dec 02 11:07:50 +0000 2024
|
|
2
|
+
X-GM-THRID: 1817326560552955180
|
|
3
|
+
X-Gmail-Labels: Archived,Sent
|
|
4
|
+
MIME-Version: 1.0
|
|
5
|
+
Date: Mon, 2 Dec 2024 12:07:50 +0100
|
|
6
|
+
Message-ID: <CAP4CaRo=fQu-7TkamEOH87i2CQyNznk6tUoUsoHpV5aU-TMqKQ@mail.gmail.com>
|
|
7
|
+
Subject: test
|
|
8
|
+
From: =?UTF-8?B?QmVkOiBmw7xyIFRlc3Qh?= <this-is-a-test-email-address@gmail.com>
|
|
9
|
+
To: this-is-a-test-email-address@tutao.de
|
|
10
|
+
Content-Type: multipart/alternative; boundary="0000000000002f88560628478f99"
|
|
11
|
+
|
|
12
|
+
--0000000000002f88560628478f99
|
|
13
|
+
|
|
14
|
+
test
|
|
15
|
+
|
|
16
|
+
--0000000000002f88560628478f99
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
<div dir="ltr">test<br></div>
|
|
20
|
+
|
|
21
|
+
--0000000000002f88560628478f99--
|
package/tests/resources/mimetools-testmsgs/faulty_multi_part_partial_content_type-expected.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"exception" : null,
|
|
3
|
+
"result" : {
|
|
4
|
+
"id" : "CAP4CaRo=fQu-7TkamEOH87i2CQyNznk6tUoUsoHpV5aU-TMqKQ@mail.gmail.com",
|
|
5
|
+
"boundary" : null,
|
|
6
|
+
"alternativeBoundary" : "0000000000002f88560628478f99",
|
|
7
|
+
"sender" : {
|
|
8
|
+
"name" : "Bed: für Test!",
|
|
9
|
+
"mailAddress" : "this-is-a-test-email-address@gmail.com",
|
|
10
|
+
"valid" : true
|
|
11
|
+
},
|
|
12
|
+
"toRecipients" : [
|
|
13
|
+
{
|
|
14
|
+
"name" : "",
|
|
15
|
+
"mailAddress" : "this-is-a-test-email-address@tutao.de",
|
|
16
|
+
"valid" : true
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"ccRecipients" : [],
|
|
20
|
+
"bccRecipients" : [],
|
|
21
|
+
"replyTo" : [],
|
|
22
|
+
"inReplyTo" : null,
|
|
23
|
+
"references" : [],
|
|
24
|
+
"autoSubmitted" : null,
|
|
25
|
+
"sentDate" : 1733137670000,
|
|
26
|
+
"subject" : "test",
|
|
27
|
+
"plainBodyText" : "<div dir=\"ltr\">test<br></div>\r\n",
|
|
28
|
+
"htmlBodyText" : null,
|
|
29
|
+
"attachedMessages" : [],
|
|
30
|
+
"attachedFiles" : [],
|
|
31
|
+
"mailHeaders" : "From 1817326565723760995@xxx Mon Dec 02 11:07:50 +0000 2024\nX-GM-THRID: 1817326560552955180\nX-Gmail-Labels: Archived,Sent\nMIME-Version: 1.0\nDate: Mon, 2 Dec 2024 12:07:50 +0100\nMessage-ID: <CAP4CaRo=fQu-7TkamEOH87i2CQyNznk6tUoUsoHpV5aU-TMqKQ@mail.gmail.com>\nSubject: test\nFrom: \"Bed: für Test!\" <this-is-a-test-email-address@gmail.com>\nTo: this-is-a-test-email-address@tutao.de\nContent-Type: multipart/alternative; boundary=\"0000000000002f88560628478f99\"",
|
|
32
|
+
"spfResult" : "None",
|
|
33
|
+
"listUnsubscribe" : false,
|
|
34
|
+
"mailAuthenticationResult" : null
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
From 1817326565723760995@xxx Mon Dec 02 11:07:50 +0000 2024
|
|
2
|
+
X-GM-THRID: 1817326560552955180
|
|
3
|
+
X-Gmail-Labels: Archived,Sent
|
|
4
|
+
MIME-Version: 1.0
|
|
5
|
+
Date: Mon, 2 Dec 2024 12:07:50 +0100
|
|
6
|
+
Message-ID: <CAP4CaRo=fQu-7TkamEOH87i2CQyNznk6tUoUsoHpV5aU-TMqKQ@mail.gmail.com>
|
|
7
|
+
Subject: test
|
|
8
|
+
From: =?UTF-8?B?QmVkOiBmw7xyIFRlc3Qh?= <this-is-a-test-email-address@gmail.com>
|
|
9
|
+
To: this-is-a-test-email-address@tutao.de
|
|
10
|
+
Content-Type: multipart/alternative; boundary="0000000000002f88560628478f99"
|
|
11
|
+
|
|
12
|
+
--0000000000002f88560628478f99
|
|
13
|
+
Content-Type: text/plain; charset="UTF-8"
|
|
14
|
+
|
|
15
|
+
test
|
|
16
|
+
|
|
17
|
+
--0000000000002f88560628478f99
|
|
18
|
+
|
|
19
|
+
<div dir="ltr">test<br></div>
|
|
20
|
+
|
|
21
|
+
--0000000000002f88560628478f99--
|
package/java/build.gradle.kts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
repositories {
|
|
2
|
-
mavenLocal()
|
|
3
|
-
maven {
|
|
4
|
-
credentials(PasswordCredentials::class)
|
|
5
|
-
url = uri("https://next.tutao.de/nexus/content/groups/public/")
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
plugins {
|
|
10
|
-
java
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
dependencies {
|
|
14
|
-
implementation("com.icegreen:greenmail-standalone:2.1.0")
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
tasks.jar {
|
|
18
|
-
val dependencies = configurations
|
|
19
|
-
.runtimeClasspath
|
|
20
|
-
.get()
|
|
21
|
-
.map(::zipTree) // OR .map { zipTree(it) }
|
|
22
|
-
from(dependencies)
|
|
23
|
-
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
24
|
-
}
|
package/java/settings.gradle.kts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
rootProject.name = "greenmail-test-server"
|
|
2
|
-
|
|
3
|
-
pluginManagement {
|
|
4
|
-
repositories {
|
|
5
|
-
mavenLocal()
|
|
6
|
-
maven {
|
|
7
|
-
url = uri("https://next.tutao.de/nexus/content/groups/public/")
|
|
8
|
-
credentials(PasswordCredentials::class)
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
buildscript {
|
|
14
|
-
repositories {
|
|
15
|
-
mavenLocal()
|
|
16
|
-
maven {
|
|
17
|
-
credentials(PasswordCredentials::class)
|
|
18
|
-
url = uri("https://next.tutao.de/nexus/content/groups/public/")
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
dependencies {
|
|
22
|
-
classpath(group = "de.tutao.gradle", name = "devDefaults", version = "3.6.2")
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
package greenmailserver;
|
|
2
|
-
|
|
3
|
-
import com.icegreen.greenmail.user.GreenMailUser;
|
|
4
|
-
import com.icegreen.greenmail.user.UserException;
|
|
5
|
-
import com.icegreen.greenmail.util.GreenMail;
|
|
6
|
-
import com.icegreen.greenmail.util.ServerSetup;
|
|
7
|
-
import jakarta.mail.MessagingException;
|
|
8
|
-
import jakarta.mail.internet.MimeMessage;
|
|
9
|
-
|
|
10
|
-
import java.io.ByteArrayInputStream;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
public class GreenMailServer {
|
|
14
|
-
public static final String imapsHost = "127.0.0.1";
|
|
15
|
-
|
|
16
|
-
private GreenMail greenMail;
|
|
17
|
-
|
|
18
|
-
public GreenMailUser userMap;
|
|
19
|
-
public GreenMailUser userSug;
|
|
20
|
-
|
|
21
|
-
public GreenMailServer(Integer p) {
|
|
22
|
-
setSystemClassLoaderForCurrentThreadContext();
|
|
23
|
-
|
|
24
|
-
ServerSetup defaultImapsProps = new ServerSetup(p, imapsHost, "imaps");
|
|
25
|
-
try {
|
|
26
|
-
greenMail = new GreenMail(defaultImapsProps);
|
|
27
|
-
} catch (Exception e) {
|
|
28
|
-
e.printStackTrace();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
greenMail.start();
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
userMap = greenMail.getUserManager().createUser("map@example.org", "map@example.org", "map");
|
|
35
|
-
userSug = greenMail.getUserManager().createUser("sug@example.org", "sug@example.org", "sug");
|
|
36
|
-
} catch (UserException e) {
|
|
37
|
-
throw new RuntimeException(e);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public void stop() {
|
|
42
|
-
greenMail.stop();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public void store_mail(String recipientAddress, String mimeMsg) throws MessagingException {
|
|
46
|
-
var recipient = greenMail.getUserManager().getUserByEmail(recipientAddress);
|
|
47
|
-
var mimeMessage = new MimeMessage(null, new ByteArrayInputStream(mimeMsg.getBytes()));
|
|
48
|
-
recipient.deliver(mimeMessage);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// ========= configuration required for (rust) jni interface ==================
|
|
53
|
-
|
|
54
|
-
// For the class loaded by jni, .getCurrentThread().getContextClassLoader() will be null
|
|
55
|
-
// set it to systemClassLoader
|
|
56
|
-
public static void setSystemClassLoaderForCurrentThreadContext() {
|
|
57
|
-
if (Thread.currentThread().getContextClassLoader() == null) {
|
|
58
|
-
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
|
59
|
-
Thread.currentThread().setContextClassLoader(cl);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
}
|