@tutao/node-mimimi 277.250414.1 → 284.250428.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tutao/node-mimimi",
3
- "version": "277.250414.1",
3
+ "version": "284.250428.2",
4
4
  "main": "./dist/binding.js",
5
5
  "types": "./dist/binding.d.ts",
6
6
  "napi": {
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "license": "MIT",
15
15
  "devDependencies": {
16
- "@tutao/otest": "277.250414.1",
16
+ "@tutao/otest": "284.250428.2",
17
17
  "@napi-rs/cli": "3.0.0-alpha.68",
18
18
  "typescript": "5.3.3",
19
19
  "zx": "8.1.5"
@@ -30,8 +30,8 @@
30
30
  "version": "napi version"
31
31
  },
32
32
  "optionalDependencies": {
33
- "@tutao/node-mimimi-win32-x64-msvc": "277.250414.1",
34
- "@tutao/node-mimimi-linux-x64-gnu": "277.250414.1",
35
- "@tutao/node-mimimi-darwin-universal": "277.250414.1"
33
+ "@tutao/node-mimimi-win32-x64-msvc": "284.250428.2",
34
+ "@tutao/node-mimimi-linux-x64-gnu": "284.250428.2",
35
+ "@tutao/node-mimimi-darwin-universal": "284.250428.2"
36
36
  }
37
37
  }
@@ -156,6 +156,7 @@ impl From<MailContact> for MailAddress {
156
156
  name: value.name,
157
157
  contact: None,
158
158
  _finalIvs: Default::default(),
159
+ _errors: Default::default(),
159
160
  }
160
161
  }
161
162
  }
@@ -578,9 +579,10 @@ impl ImportableMail {
578
579
  .into_iter()
579
580
  .map(|reply_to| EncryptedMailAddress {
580
581
  _id: Some(tutasdk::CustomId::from_custom_string(FIXED_CUSTOM_ID)),
581
- _finalIvs: Default::default(),
582
582
  name: reply_to.name,
583
583
  address: reply_to.mail_address,
584
+ _finalIvs: Default::default(),
585
+ _errors: Default::default(),
584
586
  })
585
587
  .collect();
586
588
 
@@ -605,7 +607,6 @@ impl ImportableMail {
605
607
  _format: 0,
606
608
  ownerEncSessionKey: owner_enc_sk,
607
609
  ownerKeyVersion: owner_enc_sk_version,
608
- _finalIvs: Default::default(),
609
610
  compressedHeaders: headers_string,
610
611
  subject,
611
612
  compressedBodyText: html_body_text,
@@ -632,7 +633,8 @@ impl ImportableMail {
632
633
  inReplyTo: in_reply_to,
633
634
  references,
634
635
  importedAttachments: vec![],
635
- _errors: None,
636
+ _errors: Default::default(),
637
+ _finalIvs: Default::default(),
636
638
  }
637
639
  }
638
640
  }
