I'm interested in sending emails with c++ code.
So far I've tried using the jwsmtp library at jwsmtplib and I haven't had any real success. Any suggestions? Below is my code:
//code:
#include <iostream>
#include <jwsmtp/jwsmtp.h>
using std::cout;
using std::endl;
int main( ) {
std::vector<char> vec;
std::string mess("Foo\nBar");
for(std::string::size_type i = 0; i < mess.length( ); ++i)
vec.push_back(mess[i]);
jwsmtp::mailer mail("me#gmail.com", // who the mail is too
"sme#gmail.com", // who the mail is from
"There is always room for FooBar", // subject for the email
vec, // content of the message
"smtp.gmail.com", // the smtp server to mail to
465, //jwsmtp::mailer::SMTP_PORT, // default smtp port (25)
false); // do not query MX records
mail.username("me#gmail.com");
mail.password("mepassword");
//mail.authtype(jwsmtp::mailer::PLAIN);
mail.send();
return 0;
}
I'm definitely open to other libraries or classes, but I'm constraint with OS X.
I've also download the POCO library as I've seen it mentioned in other threads, but I would prefer to have a flatter learning curve. If anyone has example code with POCO I would appreciate getting a look.
Thanks
Check out the VMime library!
Related
I'm adapting a tcp PubSub example to using inproc with multithread. It ends up hanging forever.
My setup
macOS Mojave, Xcode 10.3
zmq 4.3.2
The source code reeproducing the issue:
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <thread>
#include "zmq.h"
void hello_pubsub_inproc() {
void* context = zmq_ctx_new();
void* publisher = zmq_socket(context, ZMQ_PUB);
printf("Starting server...\n");
int pub_conn = zmq_bind(publisher, "inproc://*:4040");
void* subscriber = zmq_socket(context, ZMQ_SUB);
printf("Collecting stock information from the server.\n");
int sub_conn = zmq_connect(subscriber, "inproc://localhost:4040");
sub_conn = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, 0, 0);
std::thread t_pub = std::thread([&]{
const char* companies[2] = {"Company1", "Company2"};
int count = 0;
for(;;) {
int which_company = count % 2;
int index = (int)strlen(companies[0]);
char update[12];
snprintf(update, sizeof update, "%s",
companies[which_company]);
zmq_msg_t message;
zmq_msg_init_size(&message, index);
memcpy(zmq_msg_data(&message), update, index);
zmq_msg_send(&message, publisher, 0);
zmq_msg_close(&message);
count++;
}
});
std::thread t_sub = std::thread([&]{
int i;
for(i = 0; i < 10; i++) {
zmq_msg_t reply;
zmq_msg_init(&reply);
zmq_msg_recv(&reply, subscriber, 0);
int length = (int)zmq_msg_size(&reply);
char* value = (char*)malloc(length);
memcpy(value, zmq_msg_data(&reply), length);
zmq_msg_close(&reply);
printf("%s\n", value);
free(value);
}
});
t_pub.join();
// Give publisher time to set up.
sleep(1);
t_sub.join();
zmq_close(subscriber);
zmq_close(publisher);
zmq_ctx_destroy(context);
}
int main (int argc, char const *argv[]) {
hello_pubsub_inproc();
return 0;
}
The result
Starting server...
Collecting stock information from the server.
I've also tried adding this before joining threads to no avail:
zmq_proxy(publisher, subscriber, NULL);
The workaround: Replacing inproc with tcp fixes it instantly. But shouldn't inproc target in-process usecases?
Quick research tells me that it couldn't have been the order of bind vs. connect, since that problem is fixed in my zmq version.
The example below somehow tells me I don't have a missing shared-context issue, because it uses none:
ZeroMQ Subscribers not receiving message from Publisher over an inproc: transport class
I read from the Guide in the section Signaling Between Threads (PAIR Sockets) that
You can use PUB for the sender and SUB for the receiver. This will correctly deliver your messages exactly as you sent them and PUB does not distribute as PUSH or DEALER do. However, you need to configure the subscriber with an empty subscription, which is annoying.
What does it mean by an empty subscription?
Where am I doing wrong?
You can use PUB for the sender and SUB for the receiver. This will correctly deliver your messages exactly as you sent them and PUB does not distribute as PUSH or DEALER do. However, you need to configure the subscriber with an empty subscription, which is annoying.
Q : What does it mean by an empty subscription?
This means to set ( configure ) a subscription, driving a Topic-list message-delivery filtering, using an empty subscription string.
Q : Where am I doing wrong?
Here :
// sub_conn = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, 0, 0); // Wrong
sub_conn = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "",0); // Empty string
Doubts also here, about using a proper syntax and naming rules :
// int pub_conn = zmq_bind(publisher, "inproc://*:4040");
int pub_conn = zmq_bind(publisher, "inproc://<aStringWithNameMax256Chars>");
as inproc:// transport-class does not use any kind of external stack, but maps the AccessPoint's I/O(s) onto 1+ memory-locations ( a stack-less, I/O-thread not requiring transport-class ).
Given this, there is nothing like "<address>:<port#>" being interpreted by such (here missing) protocol, so the string-alike text gets used as-is for identifying which Memory-location are the message-data going to go into.
So, the "inproc://*:4040" does not get expanded, but used "literally" as a named inproc:// transport-class I/O-Memory-location identified as [*:4040] ( Next, asking a .connect()-method of .connect( "inproc://localhost:4040" ) will, and must do so, lexically miss the prepared Memory-location: ["*:4040"] as the strings do not match
So this ought fail to .connect() - error-handling might be silent, as since the versions +4.x there is not necessary to obey the historical requirement to first .bind() ( creating a "known" named-Memory-Location for inproc:// ) before one may call a .connect() to get it cross-connected with an "already existing" named-Memory-location, so the v4.0+ will most probably not raise any error on calling and creating a different .bind( "inproc://*:4040" ) landing-zone and next asking a non-matching .connect( "inproc://localhost:4040" ) ( which does not have a "previously prepared" landing-zone in an already existing named-Memory-location.
I'm new to POCO lib and I'm doing the net examples on the tutorial pdf.
When I'm running the DatagramSocket send example I'd always get a Poco::Net::NetException.
If I use the port '514' given by the tutorial, I'll get a Poco::IOException "I/O Error".
My environment is kubuntu 12.04, kernel 3.2.0-57-generic. Anyone knows about this?? Thx!!
// DatagramSocket send example
#include <Poco/Net/DatagramSocket.h>
#include <Poco/Net/SocketAddress.h>
#include <Poco/Timestamp.h>
#include <Poco/DateTimeFormatter.h>
#include <string>
int main()
{
Poco::Net::SocketAddress sa(Poco::Net::IPAddress(), 12345);
Poco::Net::DatagramSocket dgs(sa);
std::string syslogMsg;
Poco::Timestamp now;
syslogMsg = Poco::DateTimeFormatter::format(now, "<14>%w %f %H:%M:%S Hello, World!");
dgs.sendBytes(syslogMsg.data(), syslogMsg.size());
return 0;
}//main
Edit:
Thanks for Joachim Pileborg for suggestions on displayText() of exception. It shows this: "Net Exception: Destination address required"
And I amended the code like this and it worked:
Poco::Net::SocketAddress recver("localhost", 1234);
dgs.sendTo(syslogMsg.data(), syslogMsg.size(), recver);
But if I want to use sendBytes(), is there a way to put in a default receiver's address??
call connect(...) function of the Poco socket class.
Poco::Net::SocketAddress recver("localhost", 1234);
dgs.connect(recver);
and from there on you can dgs.sendBytes().
Hope this helps.
Please have a look at the following code:
#pragma once
using namespace System::IO::Ports;
using namespace System::Text::RegularExpressions;
using namespace System::Collections::Generic;
ref class SMS
{
public:
SMS(void);
void sendMessage();
private:
System::IO::Ports::SerialPort ^port;
};
And the cpp file
#include "StdAfx.h"
#include "SMS.h"
SMS::SMS(void)
{
//Initialize the Serial Port
port = gcnew System::IO::Ports::SerialPort();
port->PortName = "COM12";
port->BaudRate = 9600;
port->Parity = Parity::None;
port->DataBits = 8;
port->StopBits = StopBits::One;
port->Handshake = Handshake::RequestToSend;
port->DtrEnable = true;
port->RtsEnable = true;
port->NewLine = System::Environment::NewLine;
if(!port->IsOpen)
{
port->Open();
}
//Set message format
port->WriteLine("AT+CMGF=1");
//Turn off echo
port->WriteLine("ATE0");
//Set memory configurations
port->WriteLine("AT+CPMS=\"ME\",\"ME\",\"ME\"");
}
//This method will send the SMS
void SMS::sendMessage()
{
if(!port->IsOpen)
{
port->Open();
}
port->WriteLine("AT+CMGS=\"012121212\"");
port->WriteLine("Test Message From C#");
port->WriteLine(System::Convert::ToString((char)(26)));
port->Close();
}
I am trying to send SMS by accessing the dongle. The port is correct and the dongle also fine because it responded to my friend's code few hours back. What am I doing wrong here? Have I done anything incorrect with C++/CLI ? AT Commands?
try adding "CR" "LF" (Carriage Return and Line Feed characters) after each AT command, some GSM dongles (like SIM900) needem in order to work. I hope this helps
Regards
if for win32,..
prefer using
HFILE OpenFile(
LPCSTR lpFileName, // pointer to filename
LPOFSTRUCT lpReOpenBuff, // pointer to buffer for file information
UINT uStyle // action and attributes
);
with other events,...
if using SMS gateway with modem AT command capability, that's fine for direct read and write to COM port
if U using cell phone, many of this will not work. example nokia 6070, 3100 model group
best test it using hyperterminal.
I used CBuildre6 for
https://sites.google.com/site/xpressdms/rosegarden
cheer.
How may I download a file in C++ with wxWidgets?
Been googling and everything and nothing shows up! Help appreciated!
Use wxHTTP class for that.
wxHTTP Example Code:
#include <wx/sstream.h>
#include <wx/protocol/http.h>
wxHTTP get;
get.SetHeader(_T("Content-type"), _T("text/html; charset=utf-8"));
get.SetTimeout(10); // 10 seconds of timeout instead of 10 minutes ...
while (!get.Connect(_T("www.google.com")))
wxSleep(5);
wxApp::IsMainLoopRunning();
wxInputStream *httpStream = get.GetInputStream(_T("/intl/en/about.html"));
if (get.GetError() == wxPROTO_NOERR)
{
wxString res;
wxStringOutputStream out_stream(&res);
httpStream->Read(out_stream);
wxMessageBox(res);
}
else
{
wxMessageBox(_T("Unable to connect!"));
}
wxDELETE(httpStream);
get.Close();
If you want more flexible solution consider using libcurl.
Depends on where you want to 'download' it from, and how the file server allows files to be downloaded. The server might use FTP, or HTTP, or something more obscure. There is no way to tell from your question which has no useful information in it.
In general, I would not use wxWidgets for this task. wxWidgets is a GUI frmaework, with some extras for various things that may or may not be helpful in your case.
From HTTP as Andrejs suggest, from FTP using wxFTP
wxFTP ftp;
// if you don't use these lines anonymous login will be used
ftp.SetUser("user");
ftp.SetPassword("password");
if ( !ftp.Connect("ftp.wxwindows.org") )
{
wxLogError("Couldn't connect");
return;
}
ftp.ChDir("/pub");
wxInputStream *in = ftp.GetInputStream("wxWidgets-4.2.0.tar.gz");
if ( !in )
{
wxLogError("Coudln't get file");
}
else
{
size_t size = in->GetSize();
char *data = new char[size];
if ( !in->Read(data, size) )
{
wxLogError("Read error");
}
else
{
// file data is in the buffer
...
}
delete [] data;
delete in;
}
http://docs.wxwidgets.org/stable/wx_wxftp.html#wxftp
You did not define what "downloading a file" means to you.
If you want to use HTTP to retrieve some content, you should use an HTTP client library like libcurl and issue the appropriate HTTP GET request.
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