halt while sending email with Poco Net - c++

I'm trying to send an email using the Poco Net library with this code (my credentials are arbitrary obviously):
void send_email() {
// Poco::Net::SMTPClientSession session("localhost", 465);
const std::string& smtp_host {"mail.example.com"};
const std::string& smtp_user {"marinos#example.com"};
const std::string& smtp_passwd {"myPassword"};
std::string to = "marinos#example.com";
std::string from = "marinos#example.com";
std::string subject = "Your first e-mail message sent using Poco Libraries";
subject = Poco::Net::MailMessage::encodeWord(subject, "UTF-8");
std::string content = "Well done! You've successfully sent your first message using Poco SMTPClientSession";
Poco::Net::MailMessage message;
message.setSender(from);
message.addRecipient(Poco::Net::MailRecipient{Poco::Net::MailRecipient::PRIMARY_RECIPIENT, to});
message.setSubject(subject);
message.setContentType("text/plain; charset=UTF-8");
message.setContent(content, Poco::Net::MailMessage::ENCODING_8BIT);
try {
Poco::Net::SMTPClientSession session(smtp_host, 465);
session.open(); // this is where it halts
try {
session.login(Poco::Net::SMTPClientSession::AUTH_LOGIN, smtp_user, smtp_passwd);
session.sendMessage(message);
std::cout << "Message successfully sent" << std::endl;
session.close();
} catch (Poco::Net::SMTPException& e) {
std::cerr << e.displayText() << std::endl;
session.close();
}
} catch (Poco::Net::NetException& e) {
std::cerr << e.displayText() << std::endl;
}
}
and my program simply halts. I've used a debugger to locate the problem and it seems that the program halts when calling session.open(). Am I doing something wrong here?

Since I do not know specification of your SMTP server, I am speculating that you're probably suppose to use SMTPS instead of plain SMTP, because port 465 is default port for SMTPS (according to Wikipedia). I guess the program halts during SSL handshaking. By looking into Poco documentation I see that there exists SSL version of the Poco::Net::SMTPClientSession. Thus, you should try with SecureSMTPClientSession. Check if your mail server requires START_TLS, in that case I guess you should additionally call bool startTLS().

Related

Use coinbase pro websockets with cpprestsdk

I want to receive updates from websockets defined in the coinbase pro API.
For example I'd like to register the heartbeat channel, that should be received once per second according to documentation.
I've tried to register to the web socket, but I obtain only the subscriptions message in reply:
{"type":"subscriptions","channels":[{"name":"heartbeat","product_ids":["ETH-EUR"]}]}
After that I'm not receiving anything anymore. What should I do in order to listen to the messages of the client
This is the piece of code involved (modified a bit, it's in a class, m_webSocket is a class member that should be used also elsewhere, and it should be closed in the destructor):
void EndpointClient::connectToWebSockets() {
constexpr auto WebSocketFeed{ U("wss://ws-feed.pro.coinbase.com") };
constexpr auto RequestStatus{ "{\"type\": \"subscribe\", \"channels\" : [{ \"name\": \"heartbeat\", \"product_ids\" : [\"ETH-EUR\"] }]}" };
web::websockets::client::websocket_client m_webSocket;
try {
m_webSocket.connect(WebSocketFeed).wait();
auto receivedTast = m_webSocket.receive().then([this](websocket_incoming_message ret_msg) {
auto s = ret_msg.extract_string();
m_logger->info("s = " + s.get());
});
websocket_outgoing_message msg;
msg.set_utf8_message(RequestStatus);
m_webSocket.send(msg).wait();
receivedTast.wait();
m_webSocket.close().wait();
}
catch (websocket_exception& e) {
m_logger->error("coinbase: exception when setting websocket: " + string{ e.what() });
}
catch (std::exception& e) {
m_logger->error("coinbase: exception when setting websocket: " + string{ e.what() });
}
}
The .receive() method only gets one message. If you want to receive more incoming messages, you need to run it in a loop. Or you can use a websocket_callback_client instead so that it can listen automatically (websocket_callback_client.set_message_handler() method).

curlpp response is doubled

I'm just new to curlpp but I can't see what's wrong here with my code, so I hope someone can help me out.
I'm using curlpp in C++ to make Facebook Graph queries. That means the Facebook server will return Json data as result.
My code looks as follows:
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>
...
curlpp::Easy myRequest;
bool error = false;
QString result = "";
try {
// Setting the URL to the Facebook server with the query
curlpp::options::Url myUrl(request->getURL().toStdString());
// Creating stream for the result
std::ostringstream os;
curlpp::options::WriteStream ws(&os);
// setting my opts: url and output stream
myRequest.setOpt(myUrl);
myRequest.setOpt(ws);
// perform the request
myRequest.perform();
// stream the result into my stream
os << myRequest;
result = QString::fromStdString(os.str());
} catch (curlpp::RuntimeError &e) {
error = true;
qWarning() << "Error in HttpRequest execution:" << e.what();
} catch (curlpp::LogicError &e) {
error = true;
qWarning() << "Error in HttpRequest execution:" << e.what();
} catch (...) {
error = true;
qWarning() << "Unknown error in HttpRequest execution.";
}
My problem now is that the resulting stream (and thus my result QString) do contain the Json object sent by the Facebook Graph server, but twice.
That means, directly two times the same object, one after the other. And that makes it invalid Json.
But that can not be what the server delivers. And it's not what I get when I do check it with the openssl command line tool and make a HTTP Get request on my own.
What's wrong with my code?
Best, Michael

POCO json POST_METHOD returns results but gives I/O exception and ends program

Hi im havng a problem with poco under linux, im making a https json post to a webserver and im getting the response as i expected.
The problem is that i get an error after the response is printed and it ends the execution of my program.
Here is what i get on console:
200 OK
"{\"test_results\": ["result1", "result2", "result3", "result4"]}"
terminate called after throwing an instance of 'Poco::IOException' what(): I/O error
Here is the code that make the above result to be printed:
int posTry(){
try
{
// prepare session
Poco::Net::Context::Ptr context = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "", Poco::Net::Context::VERIFY_NONE, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:#STRENGTH");
Poco::URI uri("https://someURL/somePATH");
Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort(), context);
// prepare path
std::string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
// send request
std::string test = "{Some json code to get results that is already working}";
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_POST, path, Poco::Net::HTTPMessage::HTTP_1_1);
req.setContentType("application/json");
req.setKeepAlive(true);
req.setContentLength( test.length() );
session.sendRequest(req) << test;
// get response
Poco::Net::HTTPResponse res;
std::cout << res.getStatus() << " " << res.getReason() << std::endl;
// print response
std::istream &is = session.receiveResponse(res);
Poco::StreamCopier::copyStream(is, std::cout);
std::vector<Poco::Net::HTTPCookie> cookies;
res.getCookies( cookies );
}
catch( const Poco::Exception& e )
{
std::cerr << e.displayText() << std::endl;
}
catch (...)
{
std::cout << "error";
return -1;
}
return 0;
}
I don't know what is this error about and I can't even catch the error in (...) and make the program continue. Can someone help me?
The exception comes from the destructor of Poco::Net::HTTPSClientSession,
This is a known bug fixed in POCO release 1.4.2.
source: http://pocoproject.org/docs/99100-ReleaseNotes.html
If you cannot upgrade, you should be able to get rid of the exception by adding a specific catch for it.

