我可以连接到Yahoo SMTP服务器,但不能连接到Gmail服务器

s4eed

我有一个简单的SMTP邮件客户端。我可以使用此应用程序和我的Yahoo邮件帐户发送电子邮件。但是,当我要使用我的gmail帐户连接发送电子邮件到Google的SMTP服务器时失败了!这是我的SMTP类:

Smtp::Smtp( const QString &user, const QString &pass, const QString &host, int port, int timeout )
{
    socket = new QSslSocket(this);

    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
    connect(socket, SIGNAL(connected()), this, SLOT(connected() ) );
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,SLOT(errorReceived(QAbstractSocket::SocketError)));
    connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(stateChanged(QAbstractSocket::SocketState)));
    connect(socket, SIGNAL(disconnected()), this,SLOT(disconnected()));


    this->user = user;
    this->pass = pass;

    this->host = host;
    this->port = port;
    this->timeout = timeout;


}

void Smtp::sendMail(const QString &from, const QString &to, const QString &subject, const QString &body)
{
   // qDebug() << subject<<" ::: "<<body;
    message = "To: " + to + "\n";
    message.append(QString("From: " + from + "\n"));
    message.append("Subject: " + subject + "\n");
    message.append(body);

    message.replace( QString::fromLatin1( "\n" ), QString::fromLatin1( "\r\n" ) );
    message.replace( QString::fromLatin1( "\r\n.\r\n" ),
    QString::fromLatin1( "\r\n..\r\n" ) );
    //qDebug()<<message;
    this->from = from;
    rcpt = to;
    state = Init;
    socket->connectToHostEncrypted(host, port); //"smtp.gmail.com" and 465 for gmail TLS
    if (!socket->waitForConnected(timeout)) {
         qDebug() << socket->errorString();
     }

    t = new QTextStream( socket );
    t->setCodec("UTF-8");
}

Smtp::~Smtp()
{
    delete t;
    delete socket;
}
void Smtp::stateChanged(QAbstractSocket::SocketState socketState)
{

    qDebug() <<"stateChanged " << socketState;
}

void Smtp::errorReceived(QAbstractSocket::SocketError socketError)
{
    qDebug() << "error " <<socketError;
}

void Smtp::disconnected()
{

    qDebug() <<"disconneted";
    qDebug() << "error "  << socket->errorString();
}

void Smtp::connected()
{
    qDebug() << "Connected ";
}

void Smtp::readyRead()
{

     qDebug() <<"readyRead";
    // 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
        *t << "EHLO localhost" <<"\r\n";
        t->flush();

        state = HandShake;
    }
    //No need, because I'm using socket->startClienEncryption() which makes the SSL handshake for you
    /*else if (state == Tls && responseLine == "250")
    {
        // Trying AUTH
        qDebug() << "STarting Tls";
        *t << "STARTTLS" << "\r\n";
        t->flush();
        state = HandShake;
    }*/
    else if (state == HandShake && responseLine == "250")
    {
        socket->startClientEncryption();
        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() << "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 protected]>
        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 protected]>
        *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 = "";
}

我将smtp.mail.yahoo.com用作yahoo smtp服务器,将smtp.gmail.com用作gmail smtp服务器。我都使用端口465。
这是调试输出(尽管我认为没有用):

stateChanged  QAbstractSocket::HostLookupState 
stateChanged  QAbstractSocket::ConnectingState 
stateChanged  QAbstractSocket::UnconnectedState 
error  QAbstractSocket::SocketTimeoutError 
stateChanged  QAbstractSocket::UnconnectedState 
"Socket operation timed out" 

我正在使用Windows 7 64位Qt 4.8.5和Visual Studio 2008

安东·杜纳夫(Anton Dunaev)

以下示例可与GMAIL配合使用:

SmtpSsl::SmtpSsl(QObject *parent) :
    QObject(parent) ,
    smtp( new QSslSocket ) ,
    istd( new QFile ) ,
    ostd( new QFile )
{
    qDebug() << "constructing";


    // QIODevice
    QObject::connect( smtp , SIGNAL(aboutToClose()) , this , SLOT(sck_aboutToClose()) );
    QObject::connect( smtp , SIGNAL(bytesWritten(qint64)) , this , SLOT    (sck_bytesWritten(qint64)) );
    QObject::connect( smtp , SIGNAL(readChannelFinished()) , this , SLOT(sck_readChannelFinished()) );
    QObject::connect( smtp , SIGNAL(readyRead()) , this , SLOT(sck_readyRead()) );


    // QAbstractSocket
    QObject::connect( smtp , SIGNAL(connected()) , this , SLOT(sck_connected()) );
    QObject::connect( smtp , SIGNAL(disconnected()) , this , SLOT(sck_disconnected()) );
    QObject::connect( smtp , SIGNAL(error(QAbstractSocket::SocketError)) , this , SLOT(sck_error(QAbstractSocket::SocketError)) );
    QObject::connect( smtp , SIGNAL(hostFound()) , this , SLOT(sck_hostfound()) );
    QObject::connect( smtp , SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)) , this , SLOT(sck_proxyAuthRequired()) );
    QObject::connect( smtp , SIGNAL(stateChanged(QAbstractSocket::SocketState)) , this , SLOT(sck_stateChanged(QAbstractSocket::SocketState)) );


    // QSslSocket
    QObject::connect( smtp , SIGNAL(encrypted()) , this , SLOT(sck_encrypted()) );
    QObject::connect( smtp , SIGNAL(encryptedBytesWritten(qint64)) , this , SLOT(sck_encryptedBytesWritten(qint64)) );
    QObject::connect( smtp , SIGNAL(modeChanged(QSslSocket::SslMode)) , this , SLOT(sck_modeChanged(QSslSocket::SslMode)) );
    QObject::connect( smtp , SIGNAL(sslErrors(QList<QSslError>)) , this , SLOT(sck_sslErrors(QList<QSslError>)) );
    QObject::connect( smtp , SIGNAL(peerVerifyError(QSslError)) , this , SLOT(sck_peerVerifyError(QSslError)) );


    // public part
    QObject::connect( smtp , SIGNAL(encrypted()) , this , SLOT(start_session()) );
    QObject::connect( smtp , SIGNAL(disconnected()) , this , SLOT(deleteLater()) );

    smtp->setPeerVerifyMode( QSslSocket::VerifyPeer );
    smtp->connectToHostEncrypted( "smtp.gmail.com" , 465 );
    istd->open( stdin  , QIODevice::ReadOnly );
    ostd->open( stdout , QIODevice::WriteOnly );

    qDebug() << "constructed";
}

SmtpSsl::~SmtpSsl()
{
    qDebug() << "destroying";
    delete smtp;
    qDebug() << "destroyed";
}   

void
SmtpSsl::start_session()
{
    QObject::connect( smtp , SIGNAL(readyRead()) , this , SLOT(receive()) );
}   

void    SmtpSsl::receive()
{
    ostd->write( smtp->readAll() );
    ostd->flush();

    smtp->write( istd->readLine() );
}

关于您的样品。我可以猜测您有以下情况之一:

  1. 您在网络级别遇到连接问题。您可以在没有SSL的情况下连接smtp.gmail.com端口465吗?
  2. 我相信你有这种情况。您正在拦截readyRead信号,并且可能(此处未显示此代码)在进入加密状态(即SSL握手数据)之前读取了接收到的数据由于您已读取握手数据,因此QSslSocket将等待,直到可以读取已抓取的握手数据,这将导致超时。

希望对您有所帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章