简体   繁体   English

使用 curl c++ 发送电子邮件

[英]Sending an email using curl c++

Im trying to send an email using curl c++, i managed to log in well and when i run the program it works fine, does not throw any error, but the email never comes.我尝试使用 curl c++ 发送电子邮件,我成功登录,当我运行程序时它工作正常,不会抛出任何错误,但电子邮件永远不会出现。

This is my code:这是我的代码:

#include <iostream>
#include <curl/curl.h>

static const char *payload_text =
  "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
  "To: " "mailto" "\r\n"
  "From: " "mymail" "\r\n"
  "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
  "rfcpedant.example.org>\r\n"
  "Subject: SMTP 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";

size_t read_function(char *buffer, size_t size, size_t nmemb,char *data)
{
    size_t len;
    if(size == 0 or nmemb == 0)
    {
        return 0;
    }
    if(data)
    {
        len = strlen(data);
        memcpy(buffer, data, len);
        return len;
    }
    return 0;  
}

int main()
{
    CURL *curl;
    CURLcode res = CURLE_OK;
    const char *data = payload_text;
 
    curl = curl_easy_init();
    if(curl) 
    {
        curl_easy_setopt(curl, CURLOPT_USERNAME, "mymail"); 
        curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
        curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
        curl_easy_setopt(curl, CURLOPT_MAIL_FROM, "my mail");
        curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, "mailto");
        curl_easy_setopt(curl, CURLOPT_READDATA,payload_text);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_function);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
        curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
    }
    res = curl_easy_perform(curl);
    
    if(res != CURLE_OK)
    {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
        curl_easy_strerror(res));
        curl_easy_cleanup(curl);
    }
    return 0;
}

I think the problem is in the curl options READDATA and READUNCTION.我认为问题出在 curl 选项 READDATA 和 READUNCTION 中。 In the documentation says that you have to pass as an argument to READDATA a data pointer.在文档中说您必须将数据指针作为参数传递给 READDATA。 const char *data = payload_text; is the data pointer, right?是数据指针,对吧?

then READFUNCTION takes as an argument a function which return the size of the data and i think that is what size_t read_function(char *buffer, size_t size, size_t nmemb,char *data) is doing.然后 READFUNCTION 将返回数据大小的函数作为参数,我认为这就是size_t read_function(char *buffer, size_t size, size_t nmemb,char *data)正在做的事情。

I am new in this so any advice would be good for me.我是这方面的新手,所以任何建议对我都有好处。

I found this to be a helpful starting point: https://curl.se/libcurl/c/smtp-mail.html我发现这是一个有用的起点: https ://curl.se/libcurl/c/smtp-mail.html

There are two main problems with your code:您的代码有两个主要问题:

  1. Your read_function didn't keep track of how much of the payload has been read so it would keep giving the same content to libcurl over and over and never signal the end of the message.您的read_function没有跟踪已读取了多少有效负载,因此它会一遍又一遍地向 libcurl 提供相同的内容,并且永远不会发出消息结束的信号。
  2. You were setting CURLOPT_MAIL_RCPT to a string when in fact it should be a struct curl_slist * because there can be multiple recipients.您将 CURLOPT_MAIL_RCPT 设置为字符串,而实际上它应该是struct curl_slist *因为可以有多个收件人。

Here is a fixed example that I tested on my computer and it worked.这是我在计算机上测试的一个固定示例,它有效。 Private data at the top of the file was modified before posting.文件顶部的私人数据在发布前已被修改。

#define USERNAME "david"
#define PASSWORD "xxxxx"
#define MAILTO "david@example.com"
#define MAILFROM "you@example.com"
#define SMTP "smtp://your.smtp.server.example.com:25"

#include <stdio.h>
#include <curl/curl.h>

const char * payload_text =
  "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
  "To: " MAILTO "\r\n"
  "From: " MAILFROM "\r\n"
  "Subject: SMTP example message with libcurl 6\r\n"
  "\r\n"
  "Hello world!\r\n";

struct ReadData
{
  explicit ReadData(const char * str)
  {
    source = str;
    size = strlen(str);
  }

  const char * source;
  size_t size;
};

size_t read_function(char * buffer, size_t size, size_t nitems, ReadData * data)
{
  size_t len = size * nitems;
  if (len > data->size) { len = data->size; }
  memcpy(buffer, data->source, len);
  data->source += len;
  data->size -= len;
  return len;
}

int main()
{
  CURL * curl = curl_easy_init();
  if (!curl)
  {
    fprintf(stderr, "curl_easy_init failed\n");
    return 1;
  }

  curl_easy_setopt(curl, CURLOPT_USERNAME, USERNAME);
  curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD);
  curl_easy_setopt(curl, CURLOPT_URL, SMTP);
  curl_easy_setopt(curl, CURLOPT_MAIL_FROM, MAILFROM);

  struct curl_slist * rcpt = NULL;
  rcpt = curl_slist_append(rcpt, MAILTO);
  curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt);

  ReadData data(payload_text);
  curl_easy_setopt(curl, CURLOPT_READDATA, &data);
  curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_function);

  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
  curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);

  // If your server doesn't have a proper SSL certificate:
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);

  CURLcode res = curl_easy_perform(curl);
  if (res != CURLE_OK)
  {
    fprintf(stderr, "curl_easy_perform() failed: %s\n",
      curl_easy_strerror(res));
    curl_easy_cleanup(curl);
  }
  return 0;
}

read_function : you are changing the local pointer buffer that does not affect the byte buffer of a caller. read_function :您正在更改不影响调用者字节缓冲区的本地指针buffer You should copy data to the pointed buffer您应该将数据复制到指向的缓冲区

memcpy(buffer, data, len);

FYI sizeof(char) is guaranteed to be 1, thus is unneeded.仅供参考sizeof(char)保证为 1,因此不需要。

Another issue - the function never returns 0 that signals all data is sent, it sends the same data again and again.另一个问题 - 该函数永远不会返回 0 表示所有数据都已发送,它会一次又一次地发送相同的数据。 You should return 0 on a second call.您应该在第二次调用时返回 0。 Or set the length to the option CURLOPT_POSTFIELDSIZE_LARGE .或者将长度设置为选项CURLOPT_POSTFIELDSIZE_LARGE

See the example smtp-mail.c请参阅示例smtp-mail.c

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM