cargo fmt

This commit is contained in:
Gonne 2024-11-25 20:40:40 +01:00
parent defa39de28
commit 2cc90cd920

View file

@ -1,11 +1,11 @@
use email_address_parser::EmailAddress;
use fqdn::FQDN;
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::fs::File; use std::fs::File;
use std::io::{self, BufRead}; use std::io::{self, BufRead};
use std::path::Path; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use fqdn::FQDN;
use email_address_parser::EmailAddress;
#[derive(Debug)] #[derive(Debug)]
struct AliasFile { struct AliasFile {
@ -24,7 +24,10 @@ fn main() {
let mut alias_files: Vec<AliasFile> = Vec::new(); let mut alias_files: Vec<AliasFile> = Vec::new();
for i in (1..args.len()).step_by(2) { for i in (1..args.len()).step_by(2) {
if let Ok(lines) = read_lines(&args[i]) { if let Ok(lines) = read_lines(&args[i]) {
alias_files.push(AliasFile{content: lines, default_domain: FQDN::from_str(&args[i+1]).unwrap()}); alias_files.push(AliasFile {
content: lines,
default_domain: FQDN::from_str(&args[i + 1]).unwrap(),
});
} }
} }
println!("{}", generate_sieve_script(parse_alias_to_map(alias_files))); println!("{}", generate_sieve_script(parse_alias_to_map(alias_files)));
@ -33,15 +36,19 @@ fn main() {
fn generate_sieve_script(redirects: AliasMap) -> String { fn generate_sieve_script(redirects: AliasMap) -> String {
let mut script: String = "require [\"envelope\", \"copy\"];\n\n".to_string(); let mut script: String = "require [\"envelope\", \"copy\"];\n\n".to_string();
for (redirect, destinations) in redirects { for (redirect, destinations) in redirects {
script += format!("if envelope :is \"to\" \"{}\" {{\n{}}}\n", redirect, script += format!("if envelope :is \"to\" \"{}\" {{\n{}}}\n", redirect, {
{
let mut subscript: String = String::new(); let mut subscript: String = String::new();
for destination in destinations.iter().rev().skip(1).rev() { for destination in destinations.iter().rev().skip(1).rev() {
subscript += format!(" redirect :copy \"{destination}\";\n").as_str(); subscript += format!(" redirect :copy \"{destination}\";\n").as_str();
} }
subscript + format!(" redirect \"{}\";\n", destinations.iter().next_back().unwrap()).as_str() subscript
} + format!(
).as_str(); " redirect \"{}\";\n",
destinations.iter().next_back().unwrap()
)
.as_str()
})
.as_str();
} }
script script
} }
@ -58,13 +65,21 @@ fn parse_alias_to_map(alias_files: Vec<AliasFile>) -> AliasMap {
if destination.is_empty() { if destination.is_empty() {
continue; continue;
} }
let redirects: Vec<EmailAddress> = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).1.split(' ') let redirects: Vec<EmailAddress> = line
.filter(|address| address.trim().to_string().replace(',',"") != "").map(|addr| to_mailaddress(addr, &alias_file.default_domain)).collect(); .split_at(line.find(char::is_whitespace).unwrap_or(0))
.1
.split(' ')
.filter(|address| address.trim().to_string().replace(',', "") != "")
.map(|addr| to_mailaddress(addr, &alias_file.default_domain))
.collect();
if redirects.is_empty() { if redirects.is_empty() {
continue; continue;
} }
destinations.push(to_mailaddress(destination, &alias_file.default_domain)); destinations.push(to_mailaddress(destination, &alias_file.default_domain));
redirect_map.insert(to_mailaddress(destination, &alias_file.default_domain), redirects); redirect_map.insert(
to_mailaddress(destination, &alias_file.default_domain),
redirects,
);
} }
} }
let mut changed = true; let mut changed = true;
@ -75,9 +90,13 @@ fn parse_alias_to_map(alias_files: Vec<AliasFile>) -> AliasMap {
for forward_to in redirect_map.get(destination).unwrap() { for forward_to in redirect_map.get(destination).unwrap() {
if let Some(new_redirects) = redirect_map.get(forward_to) { if let Some(new_redirects) = redirect_map.get(forward_to) {
changed = true; changed = true;
all_new_redirects.entry(destination.clone()).or_insert(redirect_map.get(destination).unwrap().clone()) all_new_redirects
.entry(destination.clone())
.or_insert(redirect_map.get(destination).unwrap().clone())
.retain(|dest| *dest != *forward_to); .retain(|dest| *dest != *forward_to);
all_new_redirects.entry(destination.clone()).and_modify(|d| d.extend(new_redirects.iter().cloned())); all_new_redirects
.entry(destination.clone())
.and_modify(|d| d.extend(new_redirects.iter().cloned()));
} }
} }
} }
@ -100,12 +119,16 @@ fn to_mailaddress(local_part: &str, default_domain : &FQDN) -> EmailAddress {
// The output is wrapped in a Result to allow matching on errors. // The output is wrapped in a Result to allow matching on errors.
// Returns an Iterator to the Reader of the lines of the file. // Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>> fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, { where
P: AsRef<Path>,
{
let file = File::open(filename)?; let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines()) Ok(io::BufReader::new(file).lines())
} }
fn print_help() { fn print_help() {
print!("Reads a virtual alias file and needs a default domain to append to local paths, e.g. print!(
./alias_to_sieve example.com.txt example.com"); "Reads a virtual alias file and needs a default domain to append to local paths, e.g.
./alias_to_sieve example.com.txt example.com"
);
} }