I learn how to use C++ for network stuff, so first thing i tried is to send email with Poco C++ library. I used vcpkg to install poco with openssl, and it compiles fine
I take code like example from that question:
Sending HTML code in a mail using Poco library
Where dude could send text, but couldn't send file, so i thought that i could reproduce his result quickly, and send some text too, but it doesn't works at all
It Creates Secure SMTP session, but when i try to open it, program just stops
There's my code:
#include <Poco\Net\AcceptCertificateHandler.h>
#include <Poco\Net\FilePartSource.h>
#include <Poco\Net\InvalidCertificateHandler.h>
#include <Poco\Net\MailMessage.h>
#include <Poco\Net\NetException.h>
#include <Poco\Net\SecureSMTPClientSession.h>
#include <Poco\Net\SSLManager.h>
#include <iostream>
namespace pn = Poco::Net;
struct info
{
std::string sender;
std::string recipient;
std::string password;
std::string host;
int port;
};
void MailSender(info a)
{
Poco::Net::MailMessage mailMessage;
mailMessage.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, a.recipient, "username"));
mailMessage.setSubject("test");
mailMessage.setSender(a.sender);
mailMessage.setContent("Oh yeah!\r\n");
Poco::Net::SecureSMTPClientSession session(a.host, a.port);
std::cout << "> Session created\n";
session.open();
std::cout << "> Session opened\n";
Poco::Net::initializeSSL();
std::cout << "> SSL initialized\n";
Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> ptrHandler = new Poco::Net::AcceptCertificateHandler(false);
Poco::Net::Context::Ptr ptrContext = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", Poco::Net::Context::VERIFY_RELAXED, 9, "ALL:!ADH:!LOW:!EXP:!MD5:#STRENGTH");
Poco::Net::SSLManager::instance().initializeClient(NULL, ptrHandler, ptrContext);
std::cout << "> Client initialized\n";
try
{
session.login();
std::cout << "> 1 login completed\n";
if (session.startTLS(ptrContext))
{
session.login(Poco::Net::SecureSMTPClientSession::AUTH_LOGIN, a.sender, a.password);
std::cout << "> 2 login\n";
session.sendMessage(mailMessage);
std::cout << "> Message sent\n";
}
session.close();
std::cout << "> Session closed\n";
Poco::Net::uninitializeSSL();
}
catch (Poco::Net::SMTPException& e)
{
std::cout << e.message() << std::endl;
session.close();
Poco::Net::uninitializeSSL();
}
};
int main()
{
info a{ "username#yandex.ru" , "username#yandex.ru" , "application_password" , "smtp.yandex.ru" , 465};
/*
*a.sender = "username#yandex.ru";
*a.recipient = "username#yandex.ru";
*a.password = "application_password";
*a.host = "smtp.yandex.ru";
*a.port = 465;
*/
MailSender(a);
}
Yandex provides instruction for their smtp usage:
https://yandex.ru/support/mail/mail-clients/others.html
Mail server address - smtp.yandex.ru
Port - 465
Security - ssl
I tried mail.ru and yandex.ru with the same result - nothing
I tried version without ssl, still nothing
I tried to turn off my antivirus
Related
I am new to c++ and tring to send a mail using gmail smtp. I have done this in python but I am unable to do it in c++. I think I need to add startTLS() but it seems to be not defined. Please help me, I have tried my best. Searched the internet also could not find any thing.
#include <cstdlib>
#include <iostream>
#include <Poco/Net/SMTPClientSession.h>
#include <Poco/Net/MailMessage.h>
#include <string>
using namespace Poco::Net;
using namespace std;
int main(int argc, char** argv)
{
std::string Username = "farhantestingsmtp#gmail.com";
std::string Password = "cpguxktxoyibiybd";
std::string Receiver = "jattfarhan10#gmail.com";
std::string Name = "Jatt Farhan";
std::string Subject = "Hello!";
std::string Content = "TEXT OF THE EMAIL";
try
{
MailMessage msg;
msg.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, Receiver, Name));
msg.setSender(Username);
msg.setSubject(Subject);
msg.setContent(Content);
SMTPClientSession smtp("smtp.gmail.com", 487);
smtp.open();
cout << "Before Login";
smtp.login(SMTPClientSession::AUTH_LOGIN, Username, Password);
cout << "After Login";
smtp.sendMessage(msg);
smtp.close();
std::cerr << "Sent mail successfully!" << std::endl;
}
catch (std::exception& e)
{
std::cerr << "Failed to send mail: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
I have added my mail username and password, as it for testing. Thanks in advance.
I tried to add startTLS and could not do it as The SecureSMTPClientSession was not defined in my VS environment. I also searched the internet, but could not fix it.
Able to send UDP message to a particular IP port using Poco Lib socket communication, But unable to receive the UDP message as it is getting stuck at receiveFrom API of DatagramSocket as in below code.
I am sending message every second and also have to receive acknowledgement every second, for that i have timer , Client and Server Threads running parallelly. The problem here is I am unable to receive the UDP packets which are being captured on wireshark. It is getting stuck at receiveFrom.
Please find below Client Server and main files.
` Server.hpp
#pragma once
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/MulticastSocket.h"
#include "Poco/RunnableAdapter.h"
#include "Poco/Thread.h"
#include <cstring>
#include <iostream>
using namespace std;
using namespace Poco;
using namespace Poco::Net;
struct Server
{
int bufferSize;
SocketAddress sockets;
static bool debugModeEnabled;
Server() :
bufferSize(1024) { //sockets = SocketAddress(10000);
}
Server(const UInt16& port, const int& bufferSize)
{
sockets = SocketAddress(port);
this->bufferSize = bufferSize;
}
void receiveMessages()
{
char buffer[bufferSize];
try
{
Poco::Net::DatagramSocket datagram(sockets);//(socket);
datagram.bind(sockets);
cout << "Server started socket" << endl;
while (!datagram.available())
{
SocketAddress sender;
cout << "Server started socket 2" << endl;
int size = datagram.receiveFrom(buffer, bufferSize, sender);
//int size = datagram.receiveBytes(buffer, bufferSize);
cout << "received bytes size" << size << endl;
buffer[size] = '\0';
//std::string str(buffer);
//cout << (debugModeEnabled ? (sender.toString() + ": ") : "- ") << buffer << endl;
cout << "received: " << size << buffer << endl;
//cout << buffer << "Server adasdasd" << endl;
if (string(buffer) == "\\end")
{
//cerr << "\nUser: " << sender.toString() << " ended connection" << endl;
datagram.close(); // Closes the server
}
}
}
catch (const Poco::Exception& exc)
{
std::cerr << exc.displayText() << std::endl;
}
}
};
bool Server::debugModeEnabled = false;
`
`Client.hpp
#pragma once
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/RunnableAdapter.h"
#include "Poco/Thread.h"
#include <iostream>
#include <string>
using namespace std;
using namespace Poco;
using namespace Poco::Net;
struct Client
{
SocketAddress socket;
string str;
// By default the client connects to itself
Client() { socket = SocketAddress("127.0.0.1", 10000); }
Client(const Poco::Net::IPAddress& IP, const UInt16& port, const string& val) :
str(val)
{
socket = SocketAddress(IP, port);
}
void sendMessages()
{
DatagramSocket datagram;
datagram.connect(socket);
string message = str;
//cout << "sending: " << hex << hexify(message) << endl;
unsigned int bytes_sent = 0;
while (!datagram.available())
{
//getline(cin, message);
//bytes_sent = datagram.sendBytes(message.data(), static_cast<int>(message.size()));
bytes_sent = datagram.sendTo(message.data(), static_cast<int>(message.size()),socket);
cout << "number of bytes sent: " << std::dec << bytes_sent << endl;
if (bytes_sent >= message.size())
{
datagram.close();
}
}
}
string IP() { return socket.host().toString(); }
UInt16 port() { return socket.port(); }
static void sendMessage(const Poco::Net::IPAddress& IP, const UInt16& port, const string& message)
{
SocketAddress socket(IP, port);
DatagramSocket datagram;
datagram.connect(socket);
datagram.sendBytes(message.data(), int(message.size()));
}
};
`
` main.cpp
int bufferSize = 1024;
int exit_status = 0;
Client client(IP, ciPort, str);
Server server(mdilPort, bufferSize);
RunnableAdapter<Client> clientRunnable(client, &Client::sendMessages);
RunnableAdapter<Server> serverRunnable(server, &Server::receiveMessages);
Thread clientThread, serverThread;
// Client::sendMessage(IP, ciPort, "hello!!");
try
{
Timer t = Timer();
t.setInterval([&]() {
cout << "client Tick" << endl;
// pApp->SendIndications();
clientThread.start(clientRunnable);
clientThread.join();
},
1000);
t.setInterval([&]() {
cout<< "server Tick" << endl;
serverThread.start(serverRunnable);
serverThread.join();
},
1000);
t.setTimeout([&]() {
std::cout << "Hey.. After 30s. But I will stop the timer!" << std::endl;
t.stop();
exit(exit_status);
},
30000);
std::cout << "I am Timer" << std::endl;
while (true); // Keep main thread active
}
catch (...)
{
std::cout << "catched exception" << std::endl;
//return -1;
}
`
I tried the conventional Socket Programming API's to receive the UDP packets but there also it is getting stuck at receiveFrom API. also tried running both client and server on different process to make sure there is no issue with the multi threading synchronization, but both the approach didnt help. I am able to capture the response at Wireshark but unable to receive on the application side using Poco Lib socket API's. Also allowed visual studio code through firewall as well
Im using libtins library for sniffing.
The given example http_requests.cpp works for HTTP requests.
to capture https packets i tried using
config.set_filter("tcp port 443");
but didn't work
complete code:
#include <string>
#include <iostream>
#include <stdexcept>
#include <boost/regex.hpp>
#include "tins/tcp_ip/stream_follower.h"
#include "tins/sniffer.h"
using std::string;
using std::cout;
using std::cerr;
using std::endl;
using std::exception;
using boost::regex;
using boost::match_results;
using Tins::PDU;
using Tins::Sniffer;
using Tins::SnifferConfiguration;
using Tins::TCPIP::Stream;
using Tins::TCPIP::StreamFollower;
const size_t MAX_PAYLOAD = 3 * 1024;
regex request_regex("([\\w]+) ([^ ]+).+\r\nHost: ([\\d\\w\\.-]+)\r\n");
regex response_regex("HTTP/[^ ]+ ([\\d]+)");
void on_server_data(Stream& stream) {
match_results<Stream::payload_type::const_iterator> client_match;
match_results<Stream::payload_type::const_iterator> server_match;
const Stream::payload_type& client_payload = stream.client_payload();
const Stream::payload_type& server_payload = stream.server_payload();
bool valid = regex_search(server_payload.begin(), server_payload.end(),
server_match, response_regex) &&
regex_search(client_payload.begin(), client_payload.end(),
client_match, request_regex);
if (valid) {
// Extract all fields
string method = string(client_match[1].first, client_match[1].second);
string url = string(client_match[2].first, client_match[2].second);
string host = string(client_match[3].first, client_match[3].second);
string response_code = string(server_match[1].first, server_match[1].second);
// Now print them
cout << method << " http://" << host << url << " -> " << response_code << endl;
// Once we've seen the first request on this stream, ignore it
stream.ignore_client_data();
stream.ignore_server_data();
}
// Just in case the server returns invalid data, stop at 3kb
if (stream.server_payload().size() > MAX_PAYLOAD) {
stream.ignore_server_data();
}
}
void on_client_data(Stream& stream) {
// Don't hold more than 3kb of data from the client's flow
if (stream.client_payload().size() > MAX_PAYLOAD) {
stream.ignore_client_data();
}
}
void on_new_connection(Stream& stream) {
stream.client_data_callback(&on_client_data);
stream.server_data_callback(&on_server_data);
stream.auto_cleanup_payloads(false);
}
int main(int argc, char* argv[]) {
if (argc != 2) {
cout << "Usage: " << argv[0] << " <interface>" << endl;
return 1;
}
try {
SnifferConfiguration config;
config.set_immediate_mode(true);
// Only capture TCP traffic sent from/to port 80
config.set_filter("tcp port 443");
// Construct the sniffer we'll use
Sniffer sniffer(argv[1], config);
cout << "Starting capture on interface " << argv[1] << endl;
// Now construct the stream follower
StreamFollower follower;
follower.new_stream_callback(&on_new_connection);
sniffer.sniff_loop([&](PDU& packet) {
follower.process_packet(packet);
return true;
});
}
catch (exception& ex) {
cerr << "Error: " << ex.what() << endl;
return 1;
}
}
how do i configure it to work for https protocol?
Just changing the port won't actually help.
While it will grab the packets it won't be able to do anything with them as they will be encrypted so none of the regexps will match.
Unless you have access to the private key from the server to decrypt the content then this code will never work.
I've been unable to connect to Watson's Text-To-Speech service via websockets in C++ using the Boost Beast library
I've got code that successfully interfaces with echo.websocket.org on port 80, but it does not work with Watson's url. I've tried using variants of protocols (http(s), ws(s), and unspecified (which works for echo.websocket.com)) and I've tried both port 80 and 443, just to be sure.
I was able to get successful code running in Javascript, and using Firefox's inbuilt networking tool, I've verified it works over port 443. Using the exact same URL and port number gives me the following: "No such host is known."
Here is the relevant JS code that correctly establishes connection
var completeUrl = "wss://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?access_token=" + accessToken + "&voice=en-US_AllisonVoice";
socket = new WebSocket(completeUrl);
The following C++ code works fine in theory, and works with echo.websocket.org on port 80, but not Watson.
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
namespace websocket = boost::beast::websocket; // from <boost/beast/websocket.hpp>
// Sends a WebSocket message and prints the response
int main(int argc, char** argv)
{
try
{
std::string accessToken = "XXXXX";
auto const text = "The quick brown fox jumps over the lazy dog.";
std::string baseURL = "wss://stream.watsonplatform.net/text-to-speech/api/v1/synthesize";
std::string voiceModel = "en-US_AllisonVoice";
auto const port = "443"; // port 80 for echo.websocket.org
// port 443 for watson
std::string const host = baseURL + "?access_token=" + accessToken + "&voice=" + voiceModel;
//std::string const host = "echo.websocket.org";
boost::asio::io_context ioc;
tcp::resolver resolver{ ioc };
websocket::stream<tcp::socket> ws{ ioc };
auto const results = resolver.resolve(host, port); // Problem line - "resolve: No such host is known"
std::cout << "Host resolved" << std::endl;
boost::asio::connect(ws.next_layer(), results.begin(), results.end());
ws.handshake(host, "/");
std::cout << "Connection established" << std::endl << "------------------------------" << std::endl;
ws.write(boost::asio::buffer(std::string(text)));
std::cout << "Client request: " << text << std::endl;
boost::beast::multi_buffer buffer;
ws.read(buffer);
ws.close(websocket::close_code::normal);
std::cout << "Server response: " << boost::beast::buffers(buffer.data()) << std::endl;
}
catch (std::exception const& e)
{
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
If the Watson URL was wrong, it shouldn't work in Javascript. If the C++ code was wrong, it shouldn't work with echo.websocket.org. So I have no idea what the issue is.
The baseURL in your code specifies "wss" which means Secure Websockets (SSL). But your stream is delcared as a plain stream. If you want to connect to secure websocket servers, you should base your code on the websocket-client-ssl example instead:
https://github.com/boostorg/beast/blob/d43d9421a40c0251614bc45ea6dcf921a3dbaf37/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp#L64
I'm trying to create a simple MQTT client for my home application and I'm using libmosquittopp (which is C++ version of libmosquitto).
There is not much of a documentation for this library, but I found 2 examples (here and here) that helped me to create a code for my "MQTTWrapper" class.
Here's my code:
MQTTWrapper.h :
#pragma once
#include <mosquittopp.h>
#include <string>
class MQTTWrapper : public mosqpp::mosquittopp
{
public:
MQTTWrapper(const char* id, const char* host_, int port_);
virtual ~MQTTWrapper();
void myPublish(std::string topic, std::string value);
private:
void on_connect(int rc);
void on_publish(int mid);
std::string host;
int port;
};
MQTTWrapper.cpp
#include "MQTTWrapper.h"
#include <iostream>
MQTTWrapper::MQTTWrapper(const char* id, const char* host_, int port_) :
mosquittopp(id), host(host_), port(port_)
{
mosqpp::lib_init();
int keepalive = 10;
if (username_pw_set("sampleuser", "samplepass") != MOSQ_ERR_SUCCESS) {
std::cout << "setting passwd failed" << std::endl;
}
connect_async(host.c_str(), port, keepalive);
if (loop_start() != MOSQ_ERR_SUCCESS) {
std::cout << "loop_start failed" << std::endl;
}
}
MQTTWrapper::~MQTTWrapper()
{
std::cout << "1" << std::endl;
if (loop_stop() != MOSQ_ERR_SUCCESS) {
std::cout << "loop_stop failed" << std::endl;
}
std::cout << "2" << std::endl;
mosqpp::lib_cleanup();
std::cout << "3" << std::endl;
}
void MQTTWrapper::on_connect(int rc)
{
std::cout << "Connected with code " << rc << "." << std::endl;
}
void MQTTWrapper::myPublish(std::string topic, std::string value) {
int ret = publish(NULL, topic.c_str(), value.size(), value.c_str(), 1, false);
if (ret != MOSQ_ERR_SUCCESS) {
std::cout << "Sending failed." << std::endl;
}
}
void MQTTWrapper::on_publish(int mid) {
std::cout << "Published message with id: " << mid << std::endl;
}
and my main():
#include <iostream>
#include <string>
#include "MQTTWrapper.h"
int main(int argc, char *argv[])
{
MQTTWrapper* mqtt;
mqtt = new MQTTWrapper("Lewiatan IoT", "my.cloudmqtt.host", 12345);
std::string value("Test123");
mqtt->myPublish("sensors/temp", value);
std::cout << "about to delete mqtt" << std::endl;
delete mqtt;
std::cout << "mqtt deleted" << std::endl;
return 0;
}
Sorry for so much code.
My problem is that when I compile it and execute - my application hangs infinitely (I only waited 9 minutes) in MQTTWrapper destructor on loop_stop() method.
Tested with libmosquittopp 1.4.8 (debian package) and then after removing it- with version 1.4.9 from github.
loop_start() and loop_stop(bool force=false) should start/stop a separate thread that handles messaging.
I have tested it with forced stop (loop_stop(true)) but this way my application stops and does not publish any data. loop_stop() on the other hand publishes the data but then halts.
console output (make && ./executable):
g++ -c MQTTWrapper.cpp
g++ -c main.cpp
g++ -o executable main.o MQTTWrapper.o -lmosquittopp
about to delete mqtt
1
Connected with code 0.
Published message with id: 1
(here it hangs infinitely...)
My question:
Why this loop_stop() hangs and how to fix it?
(any documentation/tutorial/example appreciated)
Try call disconnect() before loop_stop(). You should also bear in mind that you're effectively doing this:
connect_async();
loop_start();
loop_stop();
The client may not even have had chance to connect, nor the thread actually be started before you tell it to stop.
It's worth considering running actions in the callbacks:
on_connect -> call publish
on_publish -> call disconnect