Send Email with smtp tls connection



  • hi everybody.
    i want to send email via smtp connection and use tls (STARTTLS) like gmail on port 587
    everything is fine before starttls. and when i send starttls handshake to server
    server response me with 220 response code but i cant encrypt the connection.

    here is my code :

    socket->connectToHost(host, port);
    .
    .
    .
    .
    .
    .

    // SMTP is line-oriented

    QString responseLine;
    do
    {
    responseLine = socket->readLine();
    response += responseLine;
    }
    while ( socket->canReadLine() && responseLine[3] != ' ' );

    responseLine.truncate( 3 );

    qDebug() << "Server response code:" << responseLine;
    qDebug() << "Server response: " << response;

    if ( state == Init && responseLine == "220" )
    {
    // banner was okay, let's go on
    qDebug() <<"banner was okay, let's go on ";
    *t << "EHLO kayer.co.ir" <<"\r\n";
    t->flush();

    state = Tls;
    }
    //No need, because I'm using socket->startClienEncryption() which makes the SSL handshake for you
    else if (state == Tls && responseLine == "250")
    {
    // Trying AUTH
    qDebug() <<"Trying AUTH ";
    qDebug() << "STarting Tls";
    *t << "STARTTLS" << "\r\n";
    t->flush();
    state = HandShake;
    }
    else if (state == HandShake && responseLine == "220")
    {
    qDebug() <<"Send EHLO once again but now encrypted";
    socket->startClientEncryption();
    // socket->connectToHostEncrypted(host, port);
    // socket->encryptedBytesAvailable();
    // socket->encrypted();
    if(!socket->waitForEncrypted(timeout))
    {
    qDebug() << socket->errorString();
    state = Close;
    }

    //Send EHLO once again but now encrypted

    *t << "EHLO localhost" << "\r\n";
    t->flush();
    state = Auth;
    }
    else if (state == Auth && responseLine == "250")
    {
    // Trying AUTH
    qDebug() <<"Trying AUTH";
    qDebug() << "Auth";
    *t << "AUTH LOGIN" << "\r\n";
    t->flush();
    state = User;
    }
    else if (state == User && responseLine == "334")
    {
    //Trying User
    qDebug() << "Username";
    //GMAIL is using XOAUTH2 protocol, which basically means that password and username has to be sent in base64 coding
    //https://developers.google.com/gmail/xoauth2_protocol
    *t << QByteArray().append(user).toBase64() << "\r\n";
    t->flush();

    state = Pass;
    }
    else if (state == Pass && responseLine == "334")
    {
    //Trying pass
    qDebug() << "Pass";
    *t << QByteArray().append(pass).toBase64() << "\r\n";
    t->flush();

    state = Mail;
    }
    else if ( state == Mail && responseLine == "235" )
    {
    // HELO response was okay (well, it has to be)

    //Apperantly for Google it is mandatory to have MAIL FROM and RCPT email formated the following way -> email@gmail.com
    qDebug() << "MAIL FROM:<" << from << ">";
    *t << "MAIL FROM:<" << from << ">\r\n";
    t->flush();
    state = Rcpt;
    }
    else if ( state == Rcpt && responseLine == "250" )
    {
    //Apperantly for Google it is mandatory to have MAIL FROM and RCPT email formated the following way -> email@gmail.com
    *t << "RCPT TO:<" << rcpt << ">\r\n"; //r
    t->flush();
    state = Data;
    }
    else if ( state == Data && responseLine == "250" )
    {

    *t << "DATA\r\n";
    t->flush();
    state = Body;
    }
    else if ( state == Body && responseLine == "354" )
    {

    *t << message << "\r\n.\r\n";
    t->flush();
    state = Quit;
    }
    else if ( state == Quit && responseLine == "250" )
    {

    *t << "QUIT\r\n";
    t->flush();
    // here, we just close.
    state = Close;
    emit status( tr( "Message sent" ) );
    }
    else if ( state == Close )
    {
    deleteLater();
    return;
    }
    else
    {
    // something broke.
    QMessageBox::warning( 0, tr( "Qt Simple SMTP client" ), tr( "Unexpected reply from SMTP server:\n\n" ) + response );
    state = Close;
    emit status( tr( "Failed to send message" ) );
    }
    response = "";

    ===============================================

    and this is my debugging :

    ..
    ..
    ..

    D/Qt ( 9333): smtp.cpp:55 (void Smtp::stateChanged(QAbstractSocket::SocketState)): stateChanged
    D/Qt ( 9333): smtp.cpp:56 (void Smtp::stateChanged(QAbstractSocket::SocketState)): stateChanged QAbstractSocket::HostLookupState
    D/Qt ( 9333): smtp.cpp:55 (void Smtp::stateChanged(QAbstractSocket::SocketState)): stateChanged
    D/Qt ( 9333): smtp.cpp:56 (void Smtp::stateChanged(QAbstractSocket::SocketState)): stateChanged QAbstractSocket::ConnectingState
    D/Qt ( 9333): smtp.cpp:55 (void Smtp::stateChanged(QAbstractSocket::SocketState)): stateChanged
    D/Qt ( 9333): smtp.cpp:56 (void Smtp::stateChanged(QAbstractSocket::SocketState)): stateChanged QAbstractSocket::ConnectedState
    D/Qt ( 9333): smtp.cpp:74 (void Smtp::connected()): Connected
    D/Qt ( 9333): smtp.cpp:80 (void Smtp::readyRead()): readyRead
    D/Qt ( 9333): smtp.cpp:93 (void Smtp::readyRead()): Server response code: "220"
    D/Qt ( 9333): smtp.cpp:94 (void Smtp::readyRead()): Server response: "220 mail.ABC.com ESMTP Postfix (Debian/GNU)

    D/Qt ( 9333): "
    D/Qt ( 9333): smtp.cpp:100 (void Smtp::readyRead()): banner was okay, let's go on
    D/Qt ( 9333): smtp.cpp:80 (void Smtp::readyRead()): readyRead
    D/Qt ( 9333): smtp.cpp:93 (void Smtp::readyRead()): Server response code: "250"
    D/Qt ( 9333): smtp.cpp:94 (void Smtp::readyRead()): Server response: "250-mail.ABC.com

    D/Qt ( 9333): 250-PIPELINING

    D/Qt ( 9333): 250-SIZE 35728640

    D/Qt ( 9333): 250-ETRN

    D/Qt ( 9333): 250-STARTTLS

    D/Qt ( 9333): 250-ENHANCEDSTATUSCODES

    D/Qt ( 9333): 250-8BITMIME

    D/Qt ( 9333): 250 DSN

    D/Qt ( 9333): "
    D/Qt ( 9333): smtp.cpp:110 (void Smtp::readyRead()): Trying AUTH
    D/Qt ( 9333): smtp.cpp:111 (void Smtp::readyRead()): STarting Tls
    D/Qt ( 9333): smtp.cpp:80 (void Smtp::readyRead()): readyRead
    D/Qt ( 9333): smtp.cpp:93 (void Smtp::readyRead()): Server response code: "220"
    D/Qt ( 9333): smtp.cpp:94 (void Smtp::readyRead()): Server response: "220 2.0.0 Ready to start TLS

    D/Qt ( 9333): "
    D/Qt ( 9333): smtp.cpp:95 (void Smtp::readyRead()): state: 1
    D/Qt ( 9333): smtp.cpp:118 (void Smtp::readyRead()): Send EHLO once again but now encrypted

    D/Qt ( 9333): smtp.cpp:61 (void Smtp::errorReceived(QAbstractSocket::SocketError)) : error
    D/Qt ( 9333): smtp.cpp:62 (void Smtp::errorReceived(QAbstractSocket::SocketError)) : error QAbstractSocket::SocketTimeoutError
    D/Qt ( 9333): smtp.cpp:126 (void Smtp::readyRead()): "Network operation timed out"

    ===========================
    thanks for your attention and any idea will be appreciate



  • unless you are vested in writing your own, Tokes Attila has written a pretty good library https://github.com/bluetiger9/SmtpClient-for-Qt



  • hi, im not writing my code from first , i m using the open source library as u attention it.
    but i dont know why all thems not working in my system.
    i install qt 5.2 . should i add some library to it ?? for example openssl !



  • hi , i have a problem like this, can u help me plz ?

    my code is about send mail in smtp - tls connection on port 587 , but i have problem when i use socket->startClientEncryption(); and then i have timeout error.

    plz help me about that. thank u



  • yes, I had to compile openssl 1.0.2d and Qt has to be built for openssl shared. I had to get libz to build openssl.

    openssl config that I needed:

    cd /home/jandle/Documents/Code/openssl-1.0.2d
    export INSTALLDIR=/opt/CodeSourcery/bin
    export PATH=$INSTALLDIR/bin:$PATH
    export BUILDMACH=i686-pc-linux-gnu
    export CROSS=arm-none-linux-gnueabi-
    export CC=${CROSS}gcc
    export LD=${CROSS}ld
    export AS=${CROSS}as
    export AR=${CROSS}ar
    ./Configure threads shared zlib linux-armv4 --openssldir=/home/isaw/ssl

    QT build options I used:
    cd /home/jandle/Documents/Code/QtArm

    ./configure -release -no-qml-debug -prefix ../Libs/QtArm -opensource -confirm-license -shared -no-largefile -gui -widgets -plugin-sql-mysql -openssl -continue -xplatform arm-none-linux-gnueabi-g++ -platform linux-g++ -device-option CROSS_COMPILE=/opt/CodeSourcery/bin/arm-none-linux-gnueabi- -no-compile-examples -no-warnings-are-errors -no-pch -no-dbus -no-sse2 -no-cups -no-nis -no-xcb -no-eglfs -linuxfb -no-kms -no-opengl -system-proxies -qtlibinfix arm -l rt -qpa linuxfb -fontconfig -qt-freetype -I /home/jandle/Documents/Code/openssl-1.0.2d/include/ -silent -L /home/isaw/lib -qt-zlib

    I need to do a diff to see if I edited SMTPEmail to make it compile and link. I know I had issues at first but I tried to keep all changes in my app side of the calls. I know I added printf debug statements.



  • @Alux yes, I had timeout errors before I got openssl working.



  • thanks alot for your reply. but when i use QSslSocket::supportsSsl(); this is return True, and my system is has openssl package. but in linux and in windows i have problem after sending starttls command to server and server send me HandShake accept and then i use startClientEncryption and then i have connection timeout ...



  • @Jeff-Andle thanks alot for your reply. but when i use QSslSocket::supportsSsl(); this is return True, and my system is has openssl package. but in linux and in windows i have problem after sending starttls command to server and server send me HandShake accept and then i use startClientEncryption and then i have connection timeout ...



  • Alex, I recently updated openssl to the latest rev over a security issue and have broken my app. I just today got back to where there isn't a seg fault and inside the library I am getting:

    ""The host name did not match any of the valid hosts for this certificate"
    Socket error sending Ready Message"

    You might want to put in some console debugging to see what is returned in the error slots.
    I did find a link about the certificates and hope I have time to address it before I travel at the end of the week.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.