diff --git a/src/modules/context/executors.rs b/src/modules/context/executors.rs
index a615c5b..c2ccb8f 100644
--- a/src/modules/context/executors.rs
+++ b/src/modules/context/executors.rs
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
+use crate::modules::account::migration::AccountType;
use crate::modules::context::Initialize;
use crate::modules::error::code::ErrorCode;
use crate::raise_error;
@@ -33,8 +33,7 @@ use dashmap::DashMap;
use std::sync::{Arc, LazyLock};
use tracing::info;
-pub static MAIL_CONTEXT: LazyLock =
- LazyLock::new(EmailClientExecutors::new);
+pub static MAIL_CONTEXT: LazyLock = LazyLock::new(EmailClientExecutors::new);
pub struct EmailClientExecutors {
start_at: i64,
@@ -88,15 +87,17 @@ impl EmailClientExecutors {
pub async fn start_account_syncers(&self) -> BichonResult<()> {
let accounts = AccountModel::list_all().await?;
- let active_accounts: Vec =
- accounts.into_iter().filter(|a| a.enabled).collect();
+ let active_accounts: Vec = accounts
+ .into_iter()
+ .filter(|a| a.enabled && matches!(a.account_type, AccountType::IMAP))
+ .collect();
if active_accounts.is_empty() {
info!("No active accounts found for account initialization.");
return Ok(());
}
info!(
- "System has {} active accounts to initialize.",
+ "System has {} active IMAP accounts to initialize.",
active_accounts.len()
);
for account in active_accounts {
diff --git a/src/modules/envelope/extractor.rs b/src/modules/envelope/extractor.rs
index ed6134a..7a17ba4 100644
--- a/src/modules/envelope/extractor.rs
+++ b/src/modules/envelope/extractor.rs
@@ -16,7 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use crate::modules::common::AddrVec;
use crate::modules::error::code::ErrorCode;
use crate::modules::error::BichonResult;
@@ -33,12 +32,12 @@ pub fn extract_envelope(fetch: &Fetch, account_id: u64, mailbox_id: u64) -> Bich
.map(|d| d.timestamp_millis())
.unwrap_or(0);
let uid = fetch.uid.unwrap_or(0);
- let size = fetch.size.unwrap_or(0);
let body = fetch
.body()
.ok_or_else(|| raise_error!("No body available".into(), ErrorCode::InternalError))?;
+ let size = fetch.size.unwrap_or(body.len() as u32);
let message = MessageParser::new().parse(body).ok_or_else(|| {
raise_error!(
"Email header parse result is not available".into(),
@@ -118,6 +117,92 @@ pub fn extract_envelope(fetch: &Fetch, account_id: u64, mailbox_id: u64) -> Bich
Ok(envelope)
}
+pub fn extract_envelope_from_eml(
+ body: &[u8],
+ account_id: u64,
+ mailbox_id: u64,
+) -> BichonResult {
+ let uid = 0;
+ let size = body.len() as u32;
+ let message = MessageParser::new().parse(body).ok_or_else(|| {
+ raise_error!(
+ "Email header parse result is not available".into(),
+ ErrorCode::InternalError
+ )
+ })?;
+
+ let text = if let Some(text) = message.body_text(0).map(|cow| cow.into_owned()) {
+ text
+ } else if let Some(html) = message.body_html(0).map(|cow| cow.into_owned()) {
+ from_read(html.as_bytes(), 0)
+ .map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?
+ } else {
+ String::new()
+ };
+
+ let message_id = message
+ .message_id()
+ .map(String::from)
+ .unwrap_or(generate_message_id());
+ let in_reply_to = message.in_reply_to().as_text().map(String::from);
+ let references = extract_references(&message);
+ let thread_id = compute_thread_id(in_reply_to, references, &message_id);
+ let subject = message.subject().map(String::from).unwrap_or("".into());
+ let date = message.date().map(|d| d.to_timestamp() * 1000).unwrap_or(0);
+ let bcc: Option> = message.bcc().map(|addr| {
+ AddrVec::from(addr)
+ .0
+ .into_iter()
+ .filter_map(|a| a.address)
+ .collect()
+ });
+ let cc: Option> = message.cc().map(|addr| {
+ AddrVec::from(addr)
+ .0
+ .into_iter()
+ .filter_map(|a| a.address)
+ .collect()
+ });
+ let to: Option> = message.to().map(|addr| {
+ AddrVec::from(addr)
+ .0
+ .into_iter()
+ .filter_map(|a| a.address)
+ .collect()
+ });
+ let from = message
+ .from()
+ .and_then(|addr| AddrVec::from(addr).0.into_iter().next())
+ .and_then(|add| add.address)
+ .unwrap_or_else(|| "unknown".to_string());
+
+ let attachments: Vec = message
+ .attachments()
+ .filter_map(|att| att.attachment_name())
+ .map(|name| name.to_string())
+ .collect();
+ let envelope = Envelope {
+ id: create_hash(account_id, &message_id),
+ message_id,
+ account_id,
+ mailbox_id,
+ uid,
+ subject,
+ text,
+ from,
+ to: to.unwrap_or_default(),
+ cc: cc.unwrap_or_default(),
+ bcc: bcc.unwrap_or_default(),
+ date,
+ internal_date: date,
+ size,
+ thread_id,
+ attachments,
+ tags: None,
+ };
+ Ok(envelope)
+}
+
pub fn compute_thread_id(
in_reply_to: Option,
references: Option>,
diff --git a/src/modules/import/mod.rs b/src/modules/import/mod.rs
new file mode 100644
index 0000000..e0ba03f
--- /dev/null
+++ b/src/modules/import/mod.rs
@@ -0,0 +1,162 @@
+use poem_openapi::Object;
+use serde::{Deserialize, Serialize};
+use tantivy::doc;
+
+use crate::{
+ base64_decode_url_safe,
+ modules::{
+ account::migration::{AccountModel, AccountType},
+ cache::imap::mailbox::{Attribute, AttributeEnum, MailBox},
+ envelope::extractor::extract_envelope_from_eml,
+ error::{code::ErrorCode, BichonResult},
+ indexer::{
+ manager::{EML_INDEX_MANAGER, ENVELOPE_INDEX_MANAGER},
+ schema::SchemaTools,
+ },
+ utils::create_hash,
+ },
+ raise_error,
+};
+
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+pub struct BatchEmlRequest {
+ pub account_id: u64,
+ pub mail_folder: String,
+ /// A list of emails in base64-encoded format. Each element represents one .eml file.
+ pub emls: Vec,
+}
+
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+pub struct FailedEmlDetail {
+ /// The 0-based index of the failed EML in the request list
+ pub index: usize,
+ /// The error message that caused the import to fail
+ pub error_message: String,
+}
+
+#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, Object)]
+pub struct BatchEmlResult {
+ /// Total number of emails processed
+ pub total: usize,
+ /// Number of emails successfully imported
+ pub success: usize,
+ /// Number of emails failed to import
+ pub failed: usize,
+ /// A list of details for failed imports
+ pub failed_details: Vec,
+}
+
+pub struct ImportEmls;
+
+impl ImportEmls {
+ pub async fn do_import(request: BatchEmlRequest) -> BichonResult {
+ let account = AccountModel::check_account_exists(request.account_id).await?;
+
+ if !account.enabled {
+ return Err(raise_error!("The account is disabled and cannot be used for this operation.".into(), ErrorCode::InvalidParameter));
+ }
+
+ let mailbox_id = match account.account_type {
+ AccountType::IMAP => {
+ let all_mailboxes = MailBox::list_all(account.id).await?;
+ let mailbox = all_mailboxes.into_iter().find(|m| m.name == request.mail_folder);
+
+ match mailbox {
+ Some(mailbox) => mailbox.id,
+ None => return Err(raise_error!(
+ format!("Mail folder '{}' not found for account ID {}. The target folder must exist before importing.",
+ request.mail_folder,
+ request.account_id).into(),
+ ErrorCode::ResourceNotFound
+ )),
+ }
+ },
+ AccountType::NoSync => {
+ let mailbox = MailBox {
+ id: create_hash(request.account_id, &request.mail_folder),
+ account_id: request.account_id,
+ name: request.mail_folder.clone(),
+ delimiter: Some("/".to_string()),
+ attributes: vec![Attribute {
+ attr: AttributeEnum::Extension,
+ extension: Some("CreatedByBichon".into()),
+ }],
+ exists: 0,
+ unseen: None,
+ uid_next: None,
+ uid_validity: None,
+ };
+ let mailbox_id = mailbox.id;
+ // Upsert the mailbox, creating it if it doesn't exist
+ MailBox::batch_upsert(&[mailbox]).await?;
+ mailbox_id
+ },
+ };
+
+ let fields = SchemaTools::eml_fields();
+ let account_id = account.id;
+ let mut success_count = 0;
+ let mut failed_details: Vec = Vec::new(); // Store failure details
+
+ let total = request.emls.len();
+ for (index, eml_base64) in request.emls.into_iter().enumerate() {
+ // 1. Decode Base64
+ let decoded = match base64_decode_url_safe!(eml_base64.as_bytes()) {
+ Ok(bytes) => bytes,
+ Err(e) => {
+ let error_msg =
+ format!("Failed to decode base64 EML at index {}: {:?}", index, e);
+ tracing::error!("{}", error_msg);
+ failed_details.push(FailedEmlDetail {
+ index,
+ error_message: error_msg,
+ });
+ continue;
+ }
+ };
+
+ let envelope = match extract_envelope_from_eml(&decoded, account_id, mailbox_id) {
+ Ok(env) => env,
+ Err(e) => {
+ let error_msg = format!(
+ "Failed to extract envelope from EML at index {}: {:?}",
+ index, e
+ );
+ tracing::error!("{}", error_msg);
+ failed_details.push(FailedEmlDetail {
+ index,
+ error_message: error_msg,
+ });
+ continue;
+ }
+ };
+
+ ENVELOPE_INDEX_MANAGER
+ .add_document(envelope.id, envelope.to_document(mailbox_id).unwrap())
+ .await;
+
+ EML_INDEX_MANAGER
+ .add_document(
+ envelope.id,
+ doc!(
+ fields.f_id => envelope.id,
+ fields.f_account_id => account_id,
+ fields.f_mailbox_id => mailbox_id,
+ fields.f_eml => decoded
+ ),
+ )
+ .await;
+
+ success_count += 1;
+ }
+
+ let failed_count = failed_details.len();
+
+ Ok(BatchEmlResult {
+ total,
+ success: success_count,
+ failed: failed_count,
+ failed_details, // Return the list of failure details
+ })
+ }
+}
diff --git a/src/modules/mod.rs b/src/modules/mod.rs
index f3fbf0c..1264760 100644
--- a/src/modules/mod.rs
+++ b/src/modules/mod.rs
@@ -16,7 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
pub mod account;
pub mod autoconfig;
pub mod cache;
@@ -27,6 +26,7 @@ pub mod database;
pub mod envelope;
pub mod error;
pub mod imap;
+pub mod import;
pub mod indexer;
pub mod logger;
pub mod mailbox;
diff --git a/src/modules/rest/api/import.rs b/src/modules/rest/api/import.rs
new file mode 100644
index 0000000..ede9650
--- /dev/null
+++ b/src/modules/rest/api/import.rs
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
+//
+// This file is part of the Bichon Email Archiving Project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::modules::common::auth::ClientContext;
+use crate::modules::import::BatchEmlResult;
+use crate::modules::import::{BatchEmlRequest, ImportEmls};
+use crate::modules::rest::api::ApiTags;
+use crate::modules::rest::ApiResult;
+use poem_openapi::payload::Json;
+use poem_openapi::OpenApi;
+
+pub struct ImportApi;
+
+#[OpenApi(prefix_path = "/api/v1", tag = "ApiTags::Import")]
+impl ImportApi {
+ /// Batch import one or more EML files into a specified account and mail folder.
+ ///
+ /// This endpoint accepts a JSON payload containing:
+ /// - `account_id`: the target account to import emails into
+ /// - `mail_folder`: the mailbox/folder name
+ /// - `emls`: a list of base64-encoded .eml files
+ ///
+ /// Returns a summary of the import result, including total processed, successful, and failed emails.
+ #[oai(path = "/import", method = "post", operation_id = "do_batch_import")]
+ async fn do_batch_import(
+ &self,
+ /// JSON payload with account info and EML files to import
+ payload: Json,
+ context: ClientContext,
+ ) -> ApiResult> {
+ context.require_root()?;
+ Ok(Json(ImportEmls::do_import(payload.0).await?))
+ }
+}
diff --git a/src/modules/rest/api/mod.rs b/src/modules/rest/api/mod.rs
index e609425..5248db4 100644
--- a/src/modules/rest/api/mod.rs
+++ b/src/modules/rest/api/mod.rs
@@ -16,7 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
use access_token::AccessTokenApi;
use account::AccountApi;
use auto_config::AutoConfigApi;
@@ -26,11 +25,12 @@ use oauth2::OAuth2Api;
use poem_openapi::{OpenApiService, Tags};
use system::SystemApi;
-use crate::bichon_version;
+use crate::{bichon_version, modules::rest::api::import::ImportApi};
pub mod access_token;
pub mod account;
pub mod auto_config;
+pub mod import;
pub mod mailbox;
pub mod message;
pub mod oauth2;
@@ -45,6 +45,7 @@ pub enum ApiTags {
OAuth2,
Message,
System,
+ Import,
}
type RustMailOpenApi = (
@@ -55,6 +56,7 @@ type RustMailOpenApi = (
MailBoxApi,
OAuth2Api,
MessageApi,
+ ImportApi,
);
pub fn create_openapi_service() -> OpenApiService {
@@ -67,6 +69,7 @@ pub fn create_openapi_service() -> OpenApiService {
MailBoxApi,
OAuth2Api,
MessageApi,
+ ImportApi,
),
"BichonApi",
bichon_version!(),
diff --git a/web/src/features/accounts/components/nosync-dialog.tsx b/web/src/features/accounts/components/nosync-dialog.tsx
index 751165e..c2c2231 100644
--- a/web/src/features/accounts/components/nosync-dialog.tsx
+++ b/web/src/features/accounts/components/nosync-dialog.tsx
@@ -37,10 +37,10 @@ import { AccountModel } from '../data/schema';
import { useTranslation } from 'react-i18next';
-const accountSchema = () =>
+const accountSchema = (t: (key: string) => string) =>
z.object({
name: z.string().optional(),
- email: z.string({ required_error: 'Email is required' }).email({ message: 'Invalid email address' }),
+ email: z.string({ required_error: t('validation.emailRequired') }).email({ message: t('validation.invalidEmail') }),
enabled: z.boolean()
});
@@ -85,7 +85,7 @@ export function NoSyncAccountDialog({ currentRow, open, onOpenChange }: Props) {
const form = useForm({
mode: "all",
defaultValues: isEdit ? mapCurrentRowToFormValues(currentRow) : defaultValues,
- resolver: zodResolver(accountSchema()),
+ resolver: zodResolver(accountSchema(t)),
});
const queryClient = useQueryClient();
@@ -118,7 +118,7 @@ export function NoSyncAccountDialog({ currentRow, open, onOpenChange }: Props) {
const errorMessage =
(error.response?.data as { message?: string })?.message ||
error.message ||
- `${isEdit ? 'Update' : 'Creation'} failed, please try again later`;
+ (isEdit ? t('accounts.updateFailed') : t('accounts.creationFailed'));
toast({
variant: "destructive",
@@ -134,7 +134,8 @@ export function NoSyncAccountDialog({ currentRow, open, onOpenChange }: Props) {
const commonData = {
email: data.email,
name: data.name,
- enabled: data.enabled
+ enabled: data.enabled,
+ use_dangerous: false
};
if (isEdit) {
updateMutation.mutate(commonData);
diff --git a/web/src/features/accounts/components/oauth2-action.tsx b/web/src/features/accounts/components/oauth2-action.tsx
index c353a5b..f31194d 100644
--- a/web/src/features/accounts/components/oauth2-action.tsx
+++ b/web/src/features/accounts/components/oauth2-action.tsx
@@ -33,7 +33,7 @@ export function OAuth2Action({ row }: DataTableRowActionsProps) {
const account_type = mailer.account_type;
if (account_type === "NoSync") {
- return n/a
+ return
}
const isOAuth2 = mailer.imap?.auth.auth_type === "OAuth2"
diff --git a/web/src/locales/ar.json b/web/src/locales/ar.json
index 0b7961b..058e537 100644
--- a/web/src/locales/ar.json
+++ b/web/src/locales/ar.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "تحديث حساب البريد الإلكتروني هنا. ",
"addNewEmailAccountHere": "إضافة حساب بريد إلكتروني جديد هنا. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "يستخدم هذا الحساب لأغراض التعريف فقط ولا يتطلب المزامنة مع خادم بريد إلكتروني. إنه يساعد في استيراد بيانات البريد الإلكتروني.",
- "determinesWhetherThisAccountIsActiveNoSync": "يحدد ما إذا كان هذا الحساب نشطًا. إذا تم تعطيله، فلن يتمكن الحساب من استيراد البيانات أو إجراء استعلامات.",
+ "determinesWhetherThisAccountIsActiveNoSync": "يحدد ما إذا كان هذا الحساب نشطًا. إذا تم تعطيله، فلن يكون قادرًا على استيراد البيانات.",
"folderSync": {
"noData": "لا توجد بيانات",
"noFolders": "لا توجد مجلدات للمزامنة",
diff --git a/web/src/locales/da.json b/web/src/locales/da.json
index b30b0c1..b3a3caf 100644
--- a/web/src/locales/da.json
+++ b/web/src/locales/da.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Opdater e-mailkontoen her. ",
"addNewEmailAccountHere": "Tilføj ny e-mailkonto her. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Denne konto bruges kun til identifikationsformål og kræver ikke synkronisering med en e-mailserver. Den hjælper med import af e-mail-data.",
- "determinesWhetherThisAccountIsActiveNoSync": "Bestemmer, om denne konto er aktiv. Hvis deaktiveret, vil kontoen ikke kunne importere data eller udføre søgninger.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Bestemmer, om denne konto er aktiv. Hvis den er deaktiveret, kan data ikke importeres.",
"folderSync": {
"noData": "Ingen data",
"noFolders": "Ingen mapper at synkronisere",
diff --git a/web/src/locales/de.json b/web/src/locales/de.json
index 7c0cd7b..85b89c4 100644
--- a/web/src/locales/de.json
+++ b/web/src/locales/de.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Aktualisieren Sie das E-Mail-Konto hier. ",
"addNewEmailAccountHere": "Fügen Sie hier ein neues E-Mail-Konto hinzu. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Dieses Konto dient nur zur Identifizierung und erfordert keine Synchronisierung mit dem Mailserver. Es hilft beim Import von E-Mail-Daten.",
- "determinesWhetherThisAccountIsActiveNoSync": "Bestimmt, ob dieses Konto aktiv ist. Wenn es deaktiviert ist, kann das Konto keine Daten importieren oder Abfragen ausführen.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Legt fest, ob dieses Konto aktiv ist. Wenn es deaktiviert ist, können keine Daten importiert werden.",
"folderSync": {
"noData": "Keine Daten",
"noFolders": "Keine Ordner zum Synchronisieren",
diff --git a/web/src/locales/en.json b/web/src/locales/en.json
index 5f26891..7fb81f7 100644
--- a/web/src/locales/en.json
+++ b/web/src/locales/en.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Update the email account here. ",
"addNewEmailAccountHere": "Add new email account here. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "This account is used for identification purposes only and does not require syncing with an email server. It helps with importing email data.",
- "determinesWhetherThisAccountIsActiveNoSync": "Determines whether this account is active. If disabled, the account will not be able to import data or perform queries.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Determines whether this account is active. If disabled, the account will not be able to import data.",
"folderSync": {
"noData": "No Data",
"noFolders": "No folders to sync",
diff --git a/web/src/locales/es.json b/web/src/locales/es.json
index 7dd0bba..40b4e67 100644
--- a/web/src/locales/es.json
+++ b/web/src/locales/es.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Actualiza la cuenta de correo electrónico aquí. ",
"addNewEmailAccountHere": "Añade una nueva cuenta de correo electrónico aquí. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Esta cuenta se utiliza solo para fines de identificación y no requiere sincronización con el servidor de correo. Ayuda a importar datos de correo electrónico.",
- "determinesWhetherThisAccountIsActiveNoSync": "Determina si esta cuenta está activa. Si está deshabilitada, la cuenta no podrá importar datos ni ejecutar consultas.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Determina si esta cuenta está activa. Si está desactivada, no podrá importar datos.",
"folderSync": {
"noData": "Sin datos",
"noFolders": "No hay carpetas para sincronizar",
diff --git a/web/src/locales/fi.json b/web/src/locales/fi.json
index d39d86d..fce722a 100644
--- a/web/src/locales/fi.json
+++ b/web/src/locales/fi.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Päivitä sähköpostitili täällä. ",
"addNewEmailAccountHere": "Lisää uusi sähköpostitili täällä. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Tätä tiliä käytetään vain tunnistamistarkoituksiin, eikä se vaadi synkronointia sähköpostipalvelimen kanssa. Auttaa sähköpostidatan tuomisessa.",
- "determinesWhetherThisAccountIsActiveNoSync": "Määrittää, onko tämä tili aktiivinen. Jos poistettu käytöstä, tili ei voi tuoda tietoja tai suorittaa kyselyjä.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Määrittää, onko tämä tili aktiivinen. Jos se on poistettu käytöstä, tietoja ei voi tuoda.",
"folderSync": {
"noData": "Ei tietoja",
"noFolders": "Ei synkronoitavia kansioita",
diff --git a/web/src/locales/fr.json b/web/src/locales/fr.json
index d91d62d..d8a3928 100644
--- a/web/src/locales/fr.json
+++ b/web/src/locales/fr.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Mettez à jour le compte e-mail ici. ",
"addNewEmailAccountHere": "Ajoutez un nouveau compte e-mail ici. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Ce compte est utilisé uniquement à des fins d'identification et ne nécessite pas de synchronisation avec un serveur de messagerie. Il est utile pour l'importation de données d'e-mails.",
- "determinesWhetherThisAccountIsActiveNoSync": "Détermine si ce compte est actif. S'il est désactivé, l'importation de données ou l'exécution de requêtes ne sera pas possible pour ce compte.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Détermine si ce compte est actif. S’il est désactivé, il ne pourra pas importer de données.",
"folderSync": {
"noData": "Aucune Donnée",
"noFolders": "Aucun dossier à synchroniser",
diff --git a/web/src/locales/it.json b/web/src/locales/it.json
index 18183db..3099f35 100644
--- a/web/src/locales/it.json
+++ b/web/src/locales/it.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Aggiorna l'account email qui. ",
"addNewEmailAccountHere": "Aggiungi un nuovo account email qui. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Questo account viene utilizzato solo a scopo di identificazione e non richiede la sincronizzazione con un server email. Aiuta nell'importazione dei dati email.",
- "determinesWhetherThisAccountIsActiveNoSync": "Determina se questo account è attivo. Se disabilitato, l'account non potrà importare dati o eseguire query.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Determina se questo account è attivo. Se disattivato, non sarà possibile importare dati.",
"folderSync": {
"noData": "Nessun Dato",
"noFolders": "Nessuna cartella da sincronizzare",
diff --git a/web/src/locales/jp.json b/web/src/locales/jp.json
index 3a022a3..381c39e 100644
--- a/web/src/locales/jp.json
+++ b/web/src/locales/jp.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "こちらでメールアカウントを更新してください。",
"addNewEmailAccountHere": "こちらで新しいメールアカウントを追加してください。",
"thisAccountIsUsedForIdentificationPurposesOnly": "このアカウントは識別目的でのみ使用され、メールサーバーとの同期は必要ありません。メールデータのインポートに役立ちます。",
- "determinesWhetherThisAccountIsActiveNoSync": "このアカウントが有効かどうかを決定します。無効の場合、データのインポートやクエリの実行はできません。",
+ "determinesWhetherThisAccountIsActiveNoSync": "このアカウントが有効かどうかを判定します。無効の場合、データをインポートできません。",
"folderSync": {
"noData": "データなし",
"noFolders": "同期するフォルダーがありません",
diff --git a/web/src/locales/ko.json b/web/src/locales/ko.json
index 5a4697f..2682922 100644
--- a/web/src/locales/ko.json
+++ b/web/src/locales/ko.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "여기에서 이메일 계정을 업데이트하십시오.",
"addNewEmailAccountHere": "여기에서 새 이메일 계정을 추가하십시오.",
"thisAccountIsUsedForIdentificationPurposesOnly": "이 계정은 식별 목적으로만 사용되며 이메일 서버와의 동기화가 필요하지 않습니다. 이메일 데이터 가져오기에 도움이 됩니다.",
- "determinesWhetherThisAccountIsActiveNoSync": "이 계정이 활성화되었는지 여부를 결정합니다. 비활성화된 경우 데이터 가져오기 또는 쿼리 실행이 불가능합니다.",
+ "determinesWhetherThisAccountIsActiveNoSync": "이 계정이 활성화되어 있는지 결정합니다. 비활성화되면 데이터를 가져올 수 없습니다.",
"folderSync": {
"noData": "데이터 없음",
"noFolders": "동기화할 폴더가 없습니다",
diff --git a/web/src/locales/nl.json b/web/src/locales/nl.json
index e94e8af..cb81967 100644
--- a/web/src/locales/nl.json
+++ b/web/src/locales/nl.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Werk het e-mailaccount hier bij. ",
"addNewEmailAccountHere": "Voeg hier een nieuw e-mailaccount toe. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Dit account wordt alleen gebruikt voor identificatiedoeleinden en vereist geen synchronisatie met een e-mailserver. Het helpt bij het importeren van e-mailgegevens.",
- "determinesWhetherThisAccountIsActiveNoSync": "Bepaalt of dit account actief is. Indien uitgeschakeld, kan het account geen gegevens importeren of zoekopdrachten uitvoeren.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Bepaalt of dit account actief is. Als het is uitgeschakeld, kan er geen data worden geïmporteerd.",
"folderSync": {
"noData": "Geen Gegevens",
"noFolders": "Geen mappen om te synchroniseren",
diff --git a/web/src/locales/no.json b/web/src/locales/no.json
index 4613f13..3ff4f02 100644
--- a/web/src/locales/no.json
+++ b/web/src/locales/no.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Oppdater e-postkontoen her. ",
"addNewEmailAccountHere": "Legg til ny e-postkonto her. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Denne kontoen brukes kun for identifikasjonsformål og krever ikke synkronisering med en e-postserver. Den hjelper med import av e-postdata.",
- "determinesWhetherThisAccountIsActiveNoSync": "Bestemmer om denne kontoen er aktiv. Hvis deaktivert, vil ikke kontoen kunne importere data eller utføre spørringer.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Bestemmer om denne kontoen er aktiv. Hvis den er deaktivert, kan data ikke importeres.",
"folderSync": {
"noData": "Ingen data",
"noFolders": "Ingen mapper å synkronisere",
diff --git a/web/src/locales/pt.json b/web/src/locales/pt.json
index 232e9f0..bec77b5 100644
--- a/web/src/locales/pt.json
+++ b/web/src/locales/pt.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Atualize a conta de email aqui.",
"addNewEmailAccountHere": "Adicione uma nova conta de email aqui.",
"thisAccountIsUsedForIdentificationPurposesOnly": "Esta conta é usada apenas para fins de identificação e não requer sincronização com um servidor de email. Ajuda na importação de dados de email.",
- "determinesWhetherThisAccountIsActiveNoSync": "Determina se esta conta está ativa. Se desativada, nenhuma importação de dados ou execução de consulta será possível.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Determina se esta conta está ativa. Se estiver desativada, não será possível importar dados.",
"folderSync": {
"noData": "Sem Dados",
"noFolders": "Nenhuma pasta para sincronizar",
diff --git a/web/src/locales/ru.json b/web/src/locales/ru.json
index b81f4d2..3f44b5a 100644
--- a/web/src/locales/ru.json
+++ b/web/src/locales/ru.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Обновите почтовый аккаунт здесь. ",
"addNewEmailAccountHere": "Добавьте новый почтовый аккаунт здесь. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Этот аккаунт используется только для идентификации и не требует синхронизации с почтовым сервером. Он помогает при импорте почтовых данных.",
- "determinesWhetherThisAccountIsActiveNoSync": "Определяет, активен ли этот аккаунт. Если отключено, аккаунт не сможет импортировать данные или выполнять запросы.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Определяет, активна ли учетная запись. Если она отключена, импорт данных будет невозможен.",
"folderSync": {
"noData": "Нет данных",
"noFolders": "Нет папок для синхронизации",
diff --git a/web/src/locales/sv.json b/web/src/locales/sv.json
index 3667cce..25b1e7c 100644
--- a/web/src/locales/sv.json
+++ b/web/src/locales/sv.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "Uppdatera e-postkontot här. ",
"addNewEmailAccountHere": "Lägg till nytt e-postkonto här. ",
"thisAccountIsUsedForIdentificationPurposesOnly": "Detta konto används endast för identifieringssyften och kräver inte synkronisering med en e-postserver. Det hjälper till med import av e-postdata.",
- "determinesWhetherThisAccountIsActiveNoSync": "Avgör om detta konto är aktivt. Om inaktiverat kommer kontot inte kunna importera data eller utföra sökningar.",
+ "determinesWhetherThisAccountIsActiveNoSync": "Avgör om kontot är aktivt. Om det är inaktiverat kan ingen data importeras.",
"folderSync": {
"noData": "Inga data",
"noFolders": "Inga mappar att synkronisera",
diff --git a/web/src/locales/zh-tw.json b/web/src/locales/zh-tw.json
index c10edcf..743b17d 100644
--- a/web/src/locales/zh-tw.json
+++ b/web/src/locales/zh-tw.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "在此更新電子郵件帳號。",
"addNewEmailAccountHere": "在此新增電子郵件帳號。",
"thisAccountIsUsedForIdentificationPurposesOnly": "此帳號僅用於識別目的,不需要與郵件伺服器同步。有助於匯入郵件資料。",
- "determinesWhetherThisAccountIsActiveNoSync": "決定此帳號是否為啟用狀態。如果停用,則無法匯入資料或執行查詢。",
+ "determinesWhetherThisAccountIsActiveNoSync": "用來判斷帳戶是否啟用。若停用,將無法匯入資料。",
"folderSync": {
"noData": "無資料",
"noFolders": "沒有可同步的資料夾",
diff --git a/web/src/locales/zh.json b/web/src/locales/zh.json
index 528bc8b..12d136a 100644
--- a/web/src/locales/zh.json
+++ b/web/src/locales/zh.json
@@ -251,7 +251,7 @@
"updateTheEmailAccountHere": "在此更新邮件账户。",
"addNewEmailAccountHere": "在此添加新邮件账户。",
"thisAccountIsUsedForIdentificationPurposesOnly": "此账户仅用于识别目的,不需要与邮件服务器同步。它有助于导入邮件数据。",
- "determinesWhetherThisAccountIsActiveNoSync": "确定此账户是否处于活动状态。如果禁用,账户将无法导入数据或执行查询。",
+ "determinesWhetherThisAccountIsActiveNoSync": "用于判断账户是否处于启用状态。如果被禁用,将无法导入数据。",
"folderSync": {
"noData": "无数据",
"noFolders": "没有需要同步的文件夹",