Допустим, нам понадобилось отправлять 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
:
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 все хорошо.