struct
  type mail = {
      mail_to : string list;
      mail_cc : string list ;
      mail_from : string;
      mail_subject : string;
      mail_body : string;
    }

  let sendmail ?(bin="mhmail") mail =
    let b = Buffer.create 128 in
    let q = Filename.quote in
    Buffer.add_string b bin;
    Printf.bprintf b " -from %s" (q mail.mail_from);
    Printf.bprintf b " -subject %s" (q mail.mail_subject);
    Printf.bprintf b " -body %s" (q mail.mail_body);
    let print_addr_list =
      List.iter (fun addr -> Printf.bprintf b " %s" (q addr))
    in
    print_addr_list mail.mail_to;
    (
     match mail.mail_cc with
       [] -> ()
     | l ->
         Buffer.add_string b " -cc";
         print_addr_list l
    );
    Buffer.add_string b " 2>&1";
    let com = Buffer.contents b in
    Buffer.reset b;
    let buf_size = 2048 in
    let buf = String.create buf_size in
    try
      let ic = Unix.open_process_in com in
      let rec iter () =
        match Pervasives.input ic buf 0 buf_size with
          0 -> ()
        | n -> Buffer.add_substring b buf 0 n;
            iter ()
      in
      iter ();
      let output =
        match Buffer.contents b with "" -> "" | s -> "\n"^s
      in
      match Unix.close_process_in ic with
        Unix.WEXITED 0 -> ()
      | Unix.WEXITED n ->
          let msg = Printf.sprintf "Command %s exited with code %d%s"
              com n output
          in
          failwith msg
      | Unix.WSTOPPED n ->
          let msg = Printf.sprintf "Command %s stopped by signal %d%s"
              com n output
          in
          failwith msg
      | Unix.WSIGNALED n ->
          let msg = Printf.sprintf "Command %s killed by signal %d%s"
              com n output
          in
          failwith msg
    with
      Unix.Unix_error (e,s1,s2) ->
        let msg = Printf.sprintf "%s: %s %s"
            (Unix.error_message e) s1 s2
        in
        failwith msg
    | e ->
        let s = Printexc.to_string e in
        failwith s


end