Хобрук: Ваш путь к мастерству в программировании

Поля заголовка C++ libcurl IMAP для выборки

Я использую libcurl с IMAP для получения сообщений из почтового ящика. Я могу получить сообщения полностью, но не могу получить поле заголовка; моя функция записи для завитка возвращает только первую строку.

Вот мой код:

std::string fetchdata;

size_t write_data(char* buf, size_t size, size_t nmemb, void* up) {
    fetchdata.append((char*)buf, size*nmemb);
    return size*nmemb;
}

int fetchmail() {
    CURL *curl;
    CURLcode res = CURLE_OK;

    curl = curl_easy_init();
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_USERNAME, "[email protected]");
        curl_easy_setopt(curl, CURLOPT_PASSWORD, "mypassword");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/INBOX");
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "UID FETCH 10 BODY[HEADER.FIELDS (To)]");

        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);
    }

    std::ofstream outfile("C:\\Path\\fetched.txt", std::ios_base::app);
    outfile << fetchdata;
    outfile.close();

    return (int)res;
}

Запуск fetchmail выходов

* 3 FETCH (UID 10 BODY[HEADER.FIELDS (To)] {29}

в извлеченном.txt. Однако это только первая строка; вывод консоли

* 3 FETCH (UID 10 BODY[HEADER.FIELDS (To)] {29}
To: [email protected]

)
A004 OK Success

Если я изменю write_data() на

size_t write_data(char* buf, size_t size, size_t nmemb, void* up) {
    fetchdata.append((char*)buf, size*nmemb);
    std::cout << buf;
    return size*nmemb;
}

он выводит

* 3 FETCH (UID 10 BODY[HEADER.FIELDS (To)] {29
To: [email protected]

)
A004 OK Success
ted. (Success)
 (Success)
 (Success)
WRITE] INBOX selected. (Success)
[UIDNEXT 12] Predicted next UID.
* OK [HIGHESTMODSEQ 1759]
A003 OK [READ-WRITE] INBOX selected. (Success)
* OK [HIGHESTMODSEQ 1759]
A003 OK [READ-WRITE] INBOX selected. (Success)

Это проблема с моим write_data()? buf, похоже, владеет всей информацией.

24.11.2014

  • Параметр buf в функции write_data() не завершается нулем, но cout << buf; требует этого. Вы печатаете содержимое окружающей памяти. Буфер - это просто необработанные байты, поэтому вам предоставляется размер буфера в качестве другого параметра. 25.11.2014
  • Вы могли бы или могли бы вместо этого использовать временный std::string: cout << string(buf, size*nmemb); 25.11.2014
  • Но буфер содержит то, что мне нужно, кажется, что write_data() передан неправильный размер? 25.11.2014
  • @RemyLebeau Мне нужны вещи после первой строки, но не все. 25.11.2014
  • Поскольку вы используете CURLOPT_CUSTOMREQUEST, у curl нет другого выбора, кроме как предоставить вам весь ответ сервера, поскольку у него нет контекста, чтобы узнать, что такое запрос или как обработать ответ для вас. Вам придется проанализировать ответ самостоятельно, если вы хотите извлечь из него меньшие части. 25.11.2014
  • @RemyLebeau Есть ли другой способ отдавать команды IMAP? И весь ли buf вывод серверов? 25.11.2014
  • Возможно, вы захотите просмотреть документацию и примеры curl, в частности параметры UID и SECTION URL-адреса IMAP, например: curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/INBOX/;UID=10/;SECTION=HEADER.FIELDS%20(To)");. Это создаст соответствующий FETCH без необходимости использовать CURLOPT_CUSTOMREQUEST. Прочтите RFC 5092, чтобы узнать полный синтаксис URL-адреса IMAP. 25.11.2014
  • А curl предоставит столько буферов, сколько нужно, чтобы дать вам полный ответ. Это может дать вам 1, это может дать вам много, это зависит от размера ответа и того, как curl его читает. 25.11.2014
  • @RemyLebeau Спасибо! Я приму, если вы опубликуете ответ. 25.11.2014

Ответы:


1

Параметр buf в функции write_data() не завершается нулем, но для вызова cout << buf требуется завершающий нуль, поскольку buf является указателем char*. Таким образом, вы печатаете содержимое окружающей памяти. Данные buf представляют собой просто необработанные байты, поэтому в качестве другого параметра указывается размер буфера. При печати buf вы должны учитывать этот размер, например:

std::cout << std::string(buf, size*nmemb);

В качестве альтернативы:

std::cout.write(buf, size*nmemb);

Поскольку вы используете CURLOPT_CUSTOMREQUEST, curl отправляет запрос как есть и возвращает вам ответ сервера как есть. В этой ситуации у curl нет контекста, чтобы узнать, что такое запрос или как обработать ответ для вас. Вам придется проанализировать ответ самостоятельно, если вы хотите извлечь из него меньшие части.

Возможно, вы захотите просмотреть документацию и примеры curl, в частности использовать параметры UID и SECTION URL-адреса IMAP (Читать RFC 5092 для полного синтаксиса), например:

curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/INBOX/;uid=10/;section=HEADER.FIELDS%20(To)");

Это позволит curl сгенерировать свой собственный запрос FETCH без необходимости прибегать к использованию CURLOPT_CUSTOMREQUEST вручную. Поскольку curl создает запрос FETCH, он с большей вероятностью проанализирует ответ за вас, предоставив только запрошенные данные заголовка вашей функции write_data(), поэтому ей меньше придется анализировать/удалять вручную.

25.11.2014
  • Просто чтобы другие не спотыкались об это: curl интерпретирует параметр ;uid=XXX как номер сообщения, а не UID IMAP в соответствии со спецификацией. IOW, вариант URL выдаст простую FETCH, а не UID FETCH. 30.03.2016
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..