간단한 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"
내가 사용하고 윈도우 7 64 비트를 . Qt 4.8.5 및 Visual Studio 2008 !
다음 샘플은 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() );
}
샘플에 대한 우려로. 다음 사례 중 하나가 있다고 생각합니다.
희망,이 도움.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다