QuickFix error: 58=Conditionally Required Field Missing (268)

This is the server config file
[DEFAULT]
ConnectionType=acceptor
SocketAcceptPort=5001
SocketReuseAddress=Y
StartTime=00:00:00
EndTime=00:00:00
FileLogPath=log
FileStorePath=store
[SESSION]
BeginString=FIX.4.4
SenderCompID=EXECUTOR
TargetCompID=CLIENT1
DataDictionary=/home/idf/Documents/quickfixspec/spec/FIX44.xml
I have a FIXServer and FIXClient quickfix application. The client on connection immediately shows:
IN: 8=FIX.4.4|9=197|35=X|34=34|49=EXECUTOR|52=20141114-19:12:07.219|56=CLIENT1|55=bond3|110=0|268=1|269=0|270=100.272681729868|271=0|278=1862140492|279=0|6350=0|6351=0|6360=0.0528078713919967|6361=0.00698885442689061|10=158
OUT: 8=FIX.4.4|9=123|35=j|34=45|49=CLIENT1|52=20141114-19:12:07.220|56=EXECUTOR|45=34|58=Conditionally Required Field Missing(268)|372=X|380=5|10=139
The server shows:
IN: 8=FIX.4.4|9=123|35=j|34=46|49=CLIENT1|52=20141114-19:12:12.220|56=EXECUTOR|45=35|58=Conditionally Required Field Missing (268)|372=X|380=5|10=137
OUT: 8=FIX.4.4|9=193|35=X|34=36|49=EXECUTOR|52=20141114-19:12:17.221|56=CLIENT1|268=1|279=0|269=0|278=500257692|55=bond|5270=99.54393400065|6271=0|110=0|6350=0|6351=0|6360=0.0107738308608532|6361=0.047250702092424|10=154
I looked this up on http://www.fixtradingcommunity.org/FIXimate/FIXimate3.0/ and it is "Number of entries in Market Data message."
It looks like the server is sending Marketdata and not specifying the number of NoMDEntries? It is a bit strange, because for the Java version anyway, it appears this field gets set automatically, e.g., http://www.quickfixj.org/quickfixj/usermanual/1.5.3/usage/repeating_groups.html
This is the line that causes the problem in the client as it is getting MarketData from the server. I added the try catch block so I could see the exception myself, but it gives less information than if I let QF handle the exception and sending it back to the server through [OUT:]
void MyApplication::fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType )
{
std::cout << std::endl << "IN: " << message << std::endl;
try
{
crack( message, sessionID );
}
catch(std::exception& ex)
{
//I suppose I could comment out FIX::FieldNotFound above in the throw clause and ignore this exception
/// here since it seems that the thing is plain wrong since the field IS there!!??
std::cout << "crack exception: " << ex.what() << "\n";
}
}

