535 5.7.3 当我尝试通过 libcurl 登录以向 SMTP 服务器发出 smtp 请求时身份验证失败
535 5.7.3 Authentication unsuccessful when i try to login via libcurl to do a smtp request to SMTP server
我正在尝试使用 libcurl 发送邮件。我已经在 Azure 中注册了我的应用程序,现在我有指向 /authorize 和 /token 的端点。我已经使用我的 Client_id 和授权类型为 type=client_credentials
的 Secret 获得了访问令牌,当我在登录时使用相同的令牌作为我的密码时,它仍然说来自服务器的身份验证失败。
我试过用户名为 mymail@domain.com
密码为
我错过了什么?
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#define FROM_ADDR "<lohit@mydomain.com>"
#define TO_ADDR "XXXX"
#define CC_ADDR "XXXX"
#define FROM "Lohit" FROM_ADDR
#define TO "XXX" TO_ADDR
#define CC "XXX"CC_ADDR
#define ClientID "XXXXXXX"
#define Secret "XXXXXXX"
typedef struct a_token_s {
char *token;
size_t size;
}a_token_t;
typedef struct resp_data_s {
char *resp;
size_t size;
}resp_data_t;
struct upload_status {
int lines_read;
};
static const char *payload_text[] = {
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
"To: " TO "\r\n",
"From: " FROM "\r\n",
"Cc: " CC "\r\n",
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n",
"Subject: SMTP TLS example message\r\n",
"\r\n", /* empty line to divide headers from body, see RFC5322 */
"The body of the message starts here.\r\n",
"\r\n",
"It could be a lot of lines, could be MIME encoded, whatever.\r\n",
"Check RFC5322.\r\n",
NULL
};
static void parse_token(resp_data_t *rsp_data,
a_token_t *a_token)
{
char *tmp, *tmp2;
char *needle = "\"access_token\":\"";
char token[100];
int len;
tmp = strstr(rsp_data->resp, needle);
if (tmp) {
tmp = tmp + strlen(needle);
a_token->token = malloc(2048);
if (!a_token->token){
return;
}
a_token->size = 2048;
tmp2 = strstr(tmp, "\"}");
if (!tmp2) {
free(a_token->token);
return;
}
len = tmp2 - tmp;
if (len + 1 > a_token->size) {
free(a_token->token);
return;
}
snprintf(a_token->token, len + 1, "%s", tmp);
a_token->token[len] = '[=10=]';
printf("FINAL:\n%s\n", a_token->token);
}
return;
}
static size_t cb(void *data, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
resp_data_t *rsp_data = (resp_data_t *)userp;
char *ptr = realloc(rsp_data->resp, rsp_data->size + realsize + 1);
if(ptr == NULL)
return 0; /* out of memory! */
rsp_data->resp = ptr;
memcpy(&(rsp_data->resp[rsp_data->size]), data, realsize);
rsp_data->size += realsize;
rsp_data->resp[rsp_data->size] = 0;
printf("%s\n", rsp_data->resp);
return realsize;
}
static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct upload_status *upload_ctx = (struct upload_status *)userp;
const char *data;
if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
return 0;
}
data = payload_text[upload_ctx->lines_read];
if(data) {
size_t len = strlen(data);
memcpy(ptr, data, len);
upload_ctx->lines_read++;
return len;
}
return 0;
}
int send_mail(a_token_t *a_token){
printf("SEND MAIL START\n");
CURL *hnd;
CURLcode ret = CURLE_OK;
struct curl_slist *recipients = NULL;
struct upload_status upload_ctx;
char usr_pwd_str[2048 + 50] = "lohit@mydomain.com:";
char *usr_pwd;
upload_ctx.lines_read = 0;
hnd = curl_easy_init();
if (!hnd) {
return 1;
}
if (!strlen(a_token->token)){
printf("no token\n");
return 1;
}
usr_pwd = strcat(usr_pwd_str, a_token->token);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.68.0");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(hnd, CURLOPT_SSH_KNOWNHOSTS, "/home/lohit/.ssh/known_hosts");
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* me trying to find ways to login*/
curl_easy_setopt(hnd, CURLOPT_USERNAME, "lohit@mydomain.com");
curl_easy_setopt(hnd, CURLOPT_PASSWORD, a_token->token);
curl_easy_setopt(hnd, CURLOPT_USERPWD, usr_pwd);
curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
curl_easy_setopt(hnd, CURLOPT_XOAUTH2_BEARER, a_token->token);
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://smtp.office365.com:587");
curl_easy_setopt(hnd, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, FROM_ADDR);
recipients = curl_slist_append(recipients, TO_ADDR);
recipients = curl_slist_append(recipients, CC_ADDR);
curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, recipients);
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(hnd, CURLOPT_READDATA, &upload_ctx);
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
/* Send the message */
ret = curl_easy_perform(hnd);
/* Check for errors */
if(ret != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(ret));
/* Free the list of recipients */
curl_slist_free_all(recipients);
/* Always cleanup */
curl_easy_cleanup(hnd);
return (int)ret;
}
int main(int argc, char *argv[])
{
CURLcode ret;
CURL *hnd;
char *url= "https://login.microsoftonline.com/<myapp>/oauth2/token";
hnd = curl_easy_init();
if (!hnd) {
return 1;
}
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(hnd, CURLOPT_URL, url);
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(hnd, CURLOPT_USERPWD, ClientID":"Secret);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "grant_type=client_credentials&scope=User.Read,openid,profile,email,offline_access");
curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)29);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.68.0");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(hnd, CURLOPT_SSH_KNOWNHOSTS, "/home/lohit/.ssh/known_hosts");
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_LOCALPORT, 2020L);
curl_easy_setopt(hnd, CURLOPT_LOCALPORTRANGE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
resp_data_t rsp_data;
rsp_data.resp = NULL;
rsp_data.size = 0;
curl_easy_setopt(hnd, CURLOPT_WRITEDATA,(void *)&rsp_data);
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, cb);
ret = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
hnd = NULL;
a_token_t a_token;
a_token.size = 0;
parse_token(&rsp_data, &a_token);
send_mail(&a_token);
free(rsp_data.resp);
free(a_token.token);
return (int)ret;
}
/**** End of sample code ****/
它缺少我在 Azure 门户中编辑的权限,需要管理员同意。然后一切就绪!
我正在尝试使用 libcurl 发送邮件。我已经在 Azure 中注册了我的应用程序,现在我有指向 /authorize 和 /token 的端点。我已经使用我的 Client_id 和授权类型为 type=client_credentials
的 Secret 获得了访问令牌,当我在登录时使用相同的令牌作为我的密码时,它仍然说来自服务器的身份验证失败。
我试过用户名为 mymail@domain.com
密码为
我错过了什么?
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#define FROM_ADDR "<lohit@mydomain.com>"
#define TO_ADDR "XXXX"
#define CC_ADDR "XXXX"
#define FROM "Lohit" FROM_ADDR
#define TO "XXX" TO_ADDR
#define CC "XXX"CC_ADDR
#define ClientID "XXXXXXX"
#define Secret "XXXXXXX"
typedef struct a_token_s {
char *token;
size_t size;
}a_token_t;
typedef struct resp_data_s {
char *resp;
size_t size;
}resp_data_t;
struct upload_status {
int lines_read;
};
static const char *payload_text[] = {
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
"To: " TO "\r\n",
"From: " FROM "\r\n",
"Cc: " CC "\r\n",
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n",
"Subject: SMTP TLS example message\r\n",
"\r\n", /* empty line to divide headers from body, see RFC5322 */
"The body of the message starts here.\r\n",
"\r\n",
"It could be a lot of lines, could be MIME encoded, whatever.\r\n",
"Check RFC5322.\r\n",
NULL
};
static void parse_token(resp_data_t *rsp_data,
a_token_t *a_token)
{
char *tmp, *tmp2;
char *needle = "\"access_token\":\"";
char token[100];
int len;
tmp = strstr(rsp_data->resp, needle);
if (tmp) {
tmp = tmp + strlen(needle);
a_token->token = malloc(2048);
if (!a_token->token){
return;
}
a_token->size = 2048;
tmp2 = strstr(tmp, "\"}");
if (!tmp2) {
free(a_token->token);
return;
}
len = tmp2 - tmp;
if (len + 1 > a_token->size) {
free(a_token->token);
return;
}
snprintf(a_token->token, len + 1, "%s", tmp);
a_token->token[len] = '[=10=]';
printf("FINAL:\n%s\n", a_token->token);
}
return;
}
static size_t cb(void *data, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
resp_data_t *rsp_data = (resp_data_t *)userp;
char *ptr = realloc(rsp_data->resp, rsp_data->size + realsize + 1);
if(ptr == NULL)
return 0; /* out of memory! */
rsp_data->resp = ptr;
memcpy(&(rsp_data->resp[rsp_data->size]), data, realsize);
rsp_data->size += realsize;
rsp_data->resp[rsp_data->size] = 0;
printf("%s\n", rsp_data->resp);
return realsize;
}
static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct upload_status *upload_ctx = (struct upload_status *)userp;
const char *data;
if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
return 0;
}
data = payload_text[upload_ctx->lines_read];
if(data) {
size_t len = strlen(data);
memcpy(ptr, data, len);
upload_ctx->lines_read++;
return len;
}
return 0;
}
int send_mail(a_token_t *a_token){
printf("SEND MAIL START\n");
CURL *hnd;
CURLcode ret = CURLE_OK;
struct curl_slist *recipients = NULL;
struct upload_status upload_ctx;
char usr_pwd_str[2048 + 50] = "lohit@mydomain.com:";
char *usr_pwd;
upload_ctx.lines_read = 0;
hnd = curl_easy_init();
if (!hnd) {
return 1;
}
if (!strlen(a_token->token)){
printf("no token\n");
return 1;
}
usr_pwd = strcat(usr_pwd_str, a_token->token);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.68.0");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(hnd, CURLOPT_SSH_KNOWNHOSTS, "/home/lohit/.ssh/known_hosts");
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* me trying to find ways to login*/
curl_easy_setopt(hnd, CURLOPT_USERNAME, "lohit@mydomain.com");
curl_easy_setopt(hnd, CURLOPT_PASSWORD, a_token->token);
curl_easy_setopt(hnd, CURLOPT_USERPWD, usr_pwd);
curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
curl_easy_setopt(hnd, CURLOPT_XOAUTH2_BEARER, a_token->token);
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://smtp.office365.com:587");
curl_easy_setopt(hnd, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, FROM_ADDR);
recipients = curl_slist_append(recipients, TO_ADDR);
recipients = curl_slist_append(recipients, CC_ADDR);
curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, recipients);
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(hnd, CURLOPT_READDATA, &upload_ctx);
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
/* Send the message */
ret = curl_easy_perform(hnd);
/* Check for errors */
if(ret != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(ret));
/* Free the list of recipients */
curl_slist_free_all(recipients);
/* Always cleanup */
curl_easy_cleanup(hnd);
return (int)ret;
}
int main(int argc, char *argv[])
{
CURLcode ret;
CURL *hnd;
char *url= "https://login.microsoftonline.com/<myapp>/oauth2/token";
hnd = curl_easy_init();
if (!hnd) {
return 1;
}
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(hnd, CURLOPT_URL, url);
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(hnd, CURLOPT_USERPWD, ClientID":"Secret);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "grant_type=client_credentials&scope=User.Read,openid,profile,email,offline_access");
curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)29);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.68.0");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(hnd, CURLOPT_SSH_KNOWNHOSTS, "/home/lohit/.ssh/known_hosts");
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_LOCALPORT, 2020L);
curl_easy_setopt(hnd, CURLOPT_LOCALPORTRANGE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
resp_data_t rsp_data;
rsp_data.resp = NULL;
rsp_data.size = 0;
curl_easy_setopt(hnd, CURLOPT_WRITEDATA,(void *)&rsp_data);
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, cb);
ret = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
hnd = NULL;
a_token_t a_token;
a_token.size = 0;
parse_token(&rsp_data, &a_token);
send_mail(&a_token);
free(rsp_data.resp);
free(a_token.token);
return (int)ret;
}
/**** End of sample code ****/
它缺少我在 Azure 门户中编辑的权限,需要管理员同意。然后一切就绪!