diff --git a/HSH/Helpers/Email.hs b/HSH/Helpers/Email.hs
--- a/HSH/Helpers/Email.hs
+++ b/HSH/Helpers/Email.hs
@@ -1,6 +1,10 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
 module HSH.Helpers.Email where
 import HSH
+import HSH.Helpers.Utils
 import Text.StringTemplate.Helpers
+import System.IO.Error
 
 newtype PureInput = PureInput { unpureinput :: String }
   deriving (Read,Show)
@@ -15,7 +19,19 @@
 
   This assumes a unixy environment, 
 -}
-mailxEmail emailBody subject recipient = runIO $ echo emailBody -|- mailxCommand
+--mailxEmail :: String -> String -> String -> IO (Either String ())
+mailxEmail emailBody subject "" = return . Left $ "no email recipient"
+mailxEmail emailBody subject recipient = do
+  etR <- try $ run $ echo emailBody -|- mailxCommand
+  case etR of
+    Left e -> return $ Left $ show e
+    Right okmsg -> return $ Right okmsg
   where mailxCommand = render1 [("subject",subject),("recipient",recipient)]
                                "mailx -s \"$subject$\" $recipient$"
 
+
+t = do
+  etR <- mailxEmail "meh" "mah" "moo@gmail.com"
+  case etR of
+    Left e -> fail $ "error, e: " ++ e
+    Right () -> return "cool"
diff --git a/HSH/Helpers/FileManip.hs b/HSH/Helpers/FileManip.hs
--- a/HSH/Helpers/FileManip.hs
+++ b/HSH/Helpers/FileManip.hs
@@ -4,6 +4,7 @@
 import System.FilePath (takeDirectory)
 import qualified Data.ByteString.Char8 as B
 import HSH
+import HSH.Helpers.Utils
 import Text.StringTemplate.Helpers
 import HSH.Helpers.UnixUsers
 
@@ -25,10 +26,7 @@
 findDirectories :: FilePath -> IO [FilePath]
 findDirectories d = runStrings $ render1 [("d",d)] "find $d$ -type d"
 
-runS :: String -> IO String
-runS = run
-runStrings :: String -> IO [String]
-runStrings = ( return . lines =<< ) . run 
+
 
 -- I took this out because I don't like the behavior of doesFileExist when it comes to symlinks
 -- If  symlink exists, but it's to a directlry, this test is false
diff --git a/HSH/Helpers/UnixUsers.hs b/HSH/Helpers/UnixUsers.hs
--- a/HSH/Helpers/UnixUsers.hs
+++ b/HSH/Helpers/UnixUsers.hs
@@ -51,6 +51,9 @@
 groupdel :: SysGroup -> IO (Either String ())
 groupdel (SysGroup g) = tryS $ runIO $ render1 [("g",g)] "groupdel $g$"
 
+userdel :: SysUser -> IO (Either String ())
+userdel (SysUser u) = tryS $ runIO $ render1 [("u",u)] "userdel $u$"
+
 -- a wrapper over the useradd command 
 useradd :: SysUser -> (Maybe SysGroup) -> (Maybe SysShell) -> (Maybe SysHomedir) -> IO (Either String ())
 useradd (SysUser uname) mbG mbSh mbHomedir = do
diff --git a/HSH/Helpers/Utils.hs b/HSH/Helpers/Utils.hs
--- a/HSH/Helpers/Utils.hs
+++ b/HSH/Helpers/Utils.hs
@@ -26,9 +26,41 @@
 
 
 tryS :: IO a -> IO (Either String a)
-tryS ma = return . mapeither show id =<< try ma
-  where
-    mapeither :: (a -> a') -> (b -> b') -> Either a b -> Either a' b'
-    mapeither f g (Left x) = Left $ f x
-    mapeither f g (Right x) = Right $ g x
+tryS ma = do
+  etRes <- try ma
+  return $ case etRes of
+    Left e -> Left $ show e
+    Right r -> Right r
 
+{- | Like tryEC in HSH, but doesn't attempt to parse error message, so all errors result in Left result type
+     and nothing gets re-raised via ioError -}
+{-
+tryECPromiscuous :: IO a -> IO (Either ProcessStatus a)
+tryECPromiscuous action =
+    do r <- try action
+       case r of
+         Left ioe ->
+          if isUserError ioe then
+              case (ioeGetErrorString ioe =~~ pat) of
+                Nothing -> ioError ioe -- not ours; re-raise it
+                Just e -> return . Left . proc $ e
+          else ioError ioe      -- not ours; re-raise it
+         Right result -> return (Right result)
+    where pat = ": exited with code [0-9]+$|: terminated by signal ([0-9]+)$|: stopped by signal [0-9]+"
+          proc :: String -> ProcessStatus
+          proc e
+              | e =~ "^: exited" = Exited (ExitFailure (str2ec e))
+              | e =~ "^: terminated by signal" = Terminated (str2ec e)
+              | e =~ "^: stopped by signal" = Stopped (str2ec e)
+              | otherwise = error "Internal error in tryEC"
+          str2ec e =
+              read (e =~ "[0-9]+$")
+-}
+
+-- | like HSH.runSL, but returns all output, not just the first line.
+runS :: String -> IO String
+runS = run
+
+-- | like runS, but returns as list of lines
+runStrings :: String -> IO [String]
+runStrings = ( return . lines =<< ) . run 
diff --git a/HSHHelpers.cabal b/HSHHelpers.cabal
--- a/HSHHelpers.cabal
+++ b/HSHHelpers.cabal
@@ -1,5 +1,5 @@
 Name: HSHHelpers
-Version: 0.18
+Version: 0.19
 License: GPL
 License-file: gpl.txt
 Description: 