Poco stops after SMTPClientSession.login

I just started with the Poco library and tried to create an email program (Which I knew virtually nothing about). The following is my code (There may be other problems with it besides the one I've encountered so far, but I just started working on it)
int main(int argc, char** argv)
{
Poco::Net::SocketAddress add("smtp.gmail.com:465");
Poco::Net::StreamSocket sock(add);
Poco::Net::SMTPClientSession sess(sock);
std::cout << "-";
sess.login(
"gmail.com",
Poco::Net::SMTPClientSession::AUTH_LOGIN,
"----",
"----"
);
Poco::Net::MailMessage msg;
Poco::Net::MailRecipient resp(Poco::Net::MailRecipient::PRIMARY_RECIPIENT,"michaelrgoldfine#gmail.com");
msg.addRecipient(resp);
std::string content("HELP SOS");
msg.encodeWord(content);
std::cout << msg.getContent() << "-";
}
When I go into the debugger, it runs fine until it gets to sess.login then suddenly the little bar that represents were I am in the code disappears but the program keeps running (I'm not experienced enough to know what that means). None of the cout stuff I put in actually prints, the debugger just goes past that line but nothing shows up. After a little while this comes up:
terminate called throwing an exception
So what's going on?
You are attempting to use SMTP over TLS (the port 465 passed to the SocketAddress). In one shot you have to learn (1) TLS and certificate handling in POCO, before focusing on (2) your goal: sending an email message.
I suggest to start learning POCO with simpler examples. You can find sample code in the various samples directories in the POCO source code.
I think that your code is just hanging on the TLS handshake, because it doesn't know what to do.
These are the fixes you should do before looking at the solution:
Place your code inside a try/catch block. POCO uses exceptions.
Replace StreamSocket with SecureStreamSocket.
The simplest way to properly initialize SecureStreamSocket is via the Application class. See the Applications slides and Util/samples/SampleApp/src/SampleApp.cpp.
See the documentation for the SSLManager for how to properly tell the Application which certificates to use.
Don't specify an hostname to the login() method. The hostname is optional and should be the client hostname, not the server (See the SMTP RFC).
Remember to actually send the message! Your code is not sending it :-)
OK, and now for the running code. I left steps 4 and 6 as an exercise, but this code will at least run the TLS handshake, will tell you that it cannot verify the server's certificate and, if you answer Yes on the terminal to the questions on the certificates, it will fail the SMTP authentication.
class MiniApp : public Poco::Util::Application {
int main(const vector <string>& args) {
try {
Poco::Net::SocketAddress add("smtp.gmail.com:465");
Poco::Net::SecureStreamSocket sock(add);
Poco::Net::SMTPClientSession session(sock);
session.login(Poco::Net::SMTPClientSession::AUTH_LOGIN, "user", "pw");
Poco::Net::MailMessage msg;
Poco::Net::MailRecipient recipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT,
"michaelrgoldfine#gmail.com");
msg.addRecipient(recipient);
string content("HELP SOS");
msg.encodeWord(content);
} catch (Poco::Exception& e) {
cout << "Error: " << e.displayText() << endl;
return -1;
}
return 0;
}
};
POCO_APP_MAIN(MiniApp)
Yes, so I struggled with login(), trying to use smtp.gmail.com. This is the excerpt of the communication with the SSL session that made it work.
string host("smtp.gmail.com")
Poco::UInt16 port = 587;
SecureSMTPClientSession session(host, port);
session.open();
Poco::Net::initializeSSL();
SharedPtr<InvalidCertificateHandler> ptrHandler = new AcceptCertificateHandler(false);
Context::Ptr ptrContext = new Context(Context::CLIENT_USE, "", "", "", Context::VERIFY_RELAXED, 9, true, "ALL:!ADH:!LOW:!EXP:!MD5:#STRENGTH");
SSLManager::instance().initializeClient(0, ptrHandler, ptrContext);
try
{
// SSL
session.login();
if (session.startTLS(ptrContext))
{
session.login(SMTPClientSession::AUTH_LOGIN, "user#gmail.com", "yourpassword");
session.sendMessage(message);
}
session.close();
Poco::Net::uninitializeSSL();
}
catch (SMTPException &e)
{
cout << e.message() << endl;
session.close();
Poco::Net::uninitializeSSL();
return 0;
}
Original source:
http://www.axistasoft.sg/tutorials/cpp/poco/item/sending-email-messages-using-smtp-protocol