git.fiddlerwoaroof.com
Browse code

imap 1.8.. response-too-large error

jkf authored on 04/05/2001 16:01:45
Showing 3 changed files
... ...
@@ -1,3 +1,8 @@
1
+2001-05-02  John Foderaro  <jkf@tiger.franz.com>
2
+1.8
3
+	* imap will signal a :response-too-large error if it encounter
4
+	 a letter it can't store in a lisp array.
5
+	
1 6
 2000-06-08    <jkf@CROW>
2 7
 1.7
3 8
 	* imap.cl: add parse-mail-header function to return mail headers
... ...
@@ -19,7 +19,7 @@
19 19
 ;; Commercial Software developed at private expense as specified in
20 20
 ;; DOD FAR Supplement 52.227-7013 (c) (1) (ii), as applicable.
21 21
 ;;
22
-;; $Id: imap.cl,v 1.16 2000/06/08 14:41:00 jkf Exp $
22
+;; $Id: imap.cl,v 1.17 2001/05/04 16:01:45 jkf Exp $
23 23
 
24 24
 ;; Description:
25 25
 ;;
... ...
@@ -95,7 +95,7 @@
95 95
 
96 96
 (provide :imap)
97 97
 
98
-(defparameter *imap-version-number* '(:major 1 :minor 7)) ; major.minor
98
+(defparameter *imap-version-number* '(:major 1 :minor 8)) ; major.minor
99 99
 
100 100
 ;; todo
101 101
 ;;  have the list of tags selected done on a per connection basis to
... ...
@@ -262,7 +262,9 @@
262 262
 ;
263 263
 ;  :timeout  error
264 264
 ;	server failed to respond within the timeout period
265
-
265
+;
266
+;  :response-too-large error
267
+;	contents of a response is too large to store in a Lisp array.
266 268
 
267 269
 
268 270
 ;; conditions
... ...
@@ -560,6 +562,13 @@
560 562
 	      (flet ((add-to-buffer (ch)
561 563
 		       (if* (>= pos (length buf))
562 564
 			  then ; grow buffer
565
+			       (if* (>= (length buf) 
566
+					(1- array-total-size-limit))
567
+				  then ; can't grow it any further
568
+				       (po-error
569
+					:response-too-large
570
+					:format-control
571
+					"response from mail server is too large to hold in a lisp array"))
563 572
 			       (let ((new-buf (get-line-buffer
564 573
 					       (* (length buf) 2))))
565 574
 				 (init-line-buffer new-buf buf)
... ...
@@ -1885,6 +1894,7 @@
1885 1894
 
1886 1895
 (defun get-line-buffer (size)
1887 1896
   ;; get a buffer of at least size bytes
1897
+  (setq size (min size (1- array-total-size-limit)))
1888 1898
   (mp::without-scheduling
1889 1899
     (dolist (buff *line-buffers* (make-string size))
1890 1900
 	(if* (>= (length buff) size)
... ...
@@ -1,7 +1,38 @@
1
-;; mail sending package
1
+;; -*- mode: common-lisp; package: net.aserve -*-
2 2
 ;;
3
-;; smtp -  rfc821
3
+;; smtp.cl
4 4
 ;;
5
+;; copyright (c) 1986-2000 Franz Inc, Berkeley, CA 
6
+;;
7
+;; This code is free software; you can redistribute it and/or
8
+;; modify it under the terms of the version 2.1 of
9
+;; the GNU Lesser General Public License as published by 
10
+;; the Free Software Foundation, as clarified by the AllegroServe
11
+;; prequel found in license-allegroserve.txt.
12
+;;
13
+;; This code is distributed in the hope that it will be useful,
14
+;; but without any warranty; without even the implied warranty of
15
+;; merchantability or fitness for a particular purpose.  See the GNU
16
+;; Lesser General Public License for more details.
17
+;;
18
+;; Version 2.1 of the GNU Lesser General Public License is in the file 
19
+;; license-lgpl.txt that was distributed with this file.
20
+;; If it is not present, you can access it from
21
+;; http://www.gnu.org/copyleft/lesser.txt (until superseded by a newer
22
+;; version) or write to the Free Software Foundation, Inc., 59 Temple Place, 
23
+;; Suite 330, Boston, MA  02111-1307  USA
24
+;;
25
+;;
26
+;; $Id: smtp.cl,v 1.3 2001/05/04 16:01:45 jkf Exp $
27
+
28
+;; Description:
29
+;;   send mail to an smtp server.  See rfc821 for the spec.
30
+
31
+;;- This code in this file obeys the Lisp Coding Standard found in
32
+;;- http://www.franz.com/~jkf/coding_standards.html
33
+;;-
34
+
35
+
5 36
 (defpackage :net.post-office
6 37
   (:use #:lisp #:excl)
7 38
   (:export 
... ...
@@ -10,23 +41,34 @@
10 41
 
11 42
 (in-package :net.post-office)
12 43
 
44
+
13 45
 ;; the exported functions:
14 46
 
15
-;; (send-letter "mail-server" "from" "to" "message" &key subject reply-to)
47
+;; (send-letter "mail-server" "from" "to" "message" 
48
+;;		&key cc bcc subject reply-to headers)
49
+;;								
16 50
 ;;  
17 51
 ;;    sends a message to the mail server (which may be a relay server
18 52
 ;;    or the final destination).  "from" is the address to be given
19 53
 ;;    as the sender.  "to" can be a string or a list of strings naming
20 54
 ;;    recipients.   
21 55
 ;;    "message" is the message to be sent
22
-;;    This builds a header and inserts the optional subject and reply-to
23
-;;    lines.
56
+;;    cc and bcc can be either be a string or a  list of strings
57
+;;	naming recipients.  All cc's and bcc's are sent the message
58
+;;	but the bcc's aren't included in the header created.
59
+;;    reply-to's value is a string and in cases a Reply-To header
60
+;;	 to be created.
61
+;;    headers is a string or list of stings. These are raw header lines
62
+;;	added to the header build to send out.
63
+;;
64
+;;    This builds a header and inserts the optional cc, bcc, 
65
+;;    subject and reply-to  lines.
24 66
 ;;
25 67
 ;; (send-smtp "mail-server" "from" "to" &rest messages)
26 68
 ;;    this is like send-letter except that it doesn't build a header.
27 69
 ;;    the messages should contain a header (and if not then sendmail
28 70
 ;;    notices this and builds one -- other MTAs may not be that smart).
29
-;;    The messages ia  list of string to be concatenated together
71
+;;    The messages ia  list of strings to be concatenated together
30 72
 ;;    and sent as one message
31 73
 ;;
32 74
 ;;
... ...
@@ -35,18 +77,19 @@
35 77
 
36 78
 
37 79
 
38
-
39
-
40
-
41
-
42
-
43
-
44
-(defmacro response-case ((ftp-stream) &rest case-clauses)
80
+(defmacro response-case ((smtp-stream &optional smtp-response) &rest case-clauses)
81
+  ;; get a response from the smtp server and dispatch in a 'case' like
82
+  ;; fashion to a clause based on the first digit of the return
83
+  ;; code of the response.
84
+  ;; smtp-response, if given, will be bound to string that is
85
+  ;;  the actual response
86
+  ;; 
45 87
   (let ((response-class (gensym)))
46
-    `(multiple-value-bind (,response-class ftp-response)
47
-	 (progn (force-output ,ftp-stream)
48
-		(wait-for-response ,ftp-stream))
49
-       (declare (ignorable ftp-response))
88
+    `(multiple-value-bind (,response-class ,@(if* smtp-response
89
+						then (list smtp-response)))
90
+	 (progn (force-output ,smtp-stream)
91
+		(wait-for-response ,smtp-stream))
92
+       ;;(declare (ignorable smtp-response))
50 93
        (case ,response-class
51 94
 	 ,@case-clauses))))
52 95
 
... ...
@@ -55,20 +98,38 @@
55 98
 
56 99
 
57 100
 (defun send-letter (server from to message
58
-		    &key subject
59
-			 reply-to)
60
-  (let ((header (make-string-output-stream)))
101
+		    &key cc bcc subject reply-to headers)
102
+  ;;
103
+  ;; see documentation at the head of this file
104
+  ;;
105
+  (let ((header (make-string-output-stream))
106
+	(tos (if* (stringp to) 
107
+		then (list to) 
108
+	      elseif (consp to)
109
+		then to
110
+		else (error "to should be a string or list, not ~s" to)))
111
+	(ccs
112
+	 (if* (null cc)
113
+	    then nil
114
+	  elseif (stringp cc) 
115
+	    then (list cc) 
116
+	  elseif (consp cc)
117
+	    then cc
118
+	    else (error "cc should be a string or list, not ~s" cc)))
119
+	(bccs (if* (null bcc)
120
+		 then nil
121
+	       elseif (stringp bcc) 
122
+		 then (list bcc) 
123
+	       elseif (consp bcc)
124
+		 then bcc
125
+		 else (error "bcc should be a string or list, not ~s" bcc))))
61 126
     (format header "From: ~a~c~cTo: "
62 127
 	    from
63 128
 	    #\return
64 129
 	    #\linefeed)
65
-    (let ((tos (if* (stringp to) 
66
-			then (list to) 
67
-		      elseif (consp to)
68
-			then to
69
-			else (error "to should be a string or list, not ~s"
70
-				    to))))
71
-      (format header "~{ ~a~^,~}~c~c" tos #\return #\linefeed))
130
+    (format header "~{ ~a~^,~}~c~c" tos #\return #\linefeed)
131
+    (if* ccs 
132
+       then (format header "Cc: ~{ ~a~^,~}~c~c" ccs #\return #\linefeed))
72 133
     
73 134
     (if* subject
74 135
        then (format header "Subject: ~a~c~c" subject #\return #\linefeed))
... ...
@@ -76,14 +137,20 @@
76 137
     (if* reply-to
77 138
        then (format header "Reply-To: ~a~c~c" reply-to #\return #\linefeed))
78 139
     
140
+    (if* headers
141
+       then (if* (stringp headers)
142
+	       then (setq headers (list headers))
143
+	     elseif (consp headers)
144
+	       thenret
145
+	       else (error "Unknown headers format: ~s." headers))
146
+	    (dolist (h headers) 
147
+	      (format header "~a~c~c" h #\return #\linefeed)))
79 148
     
80 149
     (format header "~c~c" #\return #\linefeed)
81 150
     
82
-    (send-smtp server from to (get-output-stream-string header) message)
83
-  
84
-  
85
-  
86
-    ))
151
+    (send-smtp server from (append tos ccs bccs)
152
+	       (get-output-stream-string header)
153
+	       message)))
87 154
     
88 155
     
89 156
 	  
... ...
@@ -102,29 +169,30 @@
102 169
 				  )))
103 170
     (unwind-protect
104 171
 	(progn
105
-	  (response-case (sock)
106
-			 (2 ;; to the initial connect
107
-			  nil)
108
-			 (t (error "initial connect failed")))
172
+	  (response-case (sock msg)
173
+	    (2 ;; to the initial connect
174
+	     nil)
175
+	    (t (error "initial connect failed: ~s" msg)))
109 176
 	  
110 177
 	  ;; now that we're connected we can compute our hostname
111 178
 	  (let ((hostname (socket:ipaddr-to-hostname
112 179
 			   (socket:local-host sock))))
113 180
 	    (if* (null hostname)
114
-	       then (format nil "[~a]" (socket:ipaddr-to-dotted
115
-					(socket:local-host sock))))
181
+	       then (setq hostname
182
+		      (format nil "[~a]" (socket:ipaddr-to-dotted
183
+					  (socket:local-host sock)))))
116 184
 	    (smtp-command sock "HELO ~a" hostname)
117
-	    (response-case (sock)
118
-			   (2 ;; ok
119
-			    nil)
120
-			   (t (error "hello greeting failed"))))
185
+	    (response-case (sock msg)
186
+	      (2 ;; ok
187
+	       nil)
188
+	      (t (error "hello greeting failed: ~s" msg))))
121 189
 	    
122 190
 	  (smtp-command sock "MAIL from:<~a>" from)
123
-	  (response-case (sock)
124
-			 (2 ;; cool
125
-			  nil
126
-			  )
127
-			 (t (error "Mail from command failed")))
191
+	  (response-case (sock msg)
192
+	    (2 ;; cool
193
+	     nil
194
+	     )
195
+	    (t (error "Mail from command failed: ~s" msg)))
128 196
 
129 197
 	  (let ((tos (if* (stringp to) 
130 198
 			then (list to) 
... ...
@@ -134,18 +202,18 @@
134 202
 				    to))))
135 203
 	    (dolist (to tos)
136 204
 	      (smtp-command sock "RCPT to:<~a>" to)
137
-	      (response-case (sock)
138
-			     (2 ;; cool
139
-			      nil
140
-			      )
141
-			     (t (error "rcpt to command failed")))))
205
+	      (response-case (sock msg)
206
+		(2 ;; cool
207
+		 nil
208
+		 )
209
+		(t (error "rcpt to command failed: ~s" msg)))))
142 210
 	
143 211
 	  (smtp-command sock "DATA")
144
-	  (response-case (sock)
145
-			 (3 ;; cool
146
-			  nil)
147
-			 (t (error "Data command failed")))
148
-	  ;(format t "sending message~%") (force-output t)	
212
+	  (response-case (sock msg)
213
+	    (3 ;; cool
214
+	     nil)
215
+	    (t (error "Data command failed: ~s" msg)))
216
+	  
149 217
 	  
150 218
 	  
151 219
 	  (let ((at-bol t))
... ...
@@ -165,19 +233,19 @@
165 233
 	  (write-char #\. sock)
166 234
 	  (write-char #\return sock) (write-char #\linefeed sock)
167 235
 	
168
-	  (response-case (sock)
169
-			 (2 nil ; (format t "Message sent to ~a~%" to)
170
-			    )
236
+	  (response-case (sock msg)
237
+	    (2 nil ; (format t "Message sent to ~a~%" to)
238
+	       )
171 239
 			 
172
-			 (t (error "message not sent")))
240
+	    (t (error "message not sent: ~s" msg)))
173 241
 
174 242
 	  (force-output t)
175 243
 	  
176 244
 	  (smtp-command sock "QUIT")
177
-	  (response-case (sock)
178
-			 (2 ;; cool
179
-			  nil)
180
-			 (t (error "quit failed"))))
245
+	  (response-case (sock msg)
246
+	    (2 ;; cool
247
+	     nil)
248
+	    (t (error "quit failed: ~s" msg))))
181 249
       (close sock))))
182 250
 
183 251
 
... ...
@@ -189,7 +257,7 @@
189 257
 	
190 258
       
191 259
 (defun wait-for-response (stream)
192
-  ;; read the response of the ftp server.
260
+  ;; read the response of the smtp server.
193 261
   ;; collect it all in a string.
194 262
   ;; Return two values:
195 263
   ;; 	response class
... ...
@@ -287,3 +355,5 @@
287 355
 	 then (vector-push-extend ch res))
288 356
 
289 357
       (setq last-ch ch))))
358
+
359
+(provide :smtp)