(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 screwtape@sdf.org \"   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 'screwtape@sdf.org \"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)))