This commit is contained in:
rustmailer
2026-05-10 01:48:26 +08:00
parent be934e2b3f
commit 9c91025c53
8 changed files with 98 additions and 21 deletions
+9 -3
View File
@@ -25,10 +25,16 @@ use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct ImapConfig {
/// IMAP server hostname or IP address
//#[oai(validator(max_length = 253, pattern = r"^[a-zA-Z0-9\-\.]+$"))]
#[cfg_attr(
feature = "web-api",
oai(validator(max_length = 253, pattern = r"^[a-zA-Z0-9\-\.]+$"))
)]
pub host: String,
/// IMAP server port number
//#[oai(validator(minimum(value = "1"), maximum(value = "65535")))]
#[cfg_attr(
feature = "web-api",
oai(validator(minimum(value = "1"), maximum(value = "65535")))
)]
pub port: u16,
/// Connection encryption method
pub encryption: Encryption,
@@ -71,7 +77,7 @@ pub struct AuthConfig {
///
/// Users should provide a plaintext password (1 to 256 characters).
/// The server will encrypt the password using AES-256-GCM and securely store it.
//#[oai(validator(max_length = 256, min_length = 1))]
#[cfg_attr(feature = "web-api", oai(validator(max_length = 256, min_length = 1)))]
pub password: Option<String>,
}
+4 -4
View File
@@ -82,7 +82,6 @@ pub struct AccountV1 {
pub id: u64,
pub imap: Option<ImapConfig>,
pub enabled: bool,
//#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub name: Option<String>,
pub capabilities: Option<Vec<String>>,
@@ -110,7 +109,6 @@ pub struct AccountV2 {
pub id: u64,
pub imap: Option<ImapConfig>,
pub enabled: bool,
//#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub name: Option<String>,
pub capabilities: Option<Vec<String>>,
@@ -141,7 +139,6 @@ pub struct AccountV3 {
pub id: u64,
pub imap: Option<ImapConfig>,
pub enabled: bool,
//#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
pub email: String,
pub name: Option<String>,
pub capabilities: Option<Vec<String>>,
@@ -176,7 +173,10 @@ pub struct AccountV4 {
pub id: u64,
pub imap: Option<ImapConfig>,
pub enabled: bool,
//#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
#[cfg_attr(
feature = "web-api",
oai(validator(custom = "crate::common::validator::EmailValidator"))
)]
pub email: String,
pub account_name: Option<String>,
pub login_name: Option<String>,
+17 -8
View File
@@ -27,7 +27,10 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccountCreateRequest {
//#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
#[cfg_attr(
feature = "web-api",
oai(validator(custom = "crate::common::validator::EmailValidator"))
)]
pub email: String,
pub login_name: Option<String>,
pub account_name: Option<String>,
@@ -36,11 +39,14 @@ pub struct AccountCreateRequest {
pub date_since: Option<DateSince>,
pub date_before: Option<RelativeDate>,
pub account_type: AccountType,
//#[oai(validator(minimum(value = "100")))]
#[cfg_attr(feature = "web-api", oai(validator(minimum(value = "100"))))]
pub folder_limit: Option<u32>,
//#[oai(validator(minimum(value = "10")))]
#[cfg_attr(feature = "web-api", oai(validator(minimum(value = "10"))))]
pub download_interval_min: Option<i64>,
//#[oai(validator(minimum(value = "10"), maximum(value = "200")))]
#[cfg_attr(
feature = "web-api",
oai(validator(minimum(value = "10"), maximum(value = "200")))
)]
pub download_batch_size: Option<u32>,
pub use_proxy: Option<u64>,
pub use_dangerous: bool,
@@ -136,7 +142,7 @@ pub struct AccountUpdateRequest {
/// Max emails to sync for this folder.
/// If not set, sync all emails.
/// otherwise sync up to `n` most recent emails (min 10).
//#[oai(validator(minimum(value = "100")))]
#[cfg_attr(feature = "web-api", oai(validator(minimum(value = "100"))))]
pub folder_limit: Option<u32>,
pub clear_folder_limit: Option<bool>,
/// Configuration for selective folder (mailbox/label) synchronization
@@ -153,10 +159,13 @@ pub struct AccountUpdateRequest {
/// Defaults to standard folders (`INBOX`, `Sent`) if empty.
/// Modified folders will be automatically synced on the next update.
pub sync_folders: Option<Vec<String>>,
/// Incremental sync interval (seconds)
//#[oai(validator(minimum(value = "10")))]
/// Incremental download interval (seconds)
#[cfg_attr(feature = "web-api", oai(validator(minimum(value = "10"))))]
pub download_interval_min: Option<i64>,
//#[oai(validator(minimum(value = "10"), maximum(value = "200")))]
#[cfg_attr(
feature = "web-api",
oai(validator(minimum(value = "10"), maximum(value = "200")))
)]
pub download_batch_size: Option<u32>,
/// Optional proxy ID for establishing the connection to external APIs (e.g., Gmail, Outlook).
/// - If `None` or not provided, the client will connect directly to the API server.
+2 -2
View File
@@ -38,7 +38,7 @@ pub struct DateSince {
/// "fixed": "2025-05-01"
/// }
/// ```
//#[oai(validator(pattern = r"^\d{4}-\d{2}-\d{2}$"))]
#[cfg_attr(feature = "web-api", oai(validator(pattern = r"^\d{4}-\d{2}-\d{2}$")))]
pub fixed: Option<String>,
/// Relative time period from current date
///
@@ -73,7 +73,7 @@ pub struct RelativeDate {
/// The time unit to use for the offset (days, months, or years)
pub unit: Unit,
/// The quantity of time units to offset (must be a positive integer)
//#[oai(validator(minimum(value = "1")))]
#[cfg_attr(feature = "web-api", oai(validator(minimum(value = "1"))))]
pub value: u32,
}
+2
View File
@@ -25,6 +25,8 @@ pub mod paginated;
pub mod periodic;
pub mod rustls;
pub mod signal;
#[cfg(feature = "web-api")]
pub mod validator;
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Addr {
+45
View File
@@ -0,0 +1,45 @@
//
// Copyright (c) 2025-2026 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 <http://www.gnu.org/licenses/>.
use std::{
fmt::{self, Display, Formatter},
str::FromStr,
};
use email_address::EmailAddress;
use poem_openapi::Validator;
pub struct EmailValidator;
impl Display for EmailValidator {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("Not a valid email address")
}
}
impl Validator<String> for EmailValidator {
fn check(&self, value: &String) -> bool {
match EmailAddress::from_str(value) {
Ok(e) => &e.email() == value,
Err(_) => false,
}
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct AccessTokenCreateRequest {
/// An optional description of the token's purpose or usage.
//#[oai(validator(max_length = "32"))]
#[cfg_attr(feature = "web-api", oai(validator(max_length = "32")))]
pub name: Option<String>,
/// The expiration interval for this token, in hours.
/// None means the token does not expire (this applies only to API tokens).
+18 -3
View File
@@ -34,7 +34,22 @@ use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
fn allowed_themes() -> HashSet<&'static str> {
["light", "dark"].into_iter().collect()
[
"light",
"dark",
"rose-light",
"rose-dark",
"orange-light",
"orange-dark",
"green-light",
"green-dark",
"yellow-light",
"yellow-dark",
"blue-light",
"blue-dark",
]
.into_iter()
.collect()
}
fn allowed_languages() -> HashSet<&'static str> {
@@ -201,7 +216,7 @@ impl RoleUpdateRequest {
pub struct UserCreateRequest {
pub username: String,
//#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
#[cfg_attr(feature = "web-api", oai(validator(custom = "crate::common::validator::EmailValidator")))]
pub email: String,
pub password: String,
@@ -338,7 +353,7 @@ impl UserCreateRequest {
#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
pub struct UserUpdateRequest {
pub username: Option<String>,
//#[oai(validator(custom = "crate::common::validator::EmailValidator"))]
#[cfg_attr(feature = "web-api", oai(validator(custom = "crate::common::validator::EmailValidator")))]
pub email: Option<String>,
pub password: Option<String>,
pub avatar_base64: Option<String>,