Boost! Yes! It's a good library for you to help you develop cross-platform C++ applications; headache free.
among all libraries in boost, boost::asio is for implementing asynchronous input output operations and working with network.
After having a look at boost asio samples and SMTP RFC : http://www.ietf.org/rfc/rfc2821.txt I implemented this simple class to be used in your C++ programs.
the only tricky part is base64 encoding which is required for sending user/password to SMTP Server.
the only tricky part is base64 encoding which is required for sending user/password to SMTP Server.
#include <iostream> #include <istream> #include <ostream> #include <string> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/lexical_cast.hpp> #include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/transform_width.hpp> #include <boost/archive/iterators/ostream_iterator.hpp> using boost::asio::ip::tcp; using namespace boost::archive::iterators; typedef base64_from_binary<transform_width<const char *,6,8> > base64_text; class SMTPClient { public: SMTPClient(std::string pServer,unsigned int pPort,std::string pUser,std::string pPassword): mServer(pServer),mPort(pPort),mUserName(pUser),mPassword(pPassword),mSocket(mIOService),mResolver(mIOService) { tcp::resolver::query qry(mServer,boost::lexical_cast<std::string>( mPort )); mResolver.async_resolve(qry,boost::bind(&SMTPClient::handleResolve,this,boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } bool Send(std::string pFrom,std::string pTo,std::string pSubject,std::string pMessage) { mFrom=pFrom; mTo=pTo; mSubject=pSubject; mMessage=pMessage; mIOService.run(); return mHasError; } private: std::string encodeBase64(std::string pData) { std::stringstream os; size_t sz=pData.size(); std::copy(base64_text(pData.c_str()),base64_text(pData.c_str()+sz),ostream_iterator<char>(os)); return os.str(); } void handleResolve(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) { if(!err) { tcp::endpoint endpoint=*endpoint_iterator; mSocket.async_connect(endpoint, boost::bind(&SMTPClient::handleConnect,this,boost::asio::placeholders::error,++endpoint_iterator)); } else { mHasError=true; mErrorMsg= err.message(); } } void writeLine(std::string pData) { std::ostream req_strm(&mRequest); req_strm << pData << "\r\n"; boost::asio::write(mSocket,mRequest); req_strm.clear(); } void handleConnect(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) { if (!err) { // The connection was successful. Send the request. std::ostream req_strm(&mRequest); writeLine("EHLO "+mServer); writeLine("AUTH LOGIN"); writeLine(encodeBase64(mUserName)); writeLine(encodeBase64(mPassword)); writeLine( "MAIL FROM:<"+mFrom+">"); writeLine( "RCPT TO:<"+mTo+">"); writeLine( "DATA"); writeLine( "SUBJECT:"+mSubject); writeLine( "From:"+mFrom); writeLine( "To:"+mTo); writeLine( ""); writeLine( mMessage ); writeLine( ".\r\n"); } else { mHasError=true; mErrorMsg= err.message(); } } std::string mServer; std::string mUserName; std::string mPassword; std::string mFrom; std::string mTo; std::string mSubject; std::string mMessage; unsigned int mPort; boost::asio::io_service mIOService; tcp::resolver mResolver; tcp::socket mSocket; boost::asio::streambuf mRequest; boost::asio::streambuf mResponse; bool mHasError; std::string mErrorMsg; };Yest ! that's it. you are free to copy and paste this code into your application:
SMTPClient mailc("yoursmtpserver.com",25,"[email protected]","password"); mailc.Send("[email protected]","[email protected]","subject","Hello from C++ SMTP Client!");