Example #1
0
void QxtSmtpPrivate::authenticate()
{
    if (!extensions.contains("AUTH") || username.isEmpty() || password.isEmpty())
    {
        state = Authenticated;
        emit qxt_p().authenticated();
    }
    else
    {
        QStringList auth = extensions["AUTH"].toUpper().split(' ', QString::SkipEmptyParts);
        if (auth.contains("CRAM-MD5"))
        {
            authCramMD5();
        }
        else if (auth.contains("PLAIN"))
        {
            authPlain();
        }
        else if (auth.contains("LOGIN"))
        {
            authLogin();
        }
        else
        {
            state = Authenticated;
            emit qxt_p().authenticated();
        }
    }
}
Example #2
0
void QxtSmtpPrivate::socketRead()
{
    buffer += socket->readAll();
    while (true)
    {
        int pos = buffer.indexOf("\r\n");
        if (pos < 0) return;
        QByteArray line = buffer.left(pos);
        buffer = buffer.mid(pos + 2);
        QByteArray code = line.left(3);
        switch (state)
        {
        case StartState:
            if (code[0] != '2')
            {
                socket->disconnectFromHost();
            }
            else
            {
                ehlo();
            }
            break;
        case HeloSent:
        case EhloSent:
        case EhloGreetReceived:
            parseEhlo(code, (line[3] != ' '), line.mid(4));
            break;
#ifndef QT_NO_OPENSSL
        case StartTLSSent:
            if (code == "220")
            {
                socket->startClientEncryption();
                ehlo();
            }
            else
            {
                authenticate();
            }
            break;
#endif
        case AuthRequestSent:
        case AuthUsernameSent:
            if (authType == AuthPlain) authPlain();
            else if (authType == AuthLogin) authLogin();
            else authCramMD5(line.mid(4));
            break;
        case AuthSent:
            if (code[0] == '2')
            {
                state = Authenticated;
                emit qxt_p().authenticated();
            }
            else
            {
                state = Disconnected;
                emit qxt_p().authenticationFailed();
                emit qxt_p().authenticationFailed( line );
                emit socket->disconnectFromHost();
            }
            break;
        case MailToSent:
        case RcptAckPending:
            if (code[0] != '2') {
                emit qxt_p().mailFailed( pending.first().first, code.toInt() );
                emit qxt_p().mailFailed(pending.first().first, code.toInt(), line);
				// pending.removeFirst();
				// DO NOT remove it, the body sent state needs this message to assigned the next mail failed message that will 
				// the sendNext 
				// a reset will be sent to clear things out
                sendNext();
                state = BodySent;
            }
            else
                sendNextRcpt(code, line);
            break;
        case SendingBody:
            sendBody(code, line);
            break;
        case BodySent:
			if ( pending.count() )
			{
				// if you removeFirst in RcpActpending/MailToSent on an error, and the queue is now empty, 
				// you will get into this state and then crash because no check is done.  CHeck added but shouldnt
				// be necessary since I commented out the removeFirst
				if (code[0] != '2')
				{
					emit qxt_p().mailFailed(pending.first().first, code.toInt() );
					emit qxt_p().mailFailed(pending.first().first, code.toInt(), line);
				}
				else
					emit qxt_p().mailSent(pending.first().first);
	            pending.removeFirst();
			}
            sendNext();
            break;
        case Resetting:
            if (code[0] != '2') {
                emit qxt_p().connectionFailed();
                emit qxt_p().connectionFailed( line );
            }
            else {
                state = Waiting;
                sendNext();
            }
            break;
        }
    }
}
Example #3
0
void Smtp::readyRead()
{
  qDebug() << Q_FUNC_INFO;
  // SMTP is line-oriented
  buffer += socket->readAll();
  while (true)
  {
    int pos = buffer.indexOf("\r\n");
    if (pos < 0) return; // Loop exit condition
    QByteArray line = buffer.left(pos);
    buffer = buffer.mid(pos + 2);
    qDebug() << "Response line:" << line;
    // Extract reponse code
    QByteArray code = line.left(3);

    switch(state) {
    case Init: {
      if (code[0] == '2') {
        // Connection was successful
        ehlo();
      } else {
        logError("Connection failed, unrecognized reply: "+line);
        state = Close;
      }
      break;
    }
    case EhloSent:
    case HeloSent:
    case EhloGreetReceived:
      parseEhloResponse(code, line[3] != ' ', line.mid(4));
      break;
#ifndef QT_NO_OPENSSL
    case StartTLSSent:
      if (code == "220") {
        socket->startClientEncryption();
        ehlo();
      } else {
        authenticate();
      }
      break;
#endif
    case AuthRequestSent:
    case AuthUsernameSent:
      if (authType == AuthPlain) authPlain();
      else if (authType == AuthLogin) authLogin();
      else authCramMD5(line.mid(4));
      break;
    case AuthSent:
    case Authenticated:
      if (code[0] == '2') {
        qDebug() << "Sending <mail from>...";
        socket->write("mail from:<" + from.toLatin1() + ">\r\n");
        socket->flush();
        state = Rcpt;
      } else {
        // Authentication failed!
        logError("Authentication failed, msg: "+line);
        state = Close;
      }
      break;
    case Rcpt:
      if (code[0] == '2') {
        socket->write("rcpt to:<" + rcpt.toLatin1() + ">\r\n");
        socket->flush();
        state = Data;
      } else {
        logError("<mail from> was rejected by server, msg: "+line);
        state = Close;
      }
      break;
    case Data:
      if (code[0] == '2') {
        socket->write("data\r\n");
        socket->flush();
        state = Body;
      } else {
        logError("<Rcpt to> was rejected by server, msg: "+line);
        state = Close;
      }
      break;
    case Body:
      if (code[0] == '3') {
        socket->write(message + "\r\n.\r\n");
        socket->flush();
        state = Quit;
      } else {
        logError("<data> was rejected by server, msg: "+line);
        state = Close;
      }
      break;
    case Quit:
      if (code[0] == '2') {
        socket->write("QUIT\r\n");
        socket->flush();
        // here, we just close.
        state = Close;
      } else {
        logError("Message was rejected by the server, error: "+line);
        state = Close;
      }
      break;
    default:
      qDebug() << "Disconnecting from host";
      socket->disconnectFromHost();
      return;
    }
  }
}