Member 12890589 Ответов: 1

Можете отправить динамической теле письма на скручиваемость


Я новичок в CURL и пытаюсь отправить динамическое тело сообщения. Но я получаю только пустую тему и тело сообщения, когда пытаюсь использовать curl lib в visual c++.
Пожалуйста помочь.

Что я уже пробовал:

<pre>    size_t Process::processmail(void *ptr, size_t size, size_t nmemb, void *userp)
    {
	std::string a, b, c, d;
	std::string arr[MAXSPACE];
	std::string search = ",";
	int spacePos;
	int currPos = 0;
	int k = 0;
	int prevPos = 0;
	std::string &statistics = *(static_cast<std::string*>(userp));
	do
	{
		spacePos = statistics.find(search, currPos);
		if (spacePos >= 0)
		{

			currPos = spacePos;
			arr[k] = statistics.substr(prevPos, currPos - prevPos);
			currPos++;
			prevPos = currPos;
			k++;
		}
	} while (spacePos >= 0);

	arr[k] = statistics.substr(prevPos, statistics.length());

	for (int i = 0; i < k; i++)
	{
		std::cout << arr[i] << std::endl;
	}
	a = arr[3];
	b = arr[2];
	c = arr[1];
	d = arr[0];
	const char *data;
	time_t now = time(0);
	char* dt = ctime(&now);
	const char *payload_text[] = {
		"Date: ", dt, "\r\n",
		"To: ",mail.c_str(), "\r\n",
		"From: " FROM "\r\n",
		"Subject: Analysis\r\n",
		"\r\n",
		"This is just a test message.\r\n",
		"\r\n",
		"A:", a.c_str(), "\r\n",
		"B:", b.c_str(), "\r\n",
		"C:", c.c_str(), "\r\n",
		NULL
	};

		if ((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
		return 0;
	}

	data = payload_text[lines_read];

	if (data) {
		size_t len = strlen(data);
		memcpy(ptr, data, len);
		lines_read++;
		return len;
	}
	return 0;
    }

     void Process::sendmail(std::string mail)
    {
	CURL *curl;
	CURLcode res = CURLE_OK;
	struct curl_slist *recipients = NULL;
	curl = curl_easy_init();
	if (curl) {
	
		curl_easy_setopt(curl, CURLOPT_USERNAME, "User Name");
		curl_easy_setopt(curl, CURLOPT_PASSWORD, "Password");
		curl_easy_setopt(curl, CURLOPT_URL, "smtp.hushmail.com:587");
		curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
		curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/certificate.pem");
		curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
		recipients = curl_slist_append(recipients, mail.c_str());
		curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
		curl_easy_setopt(curl, CURLOPT_READFUNCTION, &Process::processmail);
		curl_easy_setopt(curl, CURLOPT_READDATA, lines_read);
		curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

		
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

		
		res = curl_easy_perform(curl);

		
		if (res != CURLE_OK)
			fprintf(stderr, "curl_easy_perform() failed: %s\n",
			curl_easy_strerror(res));

		
		curl_slist_free_all(recipients);

		curl_easy_cleanup(curl);
	 }
    }

1 Ответов

Рейтинг:
5

Jochen Arndt

Итак, вы взяли пример из например libcurl использует с SMTP-почты.с[^] и изменил его.

Одна из ваших модификаций связана с почтовым содержимым, которое создается функцией обратного вызова. Так что проблема, очевидно, находится там. Кандидатом будет lines_read переменная. Но вы не показали определение этой переменной и где она инициализируется каким значением.

Функции обратного вызова должны быть статическими и поэтому обычно поддерживают аргумент указателя, чтобы разрешить доступ к нестатическим частям вашего приложения. Так и здесь. Но вы не использовали этот механизм (удалили соответствующую обработку, предусмотренную примером кода). Итак, установка CURLOPT_READDATA option бесполезен в вашем коде, а также неверен (аргумент должен быть указателем, но вы передаете lines_read что, вероятно, является int).

В классах C++ обычно указатель на класс intance передается функции обратного вызова. Затем у вас есть доступ к членам класса из статической функции обратного вызова. Принятие примера кода для вашего случая может быть сделано таким образом:

class Process
{
    // ...
protected:
    int lines_read;
    static size_t processmail(void *ptr, size_t size, size_t nmemb, void *userp);
};


size_t Process::processmail(void *ptr, size_t size, size_t nmemb, void *userp)
{
    // Must pass 'this' pointer when setting CURLOPT_READDATA
    Process *self = reinterpret_cast<Process*>(userp);
    // ...
    const char *data = payload_text[self->lines_read];
    size_t len = data ? strlen(data) : 0;
    // Check for sufficient buffer size
    // This is missing in the libcurl example
    if (len > nmemb * size)
        len = 0;
    if (len)
    {
        memcpy(ptr, data, len);
        self->lines_read++;
    }
    return len;
}

void Process::sendmail(std::string mail)
{
    lines_read = 0;
    // ...
    curl_easy_setopt(curl, CURLOPT_READDATA, this);
    // ...
}


[РЕДАКТИРОВАТЬ]
Отвечая на нижеприведенный комментарий и расширяя решение о дополнительной ошибке, которую я изначально не распознал.

Линия
std::string &statistics = *(static_cast<std::string*>(userp));
не работает с вышеприведенным решением и не работал с исходным кодом. Отливка должна быть в соответствии с типом пройденного с CURLOPT_READDATA.

При использовании моего решения передающего указатель класса это должно быть что то вроде:
std::string &statistics = self->statistics;
когда statistics это Process член класса типа string.

[/РЕДАКТИРОВАТЬ]


Member 12890589

@Jochen Arndt-Спасибо за ваше решение. После того, как я реализую ваше решение, я получаю исключение " (msvcr120d.dll) в SampleApp.exe: 0xC0000005: нарушение доступа к местоположению чтения 0x0000000000000000.". Он перенаправляется в файл iosfwd.h. статический константный _Elem *__CLRCALL_или_ключевое слово cdecl найти(пост _Elem *на _first, реализация _Count,
const _Elem& _Ch)
{ //ищите _Ch в [_First, _First + _Count)
return (_Count == 0 ? (const _Elem *) 0
: (const _Elem *)_CSTD memchr(_First, _Ch, _Count));
}
Пожалуйста помочь.

Jochen Arndt

Смотрите мое обновленное решение.

Member 12890589

@Йохен Арндт. Большое вам спасибо за ваш добрый ответ. Я получаю почтовое тело следующим образом.

Чтобы: sampleuser1@hushmail.com
От: sampleuser@hushmail.com
Тема: Анализ

Это всего лишь тестовое сообщение.

Ответ:14%
Б: 89%
С: 124.

Но тема по-прежнему отсутствует. Все содержимое отображается только на теле почты.

Jochen Arndt

Добро пожаловать.

Чего не хватает?
Ваш вышеприведенный вывод выглядит нормально (предмет есть).