@@ -233,6 +233,7 @@ public function __construct($host = null, $port = null, $localhost = null,
233
233
$ this ->setAuthMethod ('LOGIN ' , array ($ this , 'authLogin ' ), false );
234
234
$ this ->setAuthMethod ('PLAIN ' , array ($ this , 'authPlain ' ), false );
235
235
$ this ->setAuthMethod ('XOAUTH2 ' , array ($ this , 'authXOAuth2 ' ), false );
236
+ $ this ->setAuthMethod ('OAUTHBEARER ' , array ($ this , 'authOAuthBearer ' ), false );
236
237
}
237
238
238
239
/**
@@ -708,14 +709,17 @@ public function starttls()
708
709
709
710
return true ;
710
711
}
711
-
712
+
712
713
/**
713
714
* Attempt to do SMTP authentication.
714
715
*
715
716
* @param string $uid The userid to authenticate as.
716
717
* @param string $pwd The password to authenticate with.
717
- * @param string $method The requested authentication method. If none is
718
+ * @param string $method The requested authentication method. If none is
718
719
* specified, the best supported method will be used.
720
+ * If you use the special method `OAUTH`, library
721
+ * will choose between OAUTHBEARER or XOAUTH2
722
+ * according the server's capabilities.
719
723
* @param bool $tls Flag indicating whether or not TLS should be attempted.
720
724
* @param string $authz An optional authorization identifier. If specified, this
721
725
* identifier will be used as the authorization proxy.
@@ -749,6 +753,19 @@ public function auth($uid, $pwd , $method = '', $tls = true, $authz = '')
749
753
/* Return the PEAR_Error object from _getBestAuthMethod(). */
750
754
return $ method ;
751
755
}
756
+ } elseif ($ method === 'OAUTH ' ) {
757
+ // special case of OAUTH, use the supported method
758
+ $ found = false ;
759
+ $ available_methods = explode (' ' , $ this ->esmtp ['AUTH ' ]);
760
+ foreach (['OAUTHBEARER ' , 'XOAUTH2 ' ] as $ method ) {
761
+ if (in_array ($ method , $ available_methods )) {
762
+ $ found = true ;
763
+ break ;
764
+ }
765
+ }
766
+ if (!$ found ) {
767
+ return PEAR ::raiseError ("neither OAUTHBEARER nor XOAUTH2 is a supported authentication method " );
768
+ }
752
769
} else {
753
770
$ method = strtoupper ($ method );
754
771
if (!array_key_exists ($ method , $ this ->auth_methods )) {
@@ -1101,28 +1118,65 @@ protected function authGSSAPI($uid, $pwd, $authz = '')
1101
1118
* Authenticates the user using the XOAUTH2 method.
1102
1119
*
1103
1120
* @param string $uid The userid to authenticate as.
1104
- * @param string $token The access token to authenticate with.
1121
+ * @param string $token The access token prefixed by it's type
1122
+ * example: "Bearer $access_token".
1105
1123
* @param string $authz The optional authorization proxy identifier.
1106
1124
* @param object $conn The current object
1107
1125
*
1108
1126
* @return mixed Returns a PEAR_Error with an error message on any
1109
1127
* kind of failure, or true on success.
1110
1128
* @since 1.9.0
1111
1129
*/
1130
+ //FIXME: to switch into protected method on next major release
1112
1131
public function authXOAuth2 ($ uid , $ token , $ authz , $ conn )
1113
1132
{
1114
1133
$ auth = base64_encode ("user= $ uid \1auth= $ token \1\1" );
1134
+ return $ this ->authenticateOAuth ('XOAUTH2 ' , $ auth , $ authz , $ conn );
1135
+ }
1115
1136
1116
- // Maximum length of the base64-encoded token to be sent in the initial response is 497 bytes, according to
1117
- // RFC 4954 (https://datatracker.ietf.org/doc/html/rfc4954); for longer tokens an empty initial
1137
+ /**
1138
+ * Authenticates the user using the OAUTHBEARER method.
1139
+ *
1140
+ * @param string $uid The userid to authenticate as.
1141
+ * @param string $token The access token prefixed by it's type
1142
+ * example: "Bearer $access_token".
1143
+ * @param string $authz The optional authorization proxy identifier.
1144
+ * @param object $conn The current object
1145
+ *
1146
+ * @return mixed Returns a PEAR_Error with an error message on any
1147
+ * kind of failure, or true on success.
1148
+ * @since 1.9.3
1149
+ * @see https://www.rfc-editor.org/rfc/rfc7628.html
1150
+ */
1151
+ protected function authOAuthBearer ($ uid , $ token , $ authz , $ conn )
1152
+ {
1153
+ $ auth = base64_encode ("n,a= $ uid \1auth= $ token \1\1" );
1154
+ return $ this ->authenticateOAuth ('OAUTHBEARER ' , $ auth , $ authz , $ conn );
1155
+ }
1156
+
1157
+ /**
1158
+ * Authenticates the user using the OAUTHBEARER or XOAUTH2 method.
1159
+ *
1160
+ * @param string $method The method (OAUTHBEARER or XOAUTH2)
1161
+ * @param string $auth The authentication string (base64 coded)
1162
+ * @param string $authz The optional authorization proxy identifier.
1163
+ * @param object $conn The current object
1164
+ *
1165
+ * @return mixed Returns a PEAR_Error with an error message on any
1166
+ * kind of failure, or true on success.
1167
+ */
1168
+ protected function authenticateOAuth ( $ method , $ auth , $ authz , $ conn )
1169
+ {
1170
+ // Maximum length of the base64-encoded token to be sent in the initial response is 504 - strlen($method) bytes,
1171
+ // according to RFC 4954 (https://datatracker.ietf.org/doc/html/rfc4954); for longer tokens an empty initial
1118
1172
// response MUST be sent and the token must be sent separately
1119
- // (497 bytes = 512 bytes /SMTP command length limit/ - 13 bytes /"AUTH XOAUTH2 "/ - 2 bytes /CRLF/)
1120
- if (strlen ($ auth ) <= 497 ) {
1121
- if (PEAR ::isError ($ error = $ this ->put ('AUTH ' , ' XOAUTH2 ' . $ auth ))) {
1173
+ // (504 bytes = /SMTP command length limit/ - 6 bytes /"AUTH "/ -strlen($method) - 1 byte /" "/ - 2 bytes /CRLF/)
1174
+ if (strlen ($ auth ) <= ( 504 - strlen ( $ method )) ) {
1175
+ if (PEAR ::isError ($ error = $ this ->put ('AUTH ' , $ method . ' ' . $ auth ))) {
1122
1176
return $ error ;
1123
1177
}
1124
1178
} else {
1125
- if (PEAR ::isError ($ error = $ this ->put ('AUTH ' , ' XOAUTH2 ' ))) {
1179
+ if (PEAR ::isError ($ error = $ this ->put ('AUTH ' , $ method ))) {
1126
1180
return $ error ;
1127
1181
}
1128
1182
0 commit comments