Допустим, нам понадобилось отправлять Email-сообщения из Qt-приложения. Одним из наиболее простых способов является использование стороннего сервиса, основанного на REST API. Без умения отправки POST-запросов не обойтись. В этом нам поможет QNetworkAccessManager.
В качестве сервиса Email-рассылки выберем Mailgun. Для простейшей демонстрации нам вполне хватит его режима Sandbox. Для этого необходимо пройти базовую регистрацию и подтвердить регистрационный Email.
Чтобы полноценно пользоваться Mailgun, требуется подтверждение по смс и регистрация домена, поэтому ограничимся демо-режимом сервиса, который бесплатно позволяет отправлять Email-сообщения на наш собственный адрес (указанный при регистрации).
От Mailgun нас интересует три параметра:
API-ключ вида key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;URL сервиса вида https://api.mailgun.net/v3/sandboxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.mailgun.org/messages;Sandbox-отправитель вида Mailgun Sandbox <postmaster@sandboxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.mailgun.org> для заполнения пункта от.На сайте Mailgun приводится пример вызова сервиса с помощью curl:
Смотрите http://kra43.cc kRA43.CC. Kra44.cC еще на сайте.
curl -s --user 'api:key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
https://api.mailgun.net/v3/sandboxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.mailgun.org/messages \
-F from='Mailgun Sandbox <postmaster@sandboxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.mailgun.org>' \
-F to='Mikhail <xxxxxxxxxxxxxxx@gmail.com>' \
-F subject='Hello Mikhail' \
-F text='Congratulations Mikhail, you just sent an email with Mailgun! You are truly awesome!'
Таким образом, нам достаточно реализовать эквивалент этого POST-запроса в коде Qt-приложения. Должно получиться что-то подобное:

Заголовочный файл mainwidget.h:
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QSettings>
class QNetworkReply;
class QNetworkAccessManager;
namespace Ui {
class MainWidget;
}
class MainWidget : public QWidget {
Q_OBJECT
public:
explicit MainWidget( QWidget* parent = 0 );
~MainWidget();
private slots:
void onSend();
void onResponse( QNetworkReply* reply );
private:
Ui::MainWidget* ui;
QNetworkAccessManager* m_manager;
QSettings m_settings;
};
#endif // MAINWIDGET_H
Здесь мы заготовили два слота: onSend() для обработки нажатия на кнопку отправки; и onResponse() для принятия ответа сервера (ответ в текстовом виде мы просто выведем в диалоговом окне). Также мы объявили поля m_manager и m_settings. Первое поле будет отвечать за всю работу по сетевому взаимодействию, а второе поможет сохранять ключевые параметры сервиса, чтобы их не пришлось вводить заново при каждом запуске программы.
Содержимое файла mainwidget.cpp:
#include "mainwidget.h"
#include "ui_mainwidget.h"
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QSettings>
#include <QMessageBox>
static const QString SETTINGS_FILE_NAME = "config.ini";
MainWidget::MainWidget( QWidget* parent ) :
QWidget( parent ),
ui( new Ui::MainWidget ),
m_manager( new QNetworkAccessManager( this ) ),
m_settings( SETTINGS_FILE_NAME, QSettings::IniFormat ) {
ui->setupUi( this );
ui->edURL->setText( m_settings.value( "endpoint_url", "" ).toString() );
ui->edKey->setText( m_settings.value( "key", "" ).toString() );
ui->edFrom->setText( m_settings.value( "from", "" ).toString() );
ui->edTo->setText( m_settings.value( "to", "" ).toString() );
connect( ui->bnSend, SIGNAL( clicked( bool ) ), SLOT( onSend() ) );
connect( m_manager, SIGNAL( finished( QNetworkReply* ) ), SLOT( onResponse( QNetworkReply* ) ) );
}
MainWidget::~MainWidget() {
delete ui;
}
void MainWidget::onSend() {
QUrl url( ui->edURL->text() );
QNetworkRequest request( url );
QString auth = QString( "%1:%2" ).arg( "api" ).arg( ui->edKey->text() );
request.setRawHeader( "Authorization", "Basic " + auth.toLatin1().toBase64() );
request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
QUrl params;
params.addQueryItem( "from", ui->edFrom->text() );
params.addQueryItem( "to", ui->edTo->text() );
params.addQueryItem( "subject", ui->edSubject->text() );
params.addQueryItem( "text", ui->txtMessage->toPlainText() );
m_settings.setValue( "endpoint_url", ui->edURL->text() );
m_settings.setValue( "key", ui->edKey->text() );
m_settings.setValue( "from", ui->edFrom->text() );
m_settings.setValue( "to", ui->edTo->text() );
m_manager->post( request, params.encodedQuery() );
}
void MainWidget::onResponse( QNetworkReply* reply ) {
QMessageBox::information(
this,
trUtf8( "Ответ сервера" ),
reply->readAll(),
QMessageBox::Ok
);
}
Интерес представляет следующий фрагмент:
QUrl url( ui->edURL->text() );
QNetworkRequest request( url );
QString auth = QString( "%1:%2" ).arg( "api" ).arg( ui->edKey->text() );
request.setRawHeader( "Authorization", "Basic " + auth.toLatin1().toBase64() );
request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
QUrl params;
params.addQueryItem( "from", ui->edFrom->text() );
params.addQueryItem( "to", ui->edTo->text() );
params.addQueryItem( "subject", ui->edSubject->text() );
params.addQueryItem( "text", ui->txtMessage->toPlainText() );
m_manager->post( request, params.encodedQuery() );
Для инициализации запроса мы заполняем URL сервиса, данные авторизации (обратите внимание, что они кодируются в base64) и тип содержимого. Далее заполняются входные параметры сервиса from, to, subject и text. Окончательно, m_manager отправляет все это на сервер с помощью вызова post().
Теперь достаточно заполнить все поля и нажать кнопку Отправить. Если все сделано правильно, то вы увидите диалоговое окно с ответом сервиса (в формате JSON), в котором говорится об успехе операции. Буквально сразу же на ваш адрес электронной почты поступит новое сообщение с указанной темой и содержимым.
Скачать пример работы с QNetworkAccessManager в Qt
Вероятно, зависит от конкретной сборки и версии Qt. Не помню, чтобы у меня были проблемы с запуском примера в представленном виде.
Anonymous
У вас разве не возникло проблем с https? У меня например ругается что нету каких то ssl функций. С обычным http все хорошо.