なんだこれは

はてなダイアリーから移転しました。

複数のemlテキストをcsvにするってない?

eml形式の(要は1メール1ファイルの)メールテキストがいっぱいあってこれを、CSVのレコードにして、一覧にしたいという。

よくわからないが、適当なツールをさがしてみたが、いいのがない。
捜すのが下手なのかもしれない。

しかたがないので、適当に書いてみた。


ひょっとしたら、date は 日付と時間にわけたほうがよかったのかもしれない。

(ql:quickload :cl-ppcre)
(ql:quickload :csv-parser)
(ql:quickload :cl-fad)

(defvar *max-message-body-limit* 50) ;; max line for message body

;;;;
#|
; if it works on windows
(setf ccl:*default-external-format* (ccl:make-external-format
				     :character-encoding :cp932
				     :line-termination :dos))
; or other

(setf ccl:*default-external-format* (ccl:make-external-format
				     :character-encoding :utf8
				     :line-termination :unix))

|#

(defun read-txt-mail (file)
  (let ((from nil)
	(subject nil)
	(date nil)
	(message-body "")
	(message-body-count nil))
    (with-open-file (in file :direction :input)
      (loop for line = (read-line in nil nil)
	   while line
	   do (progn 
		(setf from (get-var from line "^From:" ": "))
		(setf subject (get-var subject line "^Subject:" ": "))
		(setf date (get-var date line "^Date:" ": "))
		(if message-body-count
		    (when (< message-body-count *max-message-body-limit*)
		      (incf message-body-count)
		      (setf message-body (format nil "~a~%~a" message-body line)))
		    (when (cl-ppcre:scan "^\\s*$" line)
		      (setf message-body-count 0))))))
    (list subject from date message-body)))

(defun get-var (var line regex delimit)
  (if var
      var
      (if (cl-ppcre:scan regex line)
	  (nth 1 (cl-ppcre:split delimit line))
	  nil)))

(defun read-dir (path)
  (let ((lst nil))
    (cl-fad:walk-directory 
     (cl-fad:pathname-as-directory path)
     (lambda (x) 
       (when 
	   (string-equal (pathname-type x) "txt") 
	 (push (read-txt-mail (namestring x)) lst))))
    (reverse lst)))

(defun lst-lst-csv (lst file)
  (with-open-file (out file :direction :output)
    (dolist (ls lst)
      (csv-parser:write-csv-line out ls)
 )))

(defun main ()
  (if (<= (length ccl:*command-line-argument-list*) 1)
      (format t "this program require 2 args for dir name (input) and csv file name (output) ")
      (lst-lst-csv (read-dir (first ccl:*command-line-argument-list*))
		   (second ccl:*command-line-argument-list*))))