/*
* Copyright (c) 2023 Stalwart Labs Ltd.
*
* This file is part of the Stalwart SMTP Server.
*
* 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.
* in the LICENSE file at the top-level directory of this distribution.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* You can be released from the requirements of the AGPLv3 license by
* purchasing a commercial license. Please contact licensing@stalw.art
* for more details.
*/
use std::time::Duration;
use directory::config::ConfigDirectory;
use smtp_proto::{AUTH_LOGIN, AUTH_PLAIN};
use utils::config::Config;
use crate::{
directory::sql::{create_test_directory, create_test_user_with_email, link_test_address},
smtp::{
session::{TestSession, VerifyResponse},
ParseTestConfig, TestConfig,
},
};
use smtp::{
config::{ConfigContext, IfBlock},
core::{Session, SMTP},
};
const CONFIG: &str = r#"
[directory."sql"]
type = "sql"
address = "sqlite::memory:"
[directory."sql".pool]
max-connections = 1
[directory."sql".query]
name = "SELECT name, type, secret, description, quota FROM accounts WHERE name = ? AND active = true"
members = "SELECT member_of FROM group_members WHERE name = ?"
recipients = "SELECT name FROM emails WHERE address = ?"
emails = "SELECT address FROM emails WHERE name = ? AND type != 'list' ORDER BY type DESC, address ASC"
verify = "SELECT address FROM emails WHERE address LIKE '%' || ? || '%' AND type = 'primary' ORDER BY address LIMIT 5"
expand = "SELECT p.address FROM emails AS p JOIN emails AS l ON p.name = l.name WHERE p.type = 'primary' AND l.address = ? AND l.type = 'list' ORDER BY p.address LIMIT 50"
domains = "SELECT 1 FROM emails WHERE address LIKE '%@' || ? LIMIT 1"
[directory."sql".columns]
name = "name"
description = "description"
secret = "secret"
email = "address"
quota = "quota"
type = "type"
[directory."sql".lookup]
domains = "SELECT name FROM domains WHERE name = ? LIMIT 1"
is_ip_allowed = "SELECT addr FROM allowed_ips WHERE addr = ? LIMIT 1"
"#;
#[tokio::test]
async fn lookup_sql() {
// Enable logging
/*tracing::subscriber::set_global_default(
tracing_subscriber::FmtSubscriber::builder()
.with_max_level(tracing::Level::DEBUG)
.finish(),
)
.unwrap();*/
// Parse settings
let mut core = SMTP::test();
let mut ctx = ConfigContext::new(&[]);
let config = Config::parse(CONFIG).unwrap();
ctx.directory = config.parse_directory().unwrap();
// Obtain directory handle
let handle = ctx.directory.directories.get("sql").unwrap().as_ref();
// Create tables
create_test_directory(handle).await;
// Create test records
create_test_user_with_email(handle, "jane@foobar.org", "s3cr3tp4ss", "Jane").await;
create_test_user_with_email(handle, "john@foobar.org", "mypassword", "John").await;
create_test_user_with_email(handle, "bill@foobar.org", "123456", "Bill").await;
create_test_user_with_email(handle, "mike@foobar.net", "098765", "Mike").await;
link_test_address(handle, "jane@foobar.org", "sales@foobar.org", "list").await;
link_test_address(handle, "john@foobar.org", "sales@foobar.org", "list").await;
link_test_address(handle, "bill@foobar.org", "sales@foobar.org", "list").await;
link_test_address(handle, "mike@foobar.net", "support@foobar.org", "list").await;
for query in [
"CREATE TABLE domains (name TEXT PRIMARY KEY, description TEXT);",
"INSERT INTO domains (name, description) VALUES ('foobar.org', 'Main domain');",
"INSERT INTO domains (name, description) VALUES ('foobar.net', 'Secondary domain');",
"CREATE TABLE allowed_ips (addr TEXT PRIMARY KEY);",
"INSERT INTO allowed_ips (addr) VALUES ('10.0.0.50');",
] {
handle.query(query, &[]).await.unwrap();
}
// Enable AUTH
let mut config = &mut core.session.config.auth;
config.directory = r"'sql'"
.parse_if::