Generate sieve script from hashmap

This commit is contained in:
Gonne 2024-11-03 08:46:55 +01:00
parent 184d8c543e
commit c6dca99e33
2 changed files with 68 additions and 56 deletions

7
.gitignore vendored
View file

@ -29,3 +29,10 @@ testdata/virt_aliases
# Added by cargo # Added by cargo
/target /target
# Nix
/result
# Direnv
/.direnv

59
main.rs
View file

@ -1,27 +1,42 @@
use std::fs::File; use std::io::{self};
use std::io::{self, BufRead};
use std::path::Path;
use std::env;
use std::collections::HashMap; use std::collections::HashMap;
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); let redirects = parse_alias_to_hashmap();
let sieve_script = generate_sieve_script(redirects);
println!("{}", sieve_script);
}
let file_path = &args[1]; fn generate_sieve_script(redirects: HashMap<String, Vec<String>>) -> String {
let mut script : String = "require [\"envelope\", \"copy\"];\n".to_string();
for (redirect, destinations) in redirects {
script += format!("if envelope :is \"to\" \"{}\" {{\n{}}}\n", redirect,
(|| {
let mut subscript : String = "".to_string();
for destination in destinations.iter().rev().skip(1).rev() {
subscript += format!(" redirect :copy \"{}\";\n", destination).as_str();
}
subscript += format!(" redirect \"{}\";\n", destinations.iter().rev().next().unwrap()).as_str();
return subscript;
})()
).as_str();
}
return script;
}
fn parse_alias_to_hashmap() -> HashMap<String, Vec<String>> {
// File must exist in the current path // File must exist in the current path
if let Ok(lines) = read_lines(file_path) {
// Consumes the iterator, returns an (Optional) String
let mut redirect_map : HashMap<String, Vec<String>> = HashMap::new(); let mut redirect_map : HashMap<String, Vec<String>> = HashMap::new();
let mut destinations : Vec<String> = Vec::new(); let mut destinations : Vec<String> = Vec::new();
for line in lines.flatten() { for line in io::stdin().lines() {
let line = line.unwrap();
let line = String::from(line.split_at(line.find("#").unwrap_or(line.len())).0); let line = String::from(line.split_at(line.find("#").unwrap_or(line.len())).0);
let destination = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).0; let destination = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).0;
if destination == "" { if destination == "" {
continue; continue;
} }
let redirects: Vec<String> = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).1.split(", ") let redirects: Vec<String> = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).1.split(" ")
.map(|address| to_mailaddress(address)).collect(); .filter(|address| address.trim().to_string().replace(",","") != "").map(|address| to_mailaddress(address)).collect();
if redirects.len() == 0 { if redirects.len() == 0 {
continue; continue;
} }
@ -41,29 +56,19 @@ fn main() {
all_new_redirects.entry(destination.clone()).and_modify(|d| d.extend(new_redirects.iter().map(|x| x.clone()))); all_new_redirects.entry(destination.clone()).and_modify(|d| d.extend(new_redirects.iter().map(|x| x.clone())));
} }
} }
} }
for (destination, new_redirect) in all_new_redirects { for (destination, new_redirect) in all_new_redirects {
*redirect_map.get_mut(&destination).unwrap() = new_redirect; *redirect_map.get_mut(&destination).unwrap() = new_redirect;
} }
} }
println!("{:#?}", redirect_map); return redirect_map;
}
} }
fn to_mailaddress(local_part: &str) -> String { fn to_mailaddress(local_part: &str) -> String {
let local_part = local_part.trim(); let mut addr = local_part.trim().to_string();
if local_part.contains("@") { addr = addr.replace(",", "");
return String::from(local_part); if addr.contains("@") {
return addr;
} }
return local_part.to_string() + "@mathebau.de"; return addr + "@mathebau.de";
}
// The output is wrapped in a Result to allow matching on errors.
// 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>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
} }