Support non-ascii SMTP user and password strings

The user and more importantly the password used when
authenticating SMTP connections MUST be encoded in utf-8, and
'base64-encode-string' requires unibyte strings, so call
'encode-coding-string' on them before base64 encoding them in
case they are multibyte strings.

This applies to the CRAM-MD5, LOGIN, and PLAIN auth methods.
XOAUTH2 access tokens are specified to contain only characters
in the range #x20-#x7E (SPC through ~), so utf-8 encoding is not
necessary.

See RFC 4616 and RFC 4954 (or their later updates).

* lisp/mail/smtpmail.el (smtpmail-try-auth-method): Encode user
and password using utf-8 before base64 encoding.

(Bug#75628)
This commit is contained in:
Robert Pluim 2025-01-17 16:44:08 +01:00
parent 315519fa7c
commit 745847ba8e

View file

@ -599,6 +599,8 @@ USER and PASSWORD should be non-nil."
(when (eq (car ret) 334)
(let* ((challenge (substring (cadr ret) 4))
(decoded (base64-decode-string challenge))
(password (encode-coding-string password 'utf-8))
(user (encode-coding-string user 'utf-8))
(hash (rfc2104-hash 'md5 64 16 password decoded))
(response (concat user " " hash))
;; Osamu Yamane <yamane@green.ocn.ne.jp>:
@ -618,8 +620,10 @@ USER and PASSWORD should be non-nil."
(cl-defmethod smtpmail-try-auth-method
(process (_mech (eql 'login)) user password)
(smtpmail-command-or-throw process "AUTH LOGIN")
(smtpmail-command-or-throw process (base64-encode-string user t))
(smtpmail-command-or-throw process (base64-encode-string password t)))
(let ((password (encode-coding-string password 'utf-8))
(user (encode-coding-string user 'utf-8)))
(smtpmail-command-or-throw process (base64-encode-string user t))
(smtpmail-command-or-throw process (base64-encode-string password t))))
(cl-defmethod smtpmail-try-auth-method
(process (_mech (eql 'plain)) user password)
@ -628,11 +632,13 @@ USER and PASSWORD should be non-nil."
;; violate a SHOULD in RFC 2222 paragraph 5.1. Note that this
;; is not sent if the server did not advertise AUTH PLAIN in
;; the EHLO response. See RFC 2554 for more info.
(smtpmail-command-or-throw
process
(concat "AUTH PLAIN "
(base64-encode-string (concat "\0" user "\0" password) t))
235))
(let ((password (encode-coding-string password 'utf-8))
(user (encode-coding-string user 'utf-8)))
(smtpmail-command-or-throw
process
(concat "AUTH PLAIN "
(base64-encode-string (concat "\0" user "\0" password) t))
235)))
(cl-defmethod smtpmail-try-auth-method
(process (_mech (eql 'xoauth2)) user password)