git.fiddlerwoaroof.com
Browse code

rfe12276: Handle SMTP servers which violate SMTP SASL AUTH protocol

Some SMTP servers (notably The Amazon SES SMTP endpoint
(email-smtp.us-east-1.amazonaws.com)) violate the protocol rules on the
first server response. Apparently other SMTP clients are tolerant of
this, so we try to be as well.

Change-Id: I5280fa6473e56b5c08188d2819db3271294bf62a

Ahmon Dancy authored on 19/04/2013 14:38:40
Showing 1 changed files
... ...
@@ -1,3 +1,9 @@
1
+#+(version= 8 2)
2
+(sys:defpatch "smtp" 1
3
+  "v1: Handle SMTP servers which violate SMTP SASL AUTH protocol."
4
+  :type :system
5
+  :post-loadable t)
6
+
1 7
 #+(version= 8 1)
2 8
 (sys:defpatch "smtp" 1
3 9
   "v1: add smtp support for ssl connections and STARTTLS negotiation."
... ...
@@ -472,7 +478,8 @@ Attachments must be filenames, streams, or mime-part-constructed, not ~s"
472 478
 (defun smtp-authenticate (sock server mechs login password)
473 479
   (let ((ctx (net.sasl:sasl-client-new "smtp" server
474 480
 				       :user login
475
-				       :pass password)))
481
+				       :pass password))
482
+	(first-server-response t))
476 483
     (multiple-value-bind (res selected-mech response)
477 484
 	(net.sasl:sasl-client-start ctx mechs)
478 485
       (if (not (eq res :continue))
... ...
@@ -481,12 +488,30 @@ Attachments must be filenames, streams, or mime-part-constructed, not ~s"
481 488
       (loop
482 489
 	(response-case (sock msg)
483 490
 	  (3  ;; need more interaction
484
-	   (multiple-value-setq (res response)
485
-	     (net.sasl:sasl-step 
486
-	      ctx 
487
-	      (base64-string-to-usb8-array (subseq msg 4))))
488
-	   (smtp-command sock "~a" 
489
-			 (usb8-array-to-base64-string response nil)))
491
+	   ;; [rfe12276] Some SMTP servers (notably The Amazon SES
492
+	   ;; SMTP endpoint (email-smtp.us-east-1.amazonaws.com))
493
+	   ;; violate the protocol rules on the first server response.
494
+	   ;; Apparently other SMTP clients are tolerant of this, so
495
+	   ;; we try to be as well.
496
+	   
497
+	   (multiple-value-bind (decoded-server-response err)
498
+	       (ignore-errors (base64-string-to-usb8-array (subseq msg 4)))
499
+	     (when (null decoded-server-response)
500
+	       (if* first-server-response
501
+		  then ;; Ignore initial server response if it's
502
+		       ;; bogus.
503
+		       ;;;(warn "Bogus server initial response: ~s~%" (subseq msg 4))
504
+		       (setf first-server-response nil)
505
+		  else ;; We tolerate a bogus initial response, but no others
506
+		       (error "Failed to decode server response of ~s: ~a"
507
+			      (subseq msg 4)
508
+			      err)))
509
+	     
510
+	     (multiple-value-setq (res response)
511
+	       (net.sasl:sasl-step ctx decoded-server-response))
512
+	     
513
+	     (smtp-command sock "~a" 
514
+			   (usb8-array-to-base64-string response nil))))
490 515
 	  (2 ;; server is satisfied.
491 516
 	   ;; Make sure the auth process really completed
492 517
 	   (if (not (net.sasl:sasl-conn-auth-complete-p ctx))