diff --git a/src/main.rs b/src/main.rs index 9b32738..252594c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,36 @@ -use std::io::{self}; use std::collections::BTreeMap; use std::env; +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::Path; + +#[derive(Debug)] +struct AliasFile { + content: io::Lines>, + default_domain: String, +} + fn main() { let args: Vec = env::args().collect(); - if args.len() < 2 { + if args.len() < 2 || args.len() % 2 == 0{ print_help(); return; } + let mut alias_files : Vec = Vec::new(); + for i in (1..args.len()).step_by(2) { + if let Ok(lines) = read_lines(&args[i]) { + alias_files.push(AliasFile{content: lines, default_domain: args[i+1].to_string()}) + } + } - let default_domain = &args[1]; - - let redirects = parse_alias_to_map(default_domain); + let redirects = parse_alias_to_map(alias_files); let sieve_script = generate_sieve_script(redirects); println!("{}", sieve_script); } fn generate_sieve_script(redirects: BTreeMap>) -> String { -// let mut script : String = "require [\"envelope\", \"copy\"];\n\n".to_string(); - let mut script : String = "".to_string(); + let mut script : String = "require [\"envelope\", \"copy\"];\n\n".to_string(); for (redirect, mut destinations) in redirects { script += format!("if envelope :is \"to\" \"{}\" {{\n{}}}\n", redirect, { @@ -34,24 +46,26 @@ fn generate_sieve_script(redirects: BTreeMap>) -> String { script } -fn parse_alias_to_map(default_domain : &str) -> BTreeMap> { +fn parse_alias_to_map(alias_files: Vec) -> BTreeMap> { // File must exist in the current path let mut redirect_map : BTreeMap> = BTreeMap::new(); let mut destinations : Vec = Vec::new(); - 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 destination = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).0; - if destination.is_empty() { - continue; + for alias_file in alias_files.into_iter() { + for line in alias_file.content { + let line = line.unwrap(); + 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; + if destination.is_empty() { + continue; + } + let redirects: Vec = line.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() { + continue; + } + destinations.push(to_mailaddress(destination, &alias_file.default_domain)); + redirect_map.insert(to_mailaddress(destination, &alias_file.default_domain), redirects); } - let redirects: Vec = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).1.split(" ") - .filter(|address| address.trim().to_string().replace(",","") != "").map(|addr| to_mailaddress(addr, default_domain)).collect(); - if redirects.is_empty() { - continue; - } - destinations.push(to_mailaddress(destination, default_domain)); - redirect_map.insert(to_mailaddress(destination, default_domain), redirects); } let mut changed = true; while changed { @@ -74,7 +88,7 @@ fn parse_alias_to_map(default_domain : &str) -> BTreeMap> { redirect_map } -fn to_mailaddress(local_part: &str, default_domain : &str) -> String { +fn to_mailaddress(local_part: &str, default_domain : &String) -> String { let mut addr = local_part.trim().to_string(); addr = addr.replace(",", ""); if addr.contains("@") { @@ -83,7 +97,17 @@ fn to_mailaddress(local_part: &str, default_domain : &str) -> String { addr + "@" + default_domain } -fn print_help(){ - print!("Reads a virtual alias file from STDIN and needs a default domain to append to local paths, e.g. - cat virt_aliases | ./alias_to_sieve example.com"); + +// 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

(filename: P) -> io::Result>> +where P: AsRef, { + let file = File::open(filename)?; + Ok(io::BufReader::new(file).lines()) +} + + +fn print_help(){ + print!("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 "); }