@@ -653,10 +655,7 @@ impl ImportableMail {
653
655
  pub fn from_parsed_message(parsed_message: &mail_parser::Message) -> Self {
654
656
  let subject = parsed_message.subject().unwrap_or_default().to_string();
655
657
 
656
- let date = parsed_message
657
- .date()
658
- .as_ref()
659
- .map(|date_time| DateTime::from_millis(date_time.to_timestamp() as u64 * 1000));
658
+ let date = get_importable_date_time(parsed_message);
660
659
 
661
660
  let name_as_address_if_empty_address = |mut address: MailContact| -> MailContact {
662
661
  if address.mail_address.is_empty() && !address.name.is_empty() {
@@ -770,6 +769,22 @@ impl ImportableMail {
770
769
  }
771
770
  }
772
771
 
772
+ /**
773
+ * convert the "Date:" header value from the parsed message to something we can import.
774
+ * if the value isn't valid (parser returned -1 or the value doesn't fit in an u64
775
+ * when converted to milliseconds), we'll use midnight, 1st of January 1970 as a default.
776
+ */
777
+ fn get_importable_date_time(message: &mail_parser::Message) -> Option<DateTime> {
778
+ message
779
+ .date()
780
+ .map(mail_parser::DateTime::to_timestamp)
781
+ .map(|timestamp| timestamp.max(0))
782
+ .into_iter()
783
+ .filter_map(|millis| (millis as u64).checked_mul(1000))
784
+ .map(DateTime::from_millis)
785
+ .next()
786
+ }
787
+
773
788
  #[cfg(test)]
774
789
  mod mime_string_to_importable_mail_test;
775
790
  #[cfg(test)]
@@ -65,6 +65,8 @@ pub struct MailImportMessage {
65
65
  pub enum PreparationError {
66
66
  /// Can not create a native Rest client
67
67
  NoNativeRestClient,
68
+ /// Can not create a native file client
69
+ NoNativeFileClient,
68
70
  /// some error occurred while reading import directory
69
71
  CannotReadOldStateId,
70
72
  /// Error when trying to resume the session passed from client
@@ -134,6 +136,7 @@ impl From<PreparationError> for napi::Error {
134
136
  fn from(prep_err: PreparationError) -> Self {
135
137
  let code = match prep_err {
136
138
  PreparationError::NoNativeRestClient => "NoNativeRestClient",
139
+ PreparationError::NoNativeFileClient => "NoNativeFileClient",
137
140
  PreparationError::CannotReadOldStateId => "ImportDirectoryPreparation",
138
141
  PreparationError::LoginError => "LoginError",
139
142
  PreparationError::FailedToReadEmls => "FailedToReadEmls",
package/src/importer.rs CHANGED
@@ -19,6 +19,7 @@ use crate::importer::messages::{
19
19
  ImportErrorKind, ImportOkKind, MailImportErrorMessage, PreparationError,
20
20
  };
21
21
  use crate::importer_api::TutaCredentials;
22
+ use tutasdk::bindings::native_file_client::NativeFileClient;
22
23
  use tutasdk::entities::generated::tutanota::{
23
24
  ImportMailGetIn, ImportMailPostIn, ImportMailPostOut, ImportMailState,
24
25
  };
@@ -234,7 +235,7 @@ impl ImportEssential {
234
235
  ownerKeyVersion: owner_enc_sk_for_import_state_get.version as i64,
235
236
  totalMails: total_importable_mails,
236
237
  targetMailFolder: target_mailset,
237
- _errors: None,
238
+ _errors: Default::default(),
238
239
  _finalIvs: Default::default(),
239
240
  };
240
241
 
@@ -308,6 +309,7 @@ impl Importer {
308
309
  }
309
310
 
310
311
  pub(super) async fn create_sdk(
312
+ config_directory: &str,
311
313
  tuta_credentials: TutaCredentials,
312
314
  ) -> Result<Arc<LoggedInSdk>, PreparationError> {
313
315
  let base_url = tuta_credentials.api_url.clone();
@@ -315,14 +317,19 @@ impl Importer {
315
317
  log::error!("Can not create new native rest client: {e:?}");
316
318
  PreparationError::NoNativeRestClient
317
319
  })?;
320
+ let file_client = NativeFileClient::try_new(config_directory.into()).map_err(|e| {
321
+ log::error!("Can not create new native rest client: {e:?}");
322
+ PreparationError::NoNativeRestClient
323
+ })?;
318
324
 
319
- let logged_in_sdk = tutasdk::Sdk::new(base_url, Arc::new(rest_client))
320
- .login(tuta_credentials.into())
321
- .await
322
- .map_err(|e| {
323
- log::error!("Can not login to sdk: {e:?}");
324
- PreparationError::LoginError
325
- })?;
325
+ let logged_in_sdk =
326
+ tutasdk::Sdk::new(base_url, Arc::new(rest_client), Arc::new(file_client))
327
+ .login(tuta_credentials.into())
328
+ .await
329
+ .map_err(|e| {
330
+ log::error!("Can not login to sdk: {e:?}");
331
+ PreparationError::LoginError
332
+ })?;
326
333
 
327
334
  Ok(logged_in_sdk)
328
335
  }
@@ -366,7 +373,7 @@ impl Importer {
366
373
  fs_email_client: FileImport::new(eml_files_to_import),
367
374
  };
368
375
 
369
- let logged_in_sdk = Self::create_sdk(tuta_credentials).await?;
376
+ let logged_in_sdk = Self::create_sdk(&config_directory, tuta_credentials).await?;
370
377
  let remote_import_state = logged_in_sdk
371
378
  .mail_facade()
372
379
  .get_crypto_entity_client()
@@ -775,6 +782,21 @@ pub mod tests {
775
782
  assert_eq!(remote_state.successfulMails, 1);
776
783
  }
777
784
 
785
+ #[cfg_attr(
786
+ not(feature = "test-with-local-http-server"),
787
+ ignore = "require local http server."
788
+ )]
789
+ #[tokio::test]
790
+ async fn can_import_single_eml_file_with_invalid_date() {
791
+ let importer = init_file_importer(vec!["brokendate.eml"]).await;
792
+ importer.start_stateful_import().await.unwrap();
793
+
794
+ let remote_state = importer.essentials.load_remote_state().await.unwrap();
795
+ assert_eq!(remote_state.status, ImportStatus::Finished as i64);
796
+ assert_eq!(remote_state.failedMails, 0);
797
+ assert_eq!(remote_state.successfulMails, 1);
798
+ }
799
+
778
800
  #[test]
779
801
  fn max_request_size_in_test_is_different() {
780
802
  assert_eq!(1024 * 5, MAX_REQUEST_SIZE);
@@ -238,7 +238,7 @@ impl ImporterApi {
238
238
  let import_directory =
239
239
  FileImport::prepare_file_import(config_directory, mailbox_id, source_paths)?;
240
240
 
241
- let logged_in_sdk = Importer::create_sdk(tuta_credentials).await?;
241
+ let logged_in_sdk = Importer::create_sdk(config_directory, tuta_credentials).await?;
242
242
  Importer::create_new_file_importer(
243
243
  logged_in_sdk,
244
244
  target_owner_group,
package/src/test_utils.rs CHANGED
@@ -3,6 +3,7 @@ use crate::importer::Importer;
3
3
  use std::fs;
4
4
  use std::path::PathBuf;
5
5
  use std::sync::{Arc, Mutex};
6
+ use tutasdk::bindings::test_file_client::TestFileClient;
6
7
  use tutasdk::entities::generated::tutanota::MailFolder;
7
8
  use tutasdk::folder_system::MailSetKind;
8
9
  use tutasdk::net::native_rest_client::NativeRestClient;
@@ -48,6 +49,7 @@ pub async fn init_file_importer(source_paths: Vec<&str>) -> Importer {
48
49
  let logged_in_sdk = Sdk::new(
49
50
  "http://localhost:9000".to_string(),
50
51
  Arc::new(NativeRestClient::try_new().unwrap()),
52
+ Arc::new(TestFileClient::default()),
51
53
  )
52
54
  .create_session(IMPORTED_MAIL_ADDRESS, IMPORTED_MAIL_ADDRESS_PASSKEY)
53
55
  .await
@@ -0,0 +1,9 @@
1
+ Content-Type: text/plain; charset=iso-8859-1; format=flowed
2
+ Content-Transfer-Encoding: 8bit
3
+ To: sorry@noemail.eu
4
+ From: noreply@noemail.eu
5
+ Date: Fri, Dec 14 2001 16:05:48 -0800
6
+ MIME-Version: 1.0
7
+ Subject: Broken date
8
+
9
+ This mail contains a date header that doesn't conform to the standard.