CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Dec 2001
    Posts
    1

    C++ sending Email

    How can you send emails in C++ by using system commands in Unix?. I have heard of mailx. what does it do? and can it help solve my problem?


  2. #2
    Join Date
    Aug 2000
    Location
    New Jersey
    Posts
    968

    Re: C++ sending Email

    Here's a class that can do what you need.
    I added two example functions at the end.

    #include <stdio.h>

    #ifdef WIN32
    #include <afxsock.h>
    #include <winsock.h>
    #pragma warning(disable:4786)
    #else //WIN32
    typedef unsigned int SOCKET;
    #endif //WIN32

    #include <string>
    #include <fstream>
    #include <list>
    #include <time.h>
    #include <ctype.h>

    class GeneralSendMailClass
    {
    public:
    class EmailAddr
    {
    public:
    EmailAddr(const std::string &EmailID, std::string UserName)
    : m_EmailID(EmailID), m_UserName(UserName)
    {
    }
    EmailAddr(const char*EmailID)
    : m_EmailID(EmailID), m_UserName("")
    {
    }
    const std::string m_EmailID;
    const std::string m_UserName;
    };

    enum {SMTP_OUTGOING_MAIL_PORT = 25, BASE64_MAXLINE = 76, MAX_LINE_SIZE = 4094, AUTHENTICATION_PORT = 113};
    enum LoginMethod{AUTH_LOGIN_METHOD, LOGIN_PLAIN_METHOD};
    GeneralSendMailClass(std::string X_Mailer = "X-Mailer: GeneralSendMailClass By David Maisonave\r\n", std::string X_Phone = "")
    :m_socket(NULL), m_InitiateGood(true),m_UniqueContentID(0),
    m_X_Mailer(X_Mailer), m_X_Phone(X_Phone), Auth_UserID(""), Auth_Password(""), m_LoginMethod(AUTH_LOGIN_METHOD)
    {
    #ifdef WIN32
    WORD wVersion = MAKEWORD( 1, 1 );
    WSADATA wsaData;
    if (WSAStartup(wVersion, &wsaData)) m_InitiateGood=false;
    else m_InitiateGood = true;
    #endif //WIN32
    }
    ~GeneralSendMailClass()
    {
    #ifdef WIN32
    WSACleanup();
    #endif //WIN32
    }
    std::string SendEmail(const EmailAddr &To,
    const std::string &Subject,
    const std::string &Body,
    const std::string &EmailSenderHostName,
    const std::string &EmailSenderUserID,
    const EmailAddr &Sender = EmptyEmailAddr,
    const std::list<EmailAddr> *CC_List = NULL,
    const std::list<EmailAddr> *BCC_List = NULL,
    const std::list<std::string> *AttachmentPath_List = NULL,
    const EmailAddr &ReplyToAddr = EmptyEmailAddr,
    const std::string *MessageID = NULL)
    {
    if (!m_InitiateGood) return "Error: GeneralSendMailClass failed to initiate properly";
    if( (m_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
    return "Error: socket function return INVALID_SOCKET";
    std::string ReturnValue = NO_ERRORS;
    bool SendResetIf_Throw = false;
    ReturnValueFromReceive="";
    try
    {
    hostent *mailhost = NULL;
    if( isdigit(*EmailSenderHostName.c_str()) && strchr(EmailSenderHostName.c_str(), '.') )
    {
    unsigned long tmp_iaddr = inet_addr(EmailSenderHostName.c_str());
    mailhost = gethostbyaddr( (const char *)&tmp_iaddr, 4, PF_INET );
    }
    else mailhost = gethostbyname(EmailSenderHostName.c_str());
    if(mailhost == NULL) throw("Error: hostent *mailhost = NULL");
    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(SMTP_OUTGOING_MAIL_PORT);
    memcpy( &my_addr.sin_addr, mailhost->h_addr_list[0], sizeof(struct in_addr) );
    if (connect(m_socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))) throw("Error: connect failed");
    if (!VerifyReply(CHK_220_REPLY)) throw("Error: Did not Recv 220 before hello");
    if (Auth_Password.size())
    {
    // send EHLO message
    sprintf(m_EmailBuffer, "EHLO %s%s", EmailSenderHostName.c_str(),CRLF_SET.c_str());
    if (!SendStr()) throw("Error: Failed to send EHLO");
    if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending EHLO");
    // Send Auth Login
    switch(m_LoginMethod)
    {
    case AUTH_LOGIN_METHOD:
    sprintf(m_EmailBuffer, "AUTH LOGIN%s", CRLF_SET.c_str());
    break;
    case LOGIN_PLAIN_METHOD:
    sprintf(m_EmailBuffer, "AUTH LOGIN PLAIN%s", CRLF_SET.c_str());
    break;
    }
    if (!SendStr()) throw("Error: Failed to send AUTH LOGIN");
    if (!VerifyReply(CHK_334_REPLY )) throw("Error: Failed to Recv 334 after sending AUTH LOGIN");
    // Send AuthUserID
    if (Auth_UserID.size() == 0) Auth_UserID = EmailSenderUserID;
    sprintf(m_EmailBuffer, "%s%s",
    (m_LoginMethod == AUTH_LOGIN_METHOD)?Encode64(Auth_UserID).c_str():Auth_UserID.c_str(),
    CRLF_SET.c_str());
    if (!SendStr()) throw("Error: Failed to send Auth_UserID");
    if (!VerifyReply(CHK_334_REPLY )) throw("Error: Failed to Recv 334 after sending Auth_UserID");
    // Send AuthPassword
    sprintf(m_EmailBuffer, "%s%s",
    (m_LoginMethod == AUTH_LOGIN_METHOD)?Encode64(Auth_Password).c_str():Auth_Password.c_str(),
    CRLF_SET.c_str());
    if (!SendStr()) throw("Error: Failed to send Auth_Password");
    if (!VerifyReply(CHK_235_REPLY )) throw("Error: Failed to Recv 235 after sending Auth_Password");
    }
    else
    {
    // send HELO message
    sprintf(m_EmailBuffer, "HELO %s%s", EmailSenderHostName.c_str(),CRLF_SET.c_str());
    if (!SendStr()) throw("Error: Failed to send Hello");
    if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending hello");
    }
    SendResetIf_Throw = true;
    // send MAIL message
    if(Sender.m_EmailID.size())
    {//Need to add code for Sender.m_UserName
    sprintf(m_EmailBuffer, "MAIL FROM: <%s", Sender.m_EmailID.c_str());
    if( strchr(Sender.m_EmailID.c_str(), '@' ) ) strcat( m_EmailBuffer, ">");
    else
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), "@%s>", EmailSenderHostName.c_str());
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    }
    else sprintf(m_EmailBuffer, "MAIL FROM:<%s@%s>%s", EmailSenderUserID.c_str(), EmailSenderHostName.c_str(), CRLF_SET.c_str());
    // send MAIL FROM message
    if (!SendStr()) throw("Error: Failed to send From");
    if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending From");
    // send RCPT message
    sprintf(m_EmailBuffer, "RCPT TO: <%s>%s", To.m_EmailID.c_str(), CRLF_SET.c_str());
    if (!SendStr()) throw("Error: Failed to send TO");
    if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending RCPT TO");

    // send DATA message
    sprintf( m_EmailBuffer, "DATA%s", CRLF_SET.c_str());
    if (!SendStr()) throw("Error: Failed to send DATA line");
    if (!VerifyReply(CHK_354_REPLY )) throw("Error: Failed to Recv 354 after sending DATA line");

    // construct date string
    time_t tTime = time( NULL );
    strftime(m_EmailBuffer, MAX_LINE_SIZE, "Date: %a, %d %b %Y %H:%M:%S %Z", localtime(&tTime));
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    // send mail headers
    // Date:
    if(!SendStr()) throw("Error: Failed to send DATE");
    // X-Mailer:
    if (m_X_Mailer.size())
    {
    if(!Send(m_X_Mailer.c_str(), m_X_Mailer.size())) throw("Error: Failed to send X-Mailer");
    }
    // X-Phone:
    if (m_X_Phone.size())
    {
    if(!Send(m_X_Phone.c_str(), m_X_Phone.size())) throw("Error: Failed to send X-Phone");
    }
    // Message-ID:
    if(MessageID)
    {
    sprintf(m_EmailBuffer, "Message-ID: %s%s", MessageID->c_str(), CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send Message-ID");
    }
    // To:
    sprintf(m_EmailBuffer, "To: <%s>", To.m_EmailID.c_str());
    if(To.m_UserName.size())
    {
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), " (%s)",To.m_UserName.c_str());
    }
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send TO");
    // From:
    if(Sender.m_EmailID.size())
    {
    sprintf( m_EmailBuffer, "From: <%s>", Sender.m_EmailID.c_str());
    if(Sender.m_UserName.size())
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), " (%s)",Sender.m_UserName.c_str());
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    }
    else
    sprintf( m_EmailBuffer, "From: <%s@%s>%s", EmailSenderUserID.c_str(), EmailSenderHostName.c_str(), CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send From");
    // Reply-To:
    if(ReplyToAddr.m_EmailID.size())
    {
    sprintf( m_EmailBuffer, "Reply-To: <%s>", ReplyToAddr.m_EmailID.c_str());
    if(ReplyToAddr.m_UserName.size())
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), " (%s)",ReplyToAddr.m_UserName.c_str());
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send Reply-To");
    }
    // CC:
    if(CC_List)
    {
    strcpy(m_EmailBuffer,"CC: ");
    for (std::list<EmailAddr>::const_iterator email_addr_item = CC_List->begin();
    email_addr_item != CC_List->end();email_addr_item++)
    {
    std::list<EmailAddr>::const_iterator test_item = email_addr_item;
    test_item++;
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), "<%s>", email_addr_item->m_EmailID.c_str());
    if(email_addr_item->m_UserName.size())
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), " (%s)%s",email_addr_item->m_UserName.c_str(), (test_item==CC_List->end())?"":EMAIL_ADDR_DIV_CHR);
    else
    strcat(m_EmailBuffer, (test_item==CC_List->end())?"":EMAIL_ADDR_DIV_CHR);
    }
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send CC_List");
    }
    // BCC:
    if(BCC_List)
    {
    strcpy(m_EmailBuffer,"BCC: ");
    for (std::list<EmailAddr>::const_iterator email_addr_item = BCC_List->begin();
    email_addr_item != BCC_List->end();email_addr_item++)
    {
    std::list<EmailAddr>::const_iterator test_item = email_addr_item;
    test_item++;
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), "<%s>", email_addr_item->m_EmailID.c_str());
    if(email_addr_item->m_UserName.size())
    sprintf(m_EmailBuffer + strlen(m_EmailBuffer), " (%s)%s",email_addr_item->m_UserName.c_str(), (test_item==BCC_List->end())?"":EMAIL_ADDR_DIV_CHR);
    else
    strcat(m_EmailBuffer, (test_item==BCC_List->end())?"":EMAIL_ADDR_DIV_CHR);
    }
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send BCC_List");
    }
    // Subject:
    sprintf(m_EmailBuffer, "Subject: %s%s", Subject.c_str(), CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send Subject");
    if(AttachmentPath_List)
    {
    sprintf(m_EmailBuffer, "MIME-Version: 1.0%sContent-type: multipart/mixed; boundary=\"#BOUNDARY#\"%s", CRLF_SET.c_str(), CRLF_SET.c_str());
    SendStr();
    }
    /////////////////////////////////////////////////////////
    // 08/13/98 rlb
    // empty line needed after headers, RFC822
    strcpy(m_EmailBuffer, CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send empty line needed after headers(1)");
    strcpy(m_EmailBuffer, CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send empty line needed after headers(2)");
    if(AttachmentPath_List)
    {
    sprintf(m_EmailBuffer, "%s--#BOUNDARY#%sContent-Type: text/plain; charset=ISO-8859-1%sContent-Transfer-Encoding: quoted-printable%s%s",
    CRLF_SET.c_str(), CRLF_SET.c_str(), CRLF_SET.c_str(), CRLF_SET.c_str(), CRLF_SET.c_str());
    SendStr();
    }
    /////////////////////////////////////////////////////////
    // send message text
    if(!Send(Body.c_str(), Body.size())) throw("Error: Failed to send send message text");

    // AttachmentPath_List:
    if(AttachmentPath_List)
    {
    for (std::list<std::string>::const_iterator attachment_file_item = AttachmentPath_List->begin();
    attachment_file_item != AttachmentPath_List->end();attachment_file_item++)
    {
    std::string DestStringForEncodeData;
    if (Encode64(*attachment_file_item, DestStringForEncodeData))
    {
    if(!Send(DestStringForEncodeData.c_str(), DestStringForEncodeData.size()))
    throw("Error: Failed to send BCC_List");
    }
    }
    strcpy(m_EmailBuffer, CRLF_SET.c_str());
    strcat(m_EmailBuffer, "--#BOUNDARY#--");
    SendStr();
    }
    // send message terminator and receive reply
    if(!Send("\r\n.\r\n", 5)) throw("Error: Failed to send message terminator");
    if(!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 reply after sending message terminator");
    SendResetIf_Throw=false; //No use sending reset if fail at this point

    // send QUIT message
    strcpy(m_EmailBuffer, "QUIT" );
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    if(!SendStr()) throw("Error: Failed to send QUIT message");
    if(!VerifyReply(CHK_221_REPLY )) throw("Error: Failed to Recv 221 reply after sending QUIT message");
    }
    catch(const char* ErrMsg)
    {
    ReturnValue = ErrMsg;
    if (ReturnValueFromReceive.size())
    {
    ReturnValue += " Last Rcvd = " + ReturnValueFromReceive;
    }
    if (SendResetIf_Throw)
    {
    strcpy(m_EmailBuffer, "RESET");
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    SendStr();
    strcpy(m_EmailBuffer, "QUIT");
    strcat(m_EmailBuffer, CRLF_SET.c_str());
    SendStr();
    }
    }
    shutdown (m_socket, 2);
    #ifdef WIN32
    closesocket(m_socket);
    #else
    #endif
    m_socket = NULL;
    return ReturnValue;
    }
    static const char* NO_ERRORS;
    std::string Auth_Password;
    std::string Auth_UserID;
    LoginMethod m_LoginMethod;
    private:
    SOCKET m_socket;
    bool m_InitiateGood;
    char m_EmailBuffer[MAX_LINE_SIZE + 1];
    const std::string m_X_Mailer;
    const std::string m_X_Phone;
    int m_UniqueContentID;
    std::string ReturnValueFromReceive;
    static const char* m_base64Table;
    static const char* CHK_220_REPLY;
    static const char* CHK_221_REPLY;
    static const char* CHK_235_REPLY;
    static const char* CHK_250_REPLY;
    static const char* CHK_334_REPLY;
    static const char* CHK_354_REPLY;
    static const char* EMAIL_ADDR_DIV_CHR;
    static const std::string CRLF_SET;
    static const EmailAddr EmptyEmailAddr;
    bool SendStr(void)
    {
    return Send(m_EmailBuffer, strlen(m_EmailBuffer));
    }
    bool VerifyReply(const char* szReplyString)
    {
    return Receive(m_EmailBuffer, MAX_LINE_SIZE, 0, szReplyString);
    }
    bool Receive(char* szBuffer, int nLenMax, int nFlags, const char* szReplyString)
    {
    int nRes = recv(m_socket, szBuffer, nLenMax, nFlags);
    ReturnValueFromReceive = szBuffer;
    if (nRes == SOCKET_ERROR ) return false;
    #if defined(_DEBUG) || defined(DEBUG)
    static bool FirstPass = true;
    std:fstream file("log_recv.txt",std::ios:ut|((FirstPass)?0:std::ios::app));
    FirstPass=false;
    if (!file.fail())
    {
    file.seekp(0, std::ios::end);
    file.write(szBuffer,nRes);
    file.close();
    }
    #endif //defined(_DEBUG) || defined(DEBUG)
    *(szBuffer + nRes ) = '\0';
    char* szPtr = strtok( szBuffer, "\n" );
    while(szPtr)
    {
    if(*(szPtr + 3) == ' ')
    {
    if(!strncmp(szPtr, szReplyString, strlen(szReplyString))) return true;
    else return false;
    }
    else szPtr = strtok( NULL, "\n" );
    }
    return false;
    }
    bool Send(const char *szBuffer, size_t nLen)
    {
    int nCnt = 0;
    while( nCnt < nLen )
    {
    int nRes = send( m_socket, szBuffer + nCnt, nLen - nCnt, 0);
    if( nRes == SOCKET_ERROR) return false;
    else nCnt += nRes;
    }
    return true;
    }
    bool Encode64(const unsigned char *in, unsigned inlen,
    unsigned char *out, unsigned outmax)
    {
    unsigned olen = (inlen + 2) / 3 * 4;
    if (outmax < olen) return false;
    while (inlen >= 3)
    {
    /* user provided max buffer size; make sure we don't go over it */
    *out++ = m_base64Table[in[0] >> 2];
    *out++ = m_base64Table[((in[0] << 4) & 0x30) | (in[1] >> 4)];
    *out++ = m_base64Table[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
    *out++ = m_base64Table[in[2] & 0x3f];
    in += 3;
    inlen -= 3;
    }
    if (inlen > 0)
    {
    /* user provided max buffer size; make sure we don't go over it */
    *out++ = m_base64Table[in[0] >> 2];
    unsigned char oval = (in[0] << 4) & 0x30;
    if (inlen > 1)
    oval |= in[1] >> 4;
    *out++ = m_base64Table[oval];
    *out++ = (inlen < 2) ? '=' : m_base64Table[(in[1] << 2) & 0x3c];
    *out++ = '=';
    }
    if (olen < outmax) *out = '\0';
    return true;
    }
    std::string Encode64(const char *in, unsigned inlen)
    {
    char *TmpBuf = new char[inlen*2];
    std::string ReturnValue = "";
    if (Encode64((const unsigned char *)in, inlen, (unsigned char *)TmpBuf, inlen*2))
    {
    ReturnValue = TmpBuf;
    }
    delete [] TmpBuf;
    return ReturnValue;
    }
    std::string Encode64(const std::string &Src)
    {
    return Encode64(Src.c_str(), Src.size());
    }

    bool Encode64(const std::string &FileName, std::string &encodedFile)
    {
    std::ifstream file(FileName.c_str(), std::ios::binary);
    if (file.fail())
    {
    encodedFile = "";
    return false;
    }
    file.seekg(0, std::ios::end);
    unsigned int FileLen = file.tellg();
    file.seekg(0, std::ios::beg);
    unsigned char *SrcBuf = new unsigned char[FileLen];
    file.read((char *)SrcBuf,FileLen);
    file.close();
    unsigned int DestLen = FileLen * 1.5;
    unsigned char *DestBuf = new unsigned char[DestLen];
    bool ReturnValue = Encode64(SrcBuf, FileLen, DestBuf, DestLen);
    if (ReturnValue)
    {
    encodedFile = CRLF_SET + CRLF_SET + "--#BOUNDARY#";
    encodedFile += CRLF_SET + "Content-Type: text/plain; charset=ISO-8859-1; name=" + FileName;
    encodedFile += CRLF_SET + "Content-Transfer-Encoding: base64";
    encodedFile += CRLF_SET + "Content-Disposition: attachment; filename=" + FileName;
    encodedFile += CRLF_SET + CRLF_SET;
    encodedFile += (char *)DestBuf;
    }
    delete [] SrcBuf;
    delete [] DestBuf;
    return ReturnValue;
    }
    };
    const char* GeneralSendMailClass::NO_ERRORS = "OK";
    const char* GeneralSendMailClass::CHK_220_REPLY = "220";
    const char* GeneralSendMailClass::CHK_221_REPLY = "221";
    const char* GeneralSendMailClass::CHK_235_REPLY = "235";
    const char* GeneralSendMailClass::CHK_250_REPLY = "250";
    const char* GeneralSendMailClass::CHK_334_REPLY = "334";
    const char* GeneralSendMailClass::CHK_354_REPLY = "354";
    const char* GeneralSendMailClass::EMAIL_ADDR_DIV_CHR = ",";
    const std::string GeneralSendMailClass::CRLF_SET = "\r\n";
    const GeneralSendMailClass::EmailAddr GeneralSendMailClass::EmptyEmailAddr = "";
    const char* GeneralSendMailClass::m_base64Table =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????";

    void SimpleExampleFunctionUsingGeneralSendMailClass(void)
    {
    GeneralSendMailClass MyGeneralSendMailClass;
    MyGeneralSendMailClass.Auth_Password = "MyPasswordHere"; //Not needed if server does NOT require Auth
    MyGeneralSendMailClass.SendEmail(
    "[email protected]", // Recipient Email address
    "*File Test x99: Please ignore this email.", //Subject
    "Test from GeneralSendMailClass. Please ignore this email.", //Email Body
    "foofoo.com", //Host Name (sender's Hostname)
    "MyUserID" //Sender's UserID
    );
    }

    void Example1FunctionUsingGeneralSendMailClass(void)
    {
    GeneralSendMailClass MyGeneralSendMailClass;
    MyGeneralSendMailClass.Auth_Password = "MyPasswordHere";//Not needed if server does NOT require Auth
    MyGeneralSendMailClass.Auth_UserID = "TheUserID"; //This is usually the same as EmailSenderUserID passed to SendEmail function
    std::list<std::string> ListOfAttachments; //optional list of attachments
    ListOfAttachments.push_back("c:\\test10.txt");
    ListOfAttachments.push_back("c:\\test11.txt");
    ListOfAttachments.push_back("c:\\test12.txt");
    std::string Results = MyGeneralSendMailClass.SendEmail(
    "[email protected]", // Recipient Email address
    "Hello",//Subject
    "You can run, but you can't hide.",//Email Body
    "af.mil",
    "MyUserID",
    "",
    NULL, //CC list
    NULL, //BCC list
    &ListOfAttachments);
    if (Results != GeneralSendMailClass::NO_ERRORS)
    {
    printf("Error:\r\n");
    printf(Results.c_str());
    printf("\r\n\r\nPress ENTER to quit\r\n");
    getchar();
    }
    }


    int main(int argc, char* argv[])
    {
    SimpleExampleFunctionUsingGeneralSendMailClass();
    Example1FunctionUsingGeneralSendMailClass();
    return 0;
    }



    David Maisonave
    Author of Policy Based Synchronized Smart Pointer
    http://axter.com/smartptr


    Top ten member of C++ Expert Exchange.
    C++ Topic Area

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured