(defpackage mail-demon (:use cl cl-user))
(in-package mail-demon)

;;;Assumes mail over ssh with public key access.

(defvar *ssh-user* "screwtape")
(defvar *ssh-address* "tty.sdf.org")
(defvar *ssh-port* 22)

(defun ssh-args ()
(list (format nil "-p~a" *ssh-port*)
 (format nil "~a@~a" *ssh-user* *ssh-address*)))

(defun get-my-mail () "
Fetch one screen of BSD mail's output as a list of lists. like
(({>}N 1 [email protected] \"   date  size  \\\"subject\\\"\"))
Assumes this is the only way mail is being accessed.
"
(let ((bsd-mail-string
       (with-output-to-string (*standard-output*)
        (with-input-from-string (in (format nil "x~%"))
         (ext:run-program "ssh"
          `(,@(ssh-args) "mail" "-I")
          :output t :input in)))))
 (with-input-from-string (in bsd-mail-string)
  (loop for line = (read-line in nil nil) while line
   collect (with-input-from-string (lin line)
            (list (read lin) (read lin) (read lin)
             (read-line lin)))
   initially
   (let ((initial-line (read-line in nil nil)))
    (when initial-line
     (print initial-line)
     (print (read-line in nil nil))
     (terpri)))))))

(defun send-mail (recipient topic file.txt) "
(send-mail '[email protected] \"a topic\" #p\"my.file.txt\")
Uses system() kludge. Tfw. Backtick ist verbotten.
Avoid things your parent shell is going to misunderstand.
"
(let ((content (substitute #\' #\`
                (with-open-file (in file.txt :direction :input)
                 (format nil "~{~a~%~}"
                  (loop for line = (read-line in nil nil) while line
                   collect line)))))) ;;kludge also
 (ext:system
  (format nil
   "ssh -p~a ~a@~a mail -s '~s' ~a <<EOG
~a
EOG
" *ssh-port* *ssh-user* *ssh-address* topic recipient content))))

(defun dq-mail (&rest to-delete) "
(dq-mail 1 2 3)
runs
mail -I <<EOG
d 1 2 3
q
EOG
"
(with-input-from-string (in (format nil "~{d ~a~%}q~%" to-delete))
 (ext:run-program "ssh"
  `(,@(ssh-args) "mail" "-I")
  :input in :output t :error t)))

(defun get-message (n) "
(get-message 1)
Uses one ssh like:
mail
w 1 .tmp.txt
x
And another:
cat .tmp.txt && rm .tmp.txt
"
(with-input-from-string (in (format nil "write ~d .tmp.txt~%x~%" n))
 (ext:run-program "ssh"
  `(,@(ssh-args) "mail" "-I")
  :input in :output t :error t))
(with-output-to-string (*standard-output*)
 (ext:run-program "ssh"
  `(,@(ssh-args) "cat" ".tmp.txt" "&&" "rm" ".tmp.txt")
  :output t)))