(* HCoop Domtool (http://hcoop.sourceforge.net/) * Copyright (c) 2006, Adam Chlipala * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) (* Configuring e-mail aliases *) structure Alias :> ALIAS = struct open Ast val aliases : TextIO.outstream option ref = ref NONE fun aliasesF () = valOf (!aliases) val aliasesD : TextIO.outstream option ref = ref NONE fun aliasesDF () = valOf (!aliasesD) fun write s = TextIO.output (aliasesF (), s) fun writeD s = TextIO.output (aliasesDF (), s) val _ = Domain.registerBefore (fn _ => (aliases := SOME (Domain.domainFile "aliases"); aliasesD := SOME (Domain.domainFile "aliases.default"))) val _ = Domain.registerAfter (fn _ => (TextIO.closeOut (aliasesF ()); TextIO.closeOut (aliasesDF ()))) fun validEmailUser s = size s > 0 andalso size s < 50 andalso CharVector.all (fn ch => Char.isAlphaNum ch orelse ch = #"." orelse ch = #"_" orelse ch = #"-" orelse ch = #"+") s val _ = Env.type_one "emailUser" Env.string validEmailUser fun validEmail s = case String.fields (fn ch => ch = #"@") s of [user] => validEmailUser user | [user, host] => validEmailUser user andalso Domain.validDomain host | _ => false val _ = Env.type_one "email" Env.string validEmail datatype aliasSource = User of string | Default | CatchAll val source = fn (EApp ((EVar "userSource", _), e), _) => Option.map User (Env.string e) | (EVar "defaultSource", _) => SOME Default | (EVar "catchAllSource", _) => SOME CatchAll | _ => NONE datatype aliasTarget = Address of string | Addresses of string list | Drop val target = fn (EApp ((EVar "addressTarget", _), e), _) => Option.map Address (Env.string e) | (EApp ((EVar "addressesTarget", _), e), _) => Option.map Addresses (Env.list Env.string e) | (EVar "dropTarget", _) => SOME Drop | _ => NONE fun localhostify s = let val (prefix, suffix) = Substring.splitl (fn ch => ch <> #"@") (Substring.full s) in if Substring.size suffix = 0 then s ^ "@localhost" else s end fun writeTarget (outf, t) = case t of Address s => TextIO.output (outf, localhostify s) | Addresses [] => TextIO.output (outf, "!") | Addresses ss => TextIO.output (outf, String.concatWith "," (map localhostify ss)) | Drop => TextIO.output (outf, "!") fun writeSource (s, t) = case s of User s => (write s; write "@"; write (Domain.currentDomain ()); write ": "; writeTarget (aliasesF (), t); write "\n") | Default => (write "*@"; write (Domain.currentDomain ()); write ": "; writeTarget (aliasesF (), t); write "\n") | CatchAll => (writeD "*@"; writeD (Domain.currentDomain ()); writeD ": "; writeTarget (aliasesDF (), t); writeD "\n") val _ = Env.action_two "aliasPrim" ("from", source, "to", target) writeSource end