Допустим, нам понадобилось отправлять 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:
1 2 3 4 5 6 |
curl -s --user 'api:key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \ https://api.mailgun.net/v3/sandboxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.mailgun.org/messages \ -F subject='Hello Mikhail' \ -F text='Congratulations Mikhail, you just sent an email with Mailgun! You are truly awesome!' |
Таким образом, нам достаточно реализовать эквивалент этого POST-запроса в коде Qt-приложения.
Реализация
Заголовочный файл mainwidget.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#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 ); } |
Интерес представляет следующий фрагмент:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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), в котором говорится об успехе операции. Буквально сразу же на ваш адрес электронной почты поступит новое сообщение с указанной темой и содержимым.