File indexing completed on 2024-11-24 04:53:26
0001 // 0002 // C++ Implementation: qwwsmtpclient 0003 // 0004 // Description: 0005 // 0006 // 0007 // Author: Witold Wysota <wysota@wysota.eu.org>, (C) 2009 0008 // 0009 // Copyright: See COPYING file that comes with this distribution 0010 // 0011 // 0012 #include "qwwsmtpclient.h" 0013 #include <QSslSocket> 0014 #include <QtDebug> 0015 #include <QRegularExpression> 0016 #include <QQueue> 0017 #include <QVariant> 0018 #include <QStringList> 0019 0020 /* 0021 CONNECTION ESTABLISHMENT 0022 S: 220 0023 E: 554 0024 EHLO or HELO 0025 S: 250 0026 E: 504, 550 0027 MAIL 0028 S: 250 0029 E: 552, 451, 452, 550, 553, 503 0030 RCPT 0031 S: 250, 251 (but see section 3.4 for discussion of 251 and 551) 0032 E: 550, 551, 552, 553, 450, 451, 452, 503, 550 0033 DATA 0034 I: 354 -> data -> S: 250 0035 E: 552, 554, 451, 452 0036 E: 451, 554, 503 0037 RSET 0038 S: 250 0039 VRFY 0040 S: 250, 251, 252 0041 E: 550, 551, 553, 502, 504 0042 EXPN 0043 S: 250, 252 0044 E: 550, 500, 502, 504 0045 HELP 0046 S: 211, 214 0047 E: 502, 504 0048 NOOP 0049 S: 250 0050 QUIT 0051 S: 221 0052 */ 0053 0054 struct SMTPCommand { 0055 enum Type { Connect, Disconnect, StartTLS, Authenticate, Mail, MailBurl, RawCommand }; 0056 int id; 0057 Type type; 0058 QVariant data; 0059 QVariant extra; 0060 }; 0061 0062 class QwwSmtpClientPrivate { 0063 public: 0064 QwwSmtpClientPrivate(QwwSmtpClient *qq) { 0065 q = qq; 0066 } 0067 QSslSocket *socket; 0068 0069 QwwSmtpClient::State state; 0070 void setState(QwwSmtpClient::State s); 0071 void parseOption(const QString &buffer); 0072 0073 void onConnected(); 0074 void onDisconnected(); 0075 void onError(QAbstractSocket::SocketError); 0076 void _q_readFromSocket(); 0077 void _q_encrypted(); 0078 void processNextCommand(bool ok = true); 0079 void abortDialog(); 0080 0081 void sendAuthPlain(const QString &username, const QString &password); 0082 void sendAuthLogin(const QString &username, const QString &password, int stage); 0083 0084 void sendEhlo(); 0085 void sendHelo(); 0086 void sendQuit(); 0087 void sendRcpt(); 0088 0089 int lastId; 0090 bool inProgress; 0091 QString localName; 0092 QString localNameEncrypted; 0093 QString errorString; 0094 0095 // server caps: 0096 QwwSmtpClient::Options options; 0097 QwwSmtpClient::AuthModes authModes; 0098 0099 QQueue<SMTPCommand> commandqueue; 0100 private: 0101 QwwSmtpClient *q; 0102 0103 QwwSmtpClientPrivate(const QwwSmtpClientPrivate&); // don't implement 0104 QwwSmtpClientPrivate& operator=(const QwwSmtpClientPrivate&); // don't implement 0105 }; 0106 0107 // private slot triggered upon connection to the server 0108 // - clears options 0109 // - notifies the environment 0110 void QwwSmtpClientPrivate::onConnected() { 0111 options = QwwSmtpClient::NoOptions; 0112 authModes = QwwSmtpClient::AuthNone; 0113 emit q->stateChanged(QwwSmtpClient::Connected); 0114 emit q->connected(); 0115 } 0116 0117 // private slot triggered upon disconnection from the server 0118 // - checks the cause of disconnection 0119 // - aborts or continues processing 0120 void QwwSmtpClientPrivate::onDisconnected() { 0121 setState(QwwSmtpClient::Disconnected); 0122 if (commandqueue.isEmpty()) { 0123 inProgress = false; 0124 emit q->done(true); 0125 return; 0126 } 0127 0128 if (commandqueue.head().type == SMTPCommand::Disconnect) { 0129 inProgress = false; 0130 emit q->done(true); 0131 return; 0132 } 0133 0134 emit q->commandFinished(commandqueue.head().id, true); 0135 commandqueue.clear(); 0136 inProgress = false; 0137 emit q->done(false); 0138 } 0139 0140 void QwwSmtpClientPrivate::onError(QAbstractSocket::SocketError e) 0141 { 0142 emit q->socketError(e, socket->errorString()); 0143 onDisconnected(); 0144 } 0145 0146 // main logic of the component - a slot triggered upon data entering the socket 0147 // comments inline... 0148 void QwwSmtpClientPrivate::_q_readFromSocket() { 0149 while (socket->canReadLine()) { 0150 QString line = socket->readLine(); 0151 emit q->logReceived(line.toUtf8()); 0152 QRegularExpression rx("(*ANYCRLF)^(\\d+)-(.*)$", QRegularExpression::MultilineOption); // multiline response (aka 250-XYZ) 0153 QRegularExpression rxlast("(*ANYCRLF)^(\\d+) (.*)$", QRegularExpression::MultilineOption); // single or last line response (aka 250 XYZ) 0154 // multiline 0155 QRegularExpressionMatch mid_match = rx.match(line); 0156 if (mid_match.hasMatch()) { 0157 int status = mid_match.captured(1).toInt(); 0158 SMTPCommand &cmd = commandqueue.head(); 0159 switch (cmd.type) { 0160 // trying to connect 0161 case SMTPCommand::Connect: { 0162 int stage = cmd.extra.toInt(); 0163 // stage 0 completed with success - socket is connected and EHLO was sent 0164 if(stage==1 && status==250){ 0165 QString arg = mid_match.captured(2).trimmed(); 0166 parseOption(arg); // we're probably receiving options 0167 } 0168 } 0169 break; 0170 // trying to establish deferred SSL handshake 0171 case SMTPCommand::StartTLS: { 0172 int stage = cmd.extra.toInt(); 0173 // stage 0 (negotiation) completed ok 0174 if(stage==1 && status==250){ 0175 QString arg = mid_match.captured(2).trimmed(); 0176 parseOption(arg); // we're probably receiving options 0177 } 0178 } 0179 default: break; 0180 } 0181 } else { 0182 // single line 0183 QRegularExpressionMatch last_match = rxlast.match(line); 0184 if (last_match.hasMatch()) { 0185 int status = last_match.captured(1).toInt(); 0186 SMTPCommand &cmd = commandqueue.head(); 0187 switch (cmd.type) { 0188 // trying to connect 0189 case SMTPCommand::Connect: { 0190 int stage = cmd.extra.toInt(); 0191 // connection established, server sent its banner 0192 if (stage==0 && status==220) { 0193 sendEhlo(); // connect ok, send ehlo 0194 } 0195 // server responded to EHLO 0196 if (stage==1 && status==250){ 0197 // success (EHLO) 0198 parseOption(last_match.captured(2).trimmed()); // we're probably receiving the last option 0199 errorString.clear(); 0200 setState(QwwSmtpClient::Connected); 0201 processNextCommand(); 0202 } 0203 // server responded to HELO (EHLO failed) 0204 if (stage==2 && status==250) { 0205 // success (HELO) 0206 errorString.clear(); 0207 setState(QwwSmtpClient::Connected); 0208 processNextCommand(); 0209 } 0210 // EHLO failed, reason given in errorString 0211 if (stage==1 && (status==554 || status==501 || status==502 || status==421)) { 0212 errorString = last_match.captured(2).trimmed(); 0213 sendHelo(); // ehlo failed, send helo 0214 cmd.extra = 2; 0215 } 0216 //abortDialog(); 0217 } 0218 break; 0219 // trying to establish a delayed SSL handshake 0220 case SMTPCommand::StartTLS: { 0221 int stage = cmd.extra.toInt(); 0222 // received an invitation from the server to enter TLS mode 0223 if (stage==0 && status==220) { 0224 emit q->logSent("*** startClientEncryption"); 0225 socket->startClientEncryption(); 0226 } 0227 // TLS established, connection is encrypted, EHLO was sent 0228 else if (stage==1 && status==250) { 0229 setState(QwwSmtpClient::Connected); 0230 parseOption(last_match.captured(2).trimmed()); // we're probably receiving options 0231 errorString.clear(); 0232 emit q->tlsStarted(); 0233 processNextCommand(); 0234 } 0235 // starttls failed 0236 else { 0237 emit q->logReceived(QByteArrayLiteral("*** TLS failed at stage ") + QByteArray::number(stage) + ": " + line.toUtf8()); 0238 errorString = "TLS failed"; 0239 emit q->done(false); 0240 } 0241 } 0242 break; 0243 // trying to authenticate the client to the server 0244 case SMTPCommand::Authenticate: { 0245 int stage = cmd.extra.toInt(); 0246 if (stage==0 && status==334) { 0247 // AUTH mode was accepted by the server, 1st challenge sent 0248 QwwSmtpClient::AuthMode authmode = (QwwSmtpClient::AuthMode)cmd.data.toList().at(0).toInt(); 0249 errorString.clear(); 0250 switch (authmode) { 0251 case QwwSmtpClient::AuthPlain: 0252 sendAuthPlain(cmd.data.toList().at(1).toString(), cmd.data.toList().at(2).toString()); 0253 break; 0254 case QwwSmtpClient::AuthLogin: 0255 sendAuthLogin(cmd.data.toList().at(1).toString(), cmd.data.toList().at(2).toString(), 1); 0256 break; 0257 default: 0258 qWarning("I shouldn't be here"); 0259 setState(QwwSmtpClient::Connected); 0260 processNextCommand(); 0261 break; 0262 } 0263 cmd.extra = stage+1; 0264 } else if (stage==1 && status==334) { 0265 // AUTH mode and user names were acccepted by the server, 2nd challenge sent 0266 QwwSmtpClient::AuthMode authmode = (QwwSmtpClient::AuthMode)cmd.data.toList().at(0).toInt(); 0267 errorString.clear(); 0268 switch (authmode) { 0269 case QwwSmtpClient::AuthPlain: 0270 // auth failed 0271 setState(QwwSmtpClient::Connected); 0272 processNextCommand(); 0273 break; 0274 case QwwSmtpClient::AuthLogin: 0275 sendAuthLogin(cmd.data.toList().at(1).toString(), cmd.data.toList().at(2).toString(), 2); 0276 break; 0277 default: 0278 qWarning("I shouldn't be here"); 0279 setState(QwwSmtpClient::Connected); 0280 processNextCommand(); 0281 break; 0282 } 0283 } else if (stage==2 && status==334) { 0284 // auth failed 0285 errorString = last_match.captured(2).trimmed(); 0286 setState(QwwSmtpClient::Connected); 0287 processNextCommand(); 0288 } else if (status==235) { 0289 // auth ok 0290 errorString.clear(); 0291 emit q->authenticated(); 0292 setState(QwwSmtpClient::Connected); 0293 processNextCommand(); 0294 } else { 0295 errorString = last_match.captured(2).trimmed(); 0296 setState(QwwSmtpClient::Connected); 0297 emit q->done(false); 0298 } 0299 } 0300 break; 0301 // trying to send mail 0302 case SMTPCommand::Mail: 0303 case SMTPCommand::MailBurl: 0304 { 0305 int stage = cmd.extra.toInt(); 0306 // temporary failure upon receiving the sender address (greylisting probably) 0307 if (status==421 && stage==0) { 0308 errorString = last_match.captured(2).trimmed(); 0309 // temporary envelope failure (greylisting) 0310 setState(QwwSmtpClient::Connected); 0311 processNextCommand(false); 0312 } 0313 if (status==250 && stage==0) { 0314 // sender accepted 0315 errorString.clear(); 0316 sendRcpt(); 0317 } else if (status==250 && stage==1) { 0318 // all receivers accepted 0319 if (cmd.type == SMTPCommand::MailBurl) { 0320 errorString.clear(); 0321 QByteArray url = cmd.data.toList().at(2).toByteArray(); 0322 QByteArray data = "BURL " + url + " LAST\r\n"; 0323 emit q->logSent(data); 0324 socket->write(data); 0325 cmd.extra=2; 0326 } else { 0327 errorString.clear(); 0328 QByteArray data("DATA\r\n"); 0329 emit q->logSent(data); 0330 socket->write(data); 0331 cmd.extra=2; 0332 } 0333 } else if ((cmd.type == SMTPCommand::Mail && status==354 && stage==2)) { 0334 // DATA command accepted 0335 errorString.clear(); 0336 QByteArray toBeWritten = cmd.data.toList().at(2).toByteArray() + "\r\n.\r\n"; // termination token - CRLF.CRLF 0337 emit q->logSent(toBeWritten); 0338 socket->write(toBeWritten); // expecting data to be already escaped (CRLF.CRLF) 0339 cmd.extra=3; 0340 } else if ((cmd.type == SMTPCommand::MailBurl && status==250 && stage==2)) { 0341 // BURL succeeded 0342 setState(QwwSmtpClient::Connected); 0343 errorString.clear(); 0344 processNextCommand(); 0345 } else if ((cmd.type == SMTPCommand::Mail && status==250 && stage==3)) { 0346 // mail queued 0347 setState(QwwSmtpClient::Connected); 0348 errorString.clear(); 0349 processNextCommand(); 0350 } else { 0351 // something went wrong 0352 errorString = last_match.captured(2).trimmed(); 0353 setState(QwwSmtpClient::Connected); 0354 emit q->done(false); 0355 processNextCommand(); 0356 } 0357 } 0358 default: break; 0359 } 0360 } else { 0361 qDebug() << "None of two regular expressions matched the input" << line; 0362 } 0363 } 0364 } 0365 } 0366 0367 void QwwSmtpClientPrivate::setState(QwwSmtpClient::State s) { 0368 QwwSmtpClient::State old = state; 0369 state = s; 0370 emit q->stateChanged(s); 0371 if (old == QwwSmtpClient::Connecting && s==QwwSmtpClient::Connected) emit q->connected(); 0372 if (s==QwwSmtpClient::Disconnected) emit q->disconnected(); 0373 } 0374 0375 void QwwSmtpClientPrivate::processNextCommand(bool ok) { 0376 if (inProgress && !commandqueue.isEmpty()) { 0377 emit q->commandFinished(commandqueue.head().id, !ok); 0378 commandqueue.dequeue(); 0379 } 0380 if (commandqueue.isEmpty()) { 0381 inProgress = false; 0382 emit q->done(false); 0383 return; 0384 } 0385 SMTPCommand &cmd = commandqueue.head(); 0386 switch (cmd.type) { 0387 case SMTPCommand::Connect: { 0388 QString hostName = cmd.data.toList().at(0).toString(); 0389 uint port = cmd.data.toList().at(1).toUInt(); 0390 bool ssl = cmd.data.toList().at(2).toBool(); 0391 if(ssl){ 0392 emit q->logSent(QByteArrayLiteral("*** connectToHostEncrypted: ") + hostName.toUtf8() + ':' + QByteArray::number(port)); 0393 socket->connectToHostEncrypted(hostName, port); 0394 } else { 0395 emit q->logSent(QByteArrayLiteral("*** connectToHost: ") + hostName.toUtf8() + ':' + QByteArray::number(port)); 0396 socket->connectToHost(hostName, port); 0397 } 0398 setState(QwwSmtpClient::Connecting); 0399 } 0400 break; 0401 case SMTPCommand::Disconnect: { 0402 sendQuit(); 0403 } 0404 break; 0405 case SMTPCommand::StartTLS: { 0406 QByteArray data("STARTTLS\r\n"); 0407 emit q->logSent(data); 0408 socket->write(data); 0409 setState(QwwSmtpClient::TLSRequested); 0410 } 0411 break; 0412 case SMTPCommand::Authenticate: { 0413 QwwSmtpClient::AuthMode authmode = (QwwSmtpClient::AuthMode)cmd.data.toList().at(0).toInt(); 0414 0415 if (authmode == QwwSmtpClient::AuthAny){ 0416 bool modified = false; 0417 if (authModes.testFlag(QwwSmtpClient::AuthPlain)) { 0418 authmode = QwwSmtpClient::AuthPlain; 0419 modified = true; 0420 } else if (authModes.testFlag(QwwSmtpClient::AuthLogin)) { 0421 authmode = QwwSmtpClient::AuthLogin; 0422 modified = true; 0423 } 0424 if (modified) { 0425 QVariantList data = cmd.data.toList(); 0426 data[0] = (int)authmode; 0427 cmd.data = data; 0428 } 0429 } 0430 0431 switch (authmode) { 0432 case QwwSmtpClient::AuthPlain: 0433 { 0434 QByteArray buf("AUTH PLAIN\r\n"); 0435 emit q->logSent(buf); 0436 socket->write(buf); 0437 setState(QwwSmtpClient::Authenticating); 0438 break; 0439 } 0440 case QwwSmtpClient::AuthLogin: 0441 { 0442 QByteArray buf("AUTH LOGIN\r\n"); 0443 emit q->logSent(buf); 0444 socket->write(buf); 0445 setState(QwwSmtpClient::Authenticating); 0446 break; 0447 } 0448 default: 0449 errorString = QwwSmtpClient::tr("Unsupported or unknown authentication scheme"); 0450 emit q->done(false); 0451 } 0452 } 0453 break; 0454 case SMTPCommand::Mail: 0455 case SMTPCommand::MailBurl: 0456 { 0457 setState(QwwSmtpClient::Sending); 0458 QByteArray buf = QByteArray("MAIL FROM:<").append(cmd.data.toList().at(0).toByteArray()).append(">\r\n"); 0459 emit q->logSent(buf); 0460 socket->write(buf); 0461 break; 0462 } 0463 case SMTPCommand::RawCommand: { 0464 QString cont = cmd.data.toString(); 0465 if(!cont.endsWith("\r\n")) cont.append("\r\n"); 0466 setState(QwwSmtpClient::Sending); 0467 auto buf = cont.toUtf8(); 0468 emit q->logSent(buf); 0469 socket->write(buf); 0470 } break; 0471 } 0472 inProgress = true; 0473 emit q->commandStarted(cmd.id); 0474 } 0475 0476 void QwwSmtpClientPrivate::_q_encrypted() { 0477 options = QwwSmtpClient::NoOptions; 0478 // forget everything, restart ehlo 0479 // SMTPCommand &cmd = commandqueue.head(); 0480 sendEhlo(); 0481 } 0482 0483 0484 void QwwSmtpClientPrivate::sendEhlo() { 0485 SMTPCommand &cmd = commandqueue.head(); 0486 QString domain = localName; 0487 if (socket->isEncrypted() && !localNameEncrypted.isEmpty()) 0488 domain = localNameEncrypted; 0489 QByteArray buf = QString("EHLO "+domain+"\r\n").toUtf8(); 0490 emit q->logSent(buf); 0491 socket->write(buf); 0492 cmd.extra = 1; 0493 } 0494 0495 0496 void QwwSmtpClientPrivate::sendHelo() { 0497 SMTPCommand &cmd = commandqueue.head(); 0498 QString domain = localName; 0499 if (socket->isEncrypted() && localNameEncrypted.isEmpty()) 0500 domain = localNameEncrypted; 0501 QByteArray buf = QString("HELO "+domain+"\r\n").toUtf8(); 0502 emit q->logSent(buf); 0503 socket->write(buf); 0504 cmd.extra = 1; 0505 } 0506 0507 0508 void QwwSmtpClientPrivate::sendQuit() { 0509 QByteArray buf("QUIT\r\n"); 0510 emit q->logSent(buf); 0511 socket->write(buf); 0512 socket->waitForBytesWritten(1000); 0513 socket->disconnectFromHost(); 0514 setState(QwwSmtpClient::Disconnecting); 0515 } 0516 0517 void QwwSmtpClientPrivate::sendRcpt() { 0518 SMTPCommand &cmd = commandqueue.head(); 0519 QVariantList vlist = cmd.data.toList(); 0520 QList<QVariant> rcptlist = vlist.at(1).toList(); 0521 QByteArray buf = QByteArray("RCPT TO:<").append(rcptlist.first().toByteArray()).append(">\r\n"); 0522 emit q->logSent(buf); 0523 socket->write(buf); 0524 rcptlist.removeFirst(); 0525 vlist[1] = rcptlist; 0526 cmd.data = vlist; 0527 0528 if (rcptlist.isEmpty()) cmd.extra = 1; 0529 } 0530 0531 0532 0533 void QwwSmtpClientPrivate::sendAuthPlain(const QString & username, const QString & password) { 0534 QByteArray ba; 0535 ba.append('\0'); 0536 ba.append(username.toUtf8()); 0537 ba.append('\0'); 0538 ba.append(password.toUtf8()); 0539 QByteArray encoded = ba.toBase64(); 0540 emit q->logSent(QByteArrayLiteral("*** [sending authentication data: username '") + username.toUtf8() + "']"); 0541 socket->write(encoded); 0542 socket->write("\r\n"); 0543 } 0544 0545 void QwwSmtpClientPrivate::sendAuthLogin(const QString & username, const QString & password, int stage) { 0546 if (stage==1) { 0547 QByteArray buf = username.toUtf8().toBase64() + "\r\n"; 0548 emit q->logSent(buf); 0549 socket->write(buf); 0550 } else if (stage==2) { 0551 emit q->logSent("*** [AUTH LOGIN password]"); 0552 socket->write(password.toUtf8().toBase64()); 0553 socket->write("\r\n"); 0554 } 0555 } 0556 0557 void QwwSmtpClientPrivate::parseOption(const QString &buffer){ 0558 if(buffer.toLower()=="pipelining"){ options |= QwwSmtpClient::PipeliningOption; } 0559 else if(buffer.toLower()=="starttls"){ options |= QwwSmtpClient::StartTlsOption; } 0560 else if(buffer.toLower()=="8bitmime"){ options |= QwwSmtpClient::EightBitMimeOption; } 0561 else if(buffer.toLower().startsWith("auth ")){ options |= QwwSmtpClient::AuthOption; 0562 // parse auth modes 0563 QStringList slist = buffer.mid(5).split(" "); 0564 foreach(const QString &s, slist){ 0565 if(s.toLower()=="plain"){ 0566 authModes |= QwwSmtpClient::AuthPlain; 0567 } 0568 if(s.toLower()=="login"){ 0569 authModes |= QwwSmtpClient::AuthLogin; 0570 } 0571 } 0572 } 0573 } 0574 0575 0576 QwwSmtpClient::QwwSmtpClient(QObject *parent) 0577 : QObject(parent), d(new QwwSmtpClientPrivate(this)) { 0578 d->state = Disconnected; 0579 d->lastId = 0; 0580 d->inProgress = false; 0581 d->localName = "localhost"; 0582 d->socket = new QSslSocket(this); 0583 connect(d->socket, SIGNAL(connected()), this, SLOT(onConnected())); 0584 connect(d->socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)) ); 0585 connect(d->socket, SIGNAL(disconnected()), this, SLOT(onDisconnected())); 0586 connect(d->socket, SIGNAL(readyRead()), this, SLOT(_q_readFromSocket())); 0587 connect(d->socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SIGNAL(sslErrors(const QList<QSslError>&))); 0588 } 0589 0590 0591 QwwSmtpClient::~QwwSmtpClient() { 0592 delete d; 0593 } 0594 0595 int QwwSmtpClient::connectToHost(const QString & hostName, quint16 port) { 0596 SMTPCommand cmd; 0597 cmd.type = SMTPCommand::Connect; 0598 cmd.data = QVariantList() << hostName << port << false; 0599 cmd.id = ++d->lastId; 0600 d->commandqueue.enqueue(cmd); 0601 if (!d->inProgress) 0602 d->processNextCommand(); 0603 return cmd.id; 0604 } 0605 0606 // int QwwSmtpClient::connectToHost(const QHostAddress & address, quint16 port) { 0607 // d->socket->connectToHost(address, port); 0608 // d->setState(Connecting); 0609 // } 0610 0611 0612 int QwwSmtpClient::connectToHostEncrypted(const QString & hostName, quint16 port) 0613 { 0614 SMTPCommand cmd; 0615 cmd.type = SMTPCommand::Connect; 0616 cmd.data = QVariantList() << hostName << port << true; 0617 cmd.id = ++d->lastId; 0618 d->commandqueue.enqueue(cmd); 0619 if(!d->inProgress) 0620 d->processNextCommand(); 0621 return cmd.id; 0622 } 0623 0624 int QwwSmtpClient::disconnectFromHost() { 0625 SMTPCommand cmd; 0626 cmd.type = SMTPCommand::Disconnect; 0627 cmd.id = ++d->lastId; 0628 d->commandqueue.enqueue(cmd); 0629 if (!d->inProgress) 0630 d->processNextCommand(); 0631 return cmd.id; 0632 } 0633 0634 int QwwSmtpClient::startTls() { 0635 connect(d->socket, SIGNAL(encrypted()), this, SLOT(_q_encrypted()), Qt::UniqueConnection); 0636 SMTPCommand cmd; 0637 cmd.type = SMTPCommand::StartTLS; 0638 cmd.id = ++d->lastId; 0639 d->commandqueue.enqueue(cmd); 0640 if (!d->inProgress) 0641 d->processNextCommand(); 0642 return cmd.id; 0643 } 0644 0645 void QwwSmtpClient::setLocalName(const QString & ln) { 0646 d->localName = ln; 0647 } 0648 0649 void QwwSmtpClient::setLocalNameEncrypted(const QString & ln) { 0650 d->localNameEncrypted = ln; 0651 } 0652 0653 0654 int QwwSmtpClient::authenticate(const QString &user, const QString &password, AuthMode mode) { 0655 SMTPCommand cmd; 0656 cmd.type = SMTPCommand::Authenticate; 0657 cmd.data = QVariantList() << (int)mode << user << password; 0658 cmd.id = ++d->lastId; 0659 d->commandqueue.enqueue(cmd); 0660 if (!d->inProgress) 0661 d->processNextCommand(); 0662 return cmd.id; 0663 } 0664 0665 int QwwSmtpClient::sendMail(const QByteArray &from, const QList<QByteArray> &to, const QByteArray &content) 0666 { 0667 QList<QVariant> rcpts; 0668 for(QList<QByteArray>::const_iterator it = to.begin(); it != to.end(); it ++) { 0669 rcpts.append(QVariant(*it)); 0670 } 0671 SMTPCommand cmd; 0672 cmd.type = SMTPCommand::Mail; 0673 cmd.data = QVariantList() << from << QVariant(rcpts) << content; 0674 cmd.id = ++d->lastId; 0675 d->commandqueue.enqueue(cmd); 0676 if (!d->inProgress) 0677 d->processNextCommand(); 0678 return cmd.id; 0679 } 0680 0681 int QwwSmtpClient::sendMailBurl(const QByteArray &from, const QList<QByteArray> &to, const QByteArray &url) 0682 { 0683 QList<QVariant> rcpts; 0684 for(QList<QByteArray>::const_iterator it = to.begin(); it != to.end(); it ++) { 0685 rcpts.append(QVariant(*it)); 0686 } 0687 SMTPCommand cmd; 0688 cmd.type = SMTPCommand::MailBurl; 0689 cmd.data = QVariantList() << from << QVariant(rcpts) << url; 0690 cmd.id = ++d->lastId; 0691 d->commandqueue.enqueue(cmd); 0692 if (!d->inProgress) 0693 d->processNextCommand(); 0694 return cmd.id; 0695 } 0696 0697 int QwwSmtpClient::rawCommand(const QString & raw) { 0698 SMTPCommand cmd; 0699 cmd.type = SMTPCommand::RawCommand; 0700 cmd.data = raw; 0701 cmd.id = ++d->lastId; 0702 d->commandqueue.enqueue(cmd); 0703 if (!d->inProgress) 0704 d->processNextCommand(); 0705 return cmd.id; 0706 } 0707 0708 0709 void QwwSmtpClientPrivate::abortDialog() { 0710 emit q->commandFinished(commandqueue.head().id, true); 0711 commandqueue.clear(); 0712 sendQuit(); 0713 } 0714 0715 void QwwSmtpClient::ignoreSslErrors() 0716 {d->socket->ignoreSslErrors(); 0717 } 0718 0719 QwwSmtpClient::AuthModes QwwSmtpClient::supportedAuthModes() const{ 0720 return d->authModes; 0721 } 0722 0723 QwwSmtpClient::Options QwwSmtpClient::options() const{ 0724 return d->options; 0725 } 0726 0727 QString QwwSmtpClient::errorString() const{ 0728 return d->errorString; 0729 } 0730 0731 #include "moc_qwwsmtpclient.cpp"