From 7ea34604691491e2d9f69392266f2f4417e30042 Mon Sep 17 00:00:00 2001 From: mdecimus Date: Mon, 25 Dec 2023 19:35:15 +0100 Subject: [PATCH] Updated configuration files + CHANGELOG --- CHANGELOG.md | 25 ++++++++++++++++ crates/install/src/main.rs | 43 +++++++++++++++++++-------- crates/store/src/dispatch/lookup.rs | 1 + resources/config.zip | Bin 171227 -> 171222 bytes resources/config/directory/imap.toml | 9 +++--- resources/config/directory/ldap.toml | 1 + resources/config/directory/lmtp.toml | 9 +++--- 7 files changed, 68 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91e31deb..8ffe88ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.5.0] - 2023-12-27 + +## Added +- Performance enhancements: + - Messages are parsed only once and their offsets stored in the database, which avoids having to parse them on every `FETCH` request. + - Background full-text indexing. + - Optimization of database access functions. +- Storage layer improvements: + - In addition to `FoundationDB` and `SQLite`, now it is also possible to use `RocksDB`, `PostgreSQL` and `mySQL` as a storage backend. + - Blobs can now be stored in any of the supported data stores, it is no longer limited to the file system or S3/MinIO. + - Full-text searching con now be done internally or delegated to `ElasticSearch`. + - Spam databases can now be stored in any of the supported data stores or `Redis`. It is no longer necessary to have an SQL server to use the spam filter. +- Internal directory: + - User account, groups and mailing lists can now be managed directly from Stalwart without the need of an external LDAP or SQL directory. + - HTTP API to manage users, groups, domains and mailing lists. +- IMAP4rev1 `Recent` flag support, which improves compatibility with old IMAP clients. +- LDAP bind authentication, to support some LDAP servers such as `lldap` which do not expose the userPassword attribute. +- Messages marked a spam by the spam filter can now be automatically moved to the account's `Junk Mail` folder. + +### Changed + +### Fixed +- Spamhaus DNSBL return codes. +- CLI tool reports authentication errors rather than a parsing error. + ## [0.4.2] - 2023-11-01 ## Added diff --git a/crates/install/src/main.rs b/crates/install/src/main.rs index 445af062..ba81ffd5 100644 --- a/crates/install/src/main.rs +++ b/crates/install/src/main.rs @@ -33,6 +33,7 @@ use base64::{engine::general_purpose, Engine}; use clap::{Parser, ValueEnum}; use dialoguer::{console::Term, theme::ColorfulTheme, Input, Select}; use openssl::rsa::Rsa; +use pwhash::sha512_crypt; use rand::{distributions::Alphanumeric, thread_rng, Rng}; const CONFIG_URL: &str = "https://get.stalw.art/resources/config.zip"; @@ -189,6 +190,7 @@ fn main() -> std::io::Result<()> { let mut download_url = None; // Obtain database engine + let mut is_internal = false; if component != Component::Smtp { let backend = select::( "Which database would you like to use?", @@ -240,18 +242,6 @@ fn main() -> std::io::Result<()> { Blob::Internal, )?; - let directory = select::( - "Do you already have a directory or database containing your user accounts?", - &[ - &format!("No, I want Stalwart to manage my user accounts in {store}"), - "Yes, it's an LDAP server", - "Yes, it's an PostgreSQL database", - "Yes, it's an MySQL database", - "Yes, it's an SQLite database", - ], - Directory::Internal, - )?; - let fts = select::( "Where would you like to store the full-text index?", &[&store, "ElasticSearch"], @@ -264,6 +254,19 @@ fn main() -> std::io::Result<()> { SpamDb::Internal, )?; + let directory = select::( + "Do you already have a directory or database containing your user accounts?", + &[ + &format!("No, I want Stalwart to store my user accounts in {store}"), + "Yes, it's an LDAP server", + "Yes, it's an PostgreSQL database", + "Yes, it's an MySQL database", + "Yes, it's an SQLite database", + ], + Directory::Internal, + )?; + is_internal = matches!(directory, Directory::Internal); + // Update settings sed( cfg_path.join("config.toml"), @@ -631,6 +634,22 @@ fn main() -> std::io::Result<()> { } } + if is_internal { + let secret = thread_rng() + .sample_iter(Alphanumeric) + .take(12) + .map(char::from) + .collect::(); + let hashed_secret = sha512_crypt::hash(&secret).unwrap(); + eprintln!( + "\nšŸ”‘ To create the administrator account 'admin' with password '{secret}', execute:\nšŸ”‘ ", + ); + eprintln!( + "šŸ”‘ $ SET_ADMIN_USER=\"admin\" SET_ADMIN_PASS=\"{hashed_secret}\" {}/bin/stalwart-mail --config={}/etc/config.toml", + base_path.display(), base_path.display() + ) + } + eprintln!("\nšŸŽ‰ Installation completed!\n\nāœ… {dkim_instructions}\n"); Ok(()) diff --git a/crates/store/src/dispatch/lookup.rs b/crates/store/src/dispatch/lookup.rs index a1893778..355bdbe9 100644 --- a/crates/store/src/dispatch/lookup.rs +++ b/crates/store/src/dispatch/lookup.rs @@ -34,6 +34,7 @@ use crate::{ impl LookupStore { #[allow(unreachable_patterns)] + #[allow(unused_variables)] pub async fn query( &self, query: &str, diff --git a/resources/config.zip b/resources/config.zip index b6b723a8001fed1a389b66ec88e55fb0e20d2c90..8ea3b059e033fc31ccceed73e45d4c3faa2d2d0e 100644 GIT binary patch delta 2398 zcmZWpc|6oxAD-W_Z)04hn8w;(l(b1VyOhbEM6zC#wF!|hcGC=onc<8vy(J{N!X@fb z-4;?qXtjjAnrOMv8>vh6o@wsq{oH%sKhEcOp67eM-|sokd46Z;isF+iiuDW`{LU1f zXN0yvV*tS6cFS_=6f`;YGAguXcJ$yCXv8Hb;V|i042P4}z~OMU+(_pkW5S)$d3W1& z-s*>JwD?W>9;w+)TMq@*c@?g^e`)q*f64DNR+Xd46HSiW<@tm+%s6+67 z(c;O;sOXDRXO|pyO$dU8#)*b2i)7a4h13PaX}0#n3%D1^4(5R=UbMhXxmzf*$D{hL z40p7@sx|?S9+}dpU*D^TYMH*BFf)A-NLO0rkhOzP+CJ7L1dgJN*`(*D!pe+2GS^y& z&68Cnk3Q2QQ>|6C2TL^e_w{dl+}kZJKX$OrPFPmIpF$LN3$8CKuohJ<%}!j>rOCZ@ zby9S_!n@x0N~opFy)N3kTaV@4w)MSRr+y5OGi>MyKSudPtK1NFTXFwPb?4>* zYm?aNh-r5GuSTZ#`VA5y6r=G+{jy?@tbR1o50+3wefhlXvmcqG?W~5oDeR}AGWS(( zWf@+~GA{afH%7QPyvAhrza3uQ5-uB4Rw{UHRB^|YAit0G)FFMyD5~;c7@$9e}j;WlV-C?-up@j=YO5?lRNa9>X=Jb=t(>89V2aCr)%vn@;gL2DQqho5SPTr_|@d59gPP~qyhoK8wP!AJ=}i0`X-w)GB+|eKE6D^$CS`0s!0kYnyv1<{4a&_QR>5OPKP!L zZZWVY-Kr~@^`b2`X^CqGROZ*EZO!A*MpUh-$4`mI7OCwYU$u+bPA1JPII7@}o)YMV zJkj*95n4PXc;xtYZo@Gb>R#p67o967WpV@^rXQZ!*H7%KGSECxmQt#2>~>8yqSkr? z=?>jzb)&QE)a9Eihz|S?&b8vSQ%84abq!6=t_E zx1xAZ*zAAwZd=J5Z;l=8N$zBS4*bmSD&YP^$*~0`s#W%XyfCRzz2)r# z(x>NpkHRFV$Is@{=G4ybY_ZddDoSs>jn&k+dRb@qw!P^Lc)gbuQr4$8PqMu;;ifiEGoktfh|#JpIH(%i1^)ET{6fXBD1G0-L1JlM2(=KwIapo<^@O38#r( zRvZpp4Xz?>GgM6m22#l0u;BzC>;CQL{%Sc)EhjGqoS%+Oaqo!Dzu^jU#th7p@D;#75qvAu2>FqNd^AcX4sGl4qy#X zB@OssS72Bg@RoW;#&N!q$#6UkSW4~C!EyX_w4qHp0&TiD&WP?3SSAJuOK}|jQWE@% z0CpT&WS|Nd6l9=Y=CD2!5FsHGSYr(FoCG7q^C9s(3@EOJ4Vgd-I=#bW;r1-x3`~sw z!d%D#dw`skgh|Z?@{p7bD8PX6KgJ8laV20T8|(w-Ro?+8p-LH2bAToAYmh{{a=>0p z1M1U3G&Tzh=^#w1b_(O9HE2qD|2~D`;hK{u!vuq63_ynTlfW8e{|P2f0!PpZBoTK8 z*n>&KGYnKq0}_}Z66}_fgi4uc!+3%OPzc}$xHuQptW=jUak;<+bZba}A`#$W6%!ah z^*o>hq83SL=RDv9K5B}AHf+lS4j@Ti40K?tK2U`nc__g%A0G zO8(7Q68K^alwkr3^-nbsGkS24h1Ap9A_?0RpuK+C4hsv=IhYVD1c$*B8%c~_h{UwE zlK`3>>Z`;?b(-zPj4q5|qn2+SB;f%u@N<#?ffG=It{k-X{9XxD$3aJ6c!+@x)Z(K3 zF});_PA{M$IZqQ8ooBU=gr4RC7qlO%A`peqV0{sAm1_3~aKazypWbiU&NA1MN$I z8)g9cCBO^We@6TvLMJ}@HCo`$eB|L5P@xnANOi{mI2D6rXO*HVBG_AsV(rjK0D`dh PuuuSOW#tpmFN*swbqLws delta 2410 zcmY*bc|4T+9-jC2+P9RUu}#T(&M2cra>!{+iG8ywCUhe!tJ}`Msa%x*^kZL#8H8T%m0{ z&vRve`6D)>P&P>LYNTnr8gY5>3PDRb)qGdy9;RY!{~V)~nkn|eB}p%ItMWOmH{zk= z127#dG1dPMh0qt)PZD-53+|tuXlnWxeXEZVQ@Yg0$Cqsff)bsvyqq5c zOUvrX9bGBE)I{0zQq`SQ#!yA1VUX9JwP|!)!glbC&qU91sOcIT z6=am;WHz*j^K)v(FOMeaV=CJzvalaC?nhSGlmIsASN(kDlEB7vcniKZe zOi?2&iLi0nQ!~rdkXg~*c5Mbm;2a zJ)g8$VP|T{yl#E@Cha+ax4DY0p+s*-(qkLr@yLzQt!CQprPZm7V^SS!Ct9C8;0!5H z>(O_sF80xn-O;mGYOH0tm>g?u8n&pNc5e7o)jZ>RoqI2l-(bSGu$&$`=yUPFj>^49 z^U7-PEaAtHX&RQO``v*tP>uVn#eV|@De@LIYKgHLqbEA$$Q!1l8W2f@# zE8~J{jY-9%AXV~%ujAjPN@3Pp;tkizm`OKX(~3Pl?yQH`QO*~hyktqAlJ zNESRokUA&F(SbBpOq%?Ik>_J?bg0#PbJUc}C7b37N%P!`cO73S{Fd(D;B7zO)EaE- zzqpWnN`H;fV{WPGKI@$JrO(R`Ci$B9&sl_2dA%z8Pw^8qQ~gTHt~9rw4eZ)|e91Sb z+YZ%TVT5bll+%hEeHV3i=<<>9F1O9RR+^Z^=ZYPY(;SaKb+U@p~X=bX<4TtFD&SQ}|sy7BLV@C#SjaWMdR-SNz^!|o5;cU>NL=llF;;`kSLAK9k2=3i|NuI!p~ z4^nxuIoA&-V@~%B+njlr&Qg`er(`b$o3^Qi~r{t(fRSKX9*R-Z8Ryl zS$AFe1=Aw4sKFOp$gl&R_LJ4lNlH_h4kphnGOv1co}0E)l`Z_J(xdBs&+7a%S(kMw zTwD5kh-o>hV8Az2!cMB`OtF5*a^CfDW;Hjh#Pz#GdA*^e%H?s4fPROy$1l6^Gv8A` zkMvCi>I==>Tzo%gF*ef-n|T&3s(fiU_3fG?k2pkGa(UkY@2_rt8jB7u?(b_qv$PVX zUmZC%AFg)yY=ZOE#j@9B$Zhk<@omb@1xUh^0wgB=*T)j_ zqtRNBEkxQHe~&H=N18&x=Rmm-$CQGc<49>C#tL7we;txA=Krq+=`Y%tuUfcr0;wSt zSs~4{l9h+C6Ud6#3x+Ysji`Xw801Gx!9WaR5s9#ogM5h&DB>U=Vhc=jkSmb^4zXxA zVFp#Ph($K2QFuSAsew)$ZgLv};*d8n2zTOenGGyEiF-8z=OnH^0WVJ?HW346@rX@I z=u>!feGRCOM^@w}0}2>V5K17MfNaR@FNg*~3ur)uc#7XBLT3V2FJcJQbTCOo&g6RL z7sLx?%0XQselBM%WN09tgcs6>JxM5nl;exY$t2`KZYmd{-N|S>>0c{C50cSNQgwn@ z7-l6nq~K zXb0mobbyo=6Y5riAPrZkiX$)uXD`I5W*5rq3AI+y}}11$gnGXT*RLaG5)aYzE{0nv$h=m1=!1Yk(R}1d41i4m+Cl1vAh5*$cHnXWHp~nr3y>F~2HOhpMYsv&h4==Hgd-ph xqh%mfh)>_H2%rA52n3@M7^M~As!@1UgfEN$42sb{;!nsZMw=z%qwo!<{1;szxQ_q; diff --git a/resources/config/directory/imap.toml b/resources/config/directory/imap.toml index c4f9400a..73c7c231 100644 --- a/resources/config/directory/imap.toml +++ b/resources/config/directory/imap.toml @@ -10,10 +10,11 @@ disable = true [directory."imap".pool] max-connections = 10 -min-connections = 0 -max-lifetime = "30m" -idle-timeout = "10m" -connect-timeout = "30s" + +[directory."imap".pool.timeout] +create = "30s" +wait = "30s" +recycle = "30s" [directory."imap".tls] implicit = true diff --git a/resources/config/directory/ldap.toml b/resources/config/directory/ldap.toml index 61aadc74..11ea5894 100644 --- a/resources/config/directory/ldap.toml +++ b/resources/config/directory/ldap.toml @@ -6,6 +6,7 @@ type = "ldap" address = "ldap://localhost:389" base-dn = "dc=example,dc=org" +timeout = "30s" disable = true [directory."ldap".bind] diff --git a/resources/config/directory/lmtp.toml b/resources/config/directory/lmtp.toml index 7b911997..2732be78 100644 --- a/resources/config/directory/lmtp.toml +++ b/resources/config/directory/lmtp.toml @@ -14,10 +14,11 @@ rcpt = 5 [directory."lmtp".pool] max-connections = 10 -min-connections = 0 -max-lifetime = "30m" -idle-timeout = "10m" -connect-timeout = "30s" + +[directory."lmtp".pool.timeout] +create = "30s" +wait = "30s" +recycle = "30s" [directory."lmtp".tls] implicit = false