2 ;; @description POP3 mail retrieval routines
3 ;; @version 1.9 - comments redone for automatic documentation
4 ;; @author Lutz Mueller et al., 2001, 2002
6 ;; <h2>POP3 mail retrieval routines</h2>
8 ;; Only the module 'pop3.lsp' is required, not other libraries need to be
9 ;; present. Not all mailservers support all functions.
11 ;; To use the module put a 'load' statement at the top of your file:
13 ;; (load "/usr/share/newlisp/modules/pop3.lsp")
16 ;; <h2>Function overview</h2>
17 ;; Load down all messages and put them in a directory 'messages/':
19 ;; (POP3:get-all-mail "user" "password" "pop.my-isp.com" "messages/")
22 ;; Load down only new messages:
24 ;; (POP3:get-new-mail "user" "password" "pop.my-isp.com" "messages/")
27 ;; Delete messages, which have not been read:
29 ;; (POP3:delete-old-mail "user" "password" "pop.my-isp.com")
32 ;; Delete all messages:
34 ;; (POP3:delete-all-mail "user" "password" "pop.my-isp.com")
37 ;; Get a list of status numbers '(<totalMessages>, <totalBytes>, <lastRead>)':
39 ;; (POP3:get-mail-status "user" "password" "pop.my-isp.com")
42 ;; Get error message for failed all/new/status function:
44 ;; (POP3:get-error-text)
46 ;; All functions return 'nil' on error and 'POP3:get-error-text' can be used to
47 ;; retrieve the error text.
49 ;; The variable 'POP3:debug-flag' can be set to 'true' to display all of the
50 ;; dialog with the pop2 mail server.
56 ;; @syntax (POP3:get-all-mail <str-user> <str-password> <str-server> <str-dir>)
57 ;; @param <str-user> The user ID.
58 ;; @param <str-password> The password for the user ID.
59 ;; @param <str-dir> The local directory for the retrieved mail.
60 ;; @return On success 'true' else 'nil'.
62 (define (get-all-mail userName password pop3server mail-dir
)
65 (logon userName password
)
66 (set 'status
(get-status))
67 (set 'no-msgs
(nth 2 status
))
69 (get-messages 1 no-msgs mail-dir
)
73 ;; @syntax (POP3:get-new-mail <str-user> <str-password> <str-server> <str-dir>)
74 ;; @param <str-user> The user ID.
75 ;; @param <str-password> The password for the user ID.
76 ;; @param <str-dir> The local directory for the retrieved mail.
77 ;; @return On success returns 'true' else 'nil'.
78 ;; On failure use 'POP3:get-error-text' to retrieve the text of
79 ;; the last error which occured.
81 (define (get-new-mail userName password pop3server mail-dir
)
84 (logon userName password
)
85 (set 'status
(get-status true
))
86 (if (<= (first status
) (nth 2 status
))
87 (get-messages (first status
) (nth 2 status
) mail-dir
)
91 ;; @syntax (POP3:get-mail-status <str-user> <str-password> <str-server>)
92 ;; @param <str-user> The user ID.
93 ;; @param <str-password> The password for the user ID.
94 ;; @return A list of status information.
95 ;; The list of status information returned contains the following items:
96 ;; (<totalMessages>, <totalBytes>, <lastRead>)
98 (define (get-mail-status userName password pop3server
)
101 (logon userName password
)
102 (set 'status
(get-status true
))
106 ;; @syntax (POP3:delete-old-mail <str-user> <str-password> <str-server>)
107 ;; @param <str-user> The user ID.
108 ;; @param <str-password> The password for the user ID.
109 ;; @return The number of messages left on the server.
111 (define (delete-old-mail userName password pop3server
)
114 (logon userName password
)
115 (set 'status
(get-status true
))
116 (if (> (first status
) 1)
117 (for (msg 1 (- (first status
) 1) ) (delete-message msg
))
122 ;; @syntax (POP3:delete-all-mail <str-user> <str-password> <str-server>)
123 ;; @param <str-user> The user ID.
124 ;; @param <str-password> The password for the user ID.
125 ;; @return The number of the message last read.
126 (define (delete-all-mail userName password pop3server
)
129 (logon userName password
)
130 (set 'status
(get-status))
131 (if (> (last status
) 0)
132 (for (msg 1 (last status
) ) (delete-message msg
))
137 ; receive request answer and verify
139 (define (net-confirm-request)
140 (if (net-receive socket
'rcvbuff
512 "+OK")
142 (if debug-flag
(println rcvbuff
))
143 (if (find "-ERR" rcvbuff
)
150 (while (> (net-peek socket
) 0)
151 (net-receive socket
'junk
256)
152 (if debug-flag
(println junk
) )))
157 (define (connect server
)
158 (set 'socket
(net-connect pop3server
110))
159 (if (and debug-flag socket
) (println "connected on: " socket
) )
160 (if (and socket
(net-confirm-request))
162 (finish "could not connect")))
165 (define (logon userName password
)
167 (set 'sndbuff
(append "USER " userName
"\r\n"))
168 (net-send socket
'sndbuff
)
169 (if debug-flag
(println "sent: " sndbuff
) true
)
170 (net-confirm-request)
172 (set 'sndbuff
(append "PASS " password
"\r\n"))
173 (net-send socket
'sndbuff
)
174 (if debug-flag
(println "sent: " sndbuff
) true
)
175 (net-confirm-request)
177 (if debug-flag
(println "logon successful") true
)))
180 ; get status and last read
182 (define (get-status last-flag
)
184 (set 'sndbuff
"STAT\r\n")
185 (net-send socket
'sndbuff
)
186 (if debug-flag
(println "sent: " sndbuff
) true
)
187 (net-confirm-request)
188 (net-receive socket
'status
256)
189 (if debug-flag
(println "status: " status
) true
)
193 (set 'sndbuff
"LAST\r\n")
194 (net-send socket
'sndbuff
)
195 (if debug-flag
(println "sent: " sndbuff
) true
)
196 (net-confirm-request)
197 (net-receive socket
'last-read
256)
198 (if debug-flag
(println "last read: " last-read
) true
)
200 (set 'last-read
"0"))
201 (set 'result
(list (int (first (parse status
)))))
202 (if debug-flag
(println "parsed status: " result
) true
)
203 (push (int (nth 1 (parse status
))) result
)
204 (push (int (first (parse last-read
))) result
)
210 (define (retrieve-message , message
)
213 (while (not finished
)
214 (net-receive socket
'rcvbuff
16384)
215 (set 'message
(append message rcvbuff
))
216 (if (find "\r\n.\r\n" message
) (set 'finished true
)))
217 (if debug-flag
(println "received message") true
)
223 ; v 1.4: modified file name generation to improve uniqueness. (CaveGuy)
224 ; file name now created using last SMTP or ESMTP ID from header.
225 ; v 1.5: changed file type to ".pop3" to reflect the context that created it.
226 ; (get-messages now forces the directory, if it does not exsist.
228 ; v 1.6: make sure directory? doesn't have trailing slash in arg
230 (define (get-messages from to mail-dir
)
231 (if (ends-with mail-dir
"/") (set 'mail-dir
(chop mail-dir
)))
232 (if (if (not (directory? mail-dir
)) (make-dir mail-dir
) true
)
234 (set 'mail-dir
(append mail-dir
"/"))
236 (if debug-flag
(println "getting message " msg
) true
)
237 (set 'sndbuff
(append "RETR " (string msg
) "\r\n"))
238 (net-send socket
'sndbuff
)
239 (if debug-flag
(println "sent: " sndbuff
) true
)
240 (set 'message
(retrieve-message))
241 (if debug-flag
(println (slice message
1 200)) true
)
242 (set 'istr
(get-message-id message
))
243 (set 'istr
(append mail-dir
"ME-" istr
))
244 (if debug-flag
(println "saving " istr
) true
)
245 (write-file istr message
)
246 (if (not (rename-file istr
(append istr
".pop3")))
247 (delete-file istr
)))))
248 true
) ; other parts of pop3 rely on 'true' return
252 (define (delete-message msg
)
254 (set 'sndbuff
(append "DELE " (string msg
) "\r\n"))
255 (net-send socket
'sndbuff
)
256 (if debug-flag
(println "sent: " sndbuff
) true
)
257 (net-confirm-request)))
259 ; get-message-date was
260 ; changed to get-message-id
263 (define (get-message-id message
)
264 (set 'ipos
(+ (find "id <| id |\tid " message
1) 5)
265 'iend
(find "@|;|\n|\r| |\t" (slice message ipos
) 1))
267 (print "Message ID: " (slice message ipos iend
) "\n"))
268 (set 'istr
(slice message ipos iend
)) )
274 (set 'sndbuff
"QUIT\r\n")
275 (net-send socket
'sndbuff
)
276 (if debug-flag
(println "sent: " sndbuff
) true
)
277 (net-receive socket
'rcvbuff
256)
278 (if debug-flag
(println rcvbuff
) true
)
281 ; report error and finish
283 (define (finish message
)
284 (if (ends-with message
"+OK")
285 (set 'message
(chop message
3)))
286 ;(print "<h3>" message "</h3>")
287 (set 'mail-error-text message
)
288 (if debug-flag
(println "ERROR: " message
) true
)
289 (if socket
(net-flush))
290 (if socket
(log-off))
293 ;; @syntax (POP3:get-error-text)
294 ;; @return The text of the last error occurred.
296 (define (get-error-text) mail-error-text
)
301 ;(if (not(POP3:get-all-mail "user" "password" "my-isp.com" "mail"))
302 ; (print (POP3:get-error-text)) true)
305 ;(POP3:get-new-mail "user" "password" "my-isp.com" "mail")
306 ;(print (POP3:get-mail-status ""user" "password" "my-isp.com"))