Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
PIM
KSmtp
Commits
2cbd60db
Commit
2cbd60db
authored
Jan 26, 2021
by
Laurent Montel
😁
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
run git clang-format
parent
25c364e4
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
208 additions
and
256 deletions
+208
-256
autotests/fakeserver.cpp
autotests/fakeserver.cpp
+7
-13
autotests/fakeserver.h
autotests/fakeserver.h
+3
-3
autotests/smtptest.cpp
autotests/smtptest.cpp
+36
-58
autotests/smtptest.h
autotests/smtptest.h
+1
-1
src/job.h
src/job.h
+2
-1
src/job_p.h
src/job_p.h
+5
-3
src/loginjob.cpp
src/loginjob.cpp
+21
-27
src/loginjob.h
src/loginjob.h
+6
-17
src/sendjob.cpp
src/sendjob.cpp
+7
-11
src/sendjob.h
src/sendjob.h
+2
-1
src/serverresponse_p.h
src/serverresponse_p.h
+3
-2
src/session.cpp
src/session.cpp
+26
-22
src/session.h
src/session.h
+6
-5
src/session_p.h
src/session_p.h
+4
-4
src/sessionthread.cpp
src/sessionthread.cpp
+34
-38
src/sessionthread_p.h
src/sessionthread_p.h
+3
-2
src/sessionuiproxy.h
src/sessionuiproxy.h
+2
-1
tests/logintest.cpp
tests/logintest.cpp
+40
-47
No files found.
autotests/fakeserver.cpp
View file @
2cbd60db
...
...
@@ -8,9 +8,9 @@
#include "fakeserver.h"
#include <QTest>
#include <QFile>
#include <QDebug>
#include <QFile>
#include <QTest>
FakeServer
::
FakeServer
(
QObject
*
parent
)
:
QThread
(
parent
)
...
...
@@ -25,17 +25,12 @@ QByteArray FakeServer::greeting()
QList
<
QByteArray
>
FakeServer
::
greetingAndEhlo
(
bool
multiline
)
{
return
QList
<
QByteArray
>
()
<<
greeting
()
<<
"C: EHLO 127.0.0.1"
<<
QByteArray
(
"S: 250"
)
+
(
multiline
?
'-'
:
' '
)
+
"Localhost ready to roll"
;
return
QList
<
QByteArray
>
()
<<
greeting
()
<<
"C: EHLO 127.0.0.1"
<<
QByteArray
(
"S: 250"
)
+
(
multiline
?
'-'
:
' '
)
+
"Localhost ready to roll"
;
}
QList
<
QByteArray
>
FakeServer
::
bye
()
{
return
{
"C: QUIT"
,
"S: 221 So long, and thanks for all the fish"
,
"X: "
};
return
{
"C: QUIT"
,
"S: 221 So long, and thanks for all the fish"
,
"X: "
};
}
FakeServer
::~
FakeServer
()
...
...
@@ -72,7 +67,7 @@ void FakeServer::newConnection()
m_clientSockets
<<
m_tcpServer
->
nextPendingConnection
();
connect
(
m_clientSockets
.
last
(),
&
QIODevice
::
readyRead
,
this
,
&
FakeServer
::
dataAvailable
);
//m_clientParsers << new KIMAP::ImapStreamParser( m_clientSockets.last(), true );
//
m_clientParsers << new KIMAP::ImapStreamParser( m_clientSockets.last(), true );
QVERIFY
(
m_clientSockets
.
size
()
<=
m_scenarios
.
size
());
...
...
@@ -125,7 +120,7 @@ void FakeServer::addScenarioFromFile(const QString &fileName)
// When loading from files we never have the authentication phase
// force jumping directly to authenticated state.
//scenario << preauth();
//
scenario << preauth();
while
(
!
file
.
atEnd
())
{
scenario
<<
file
.
readLine
().
trimmed
();
...
...
@@ -166,8 +161,7 @@ void FakeServer::writeServerPart(int scenarioNumber)
QList
<
QByteArray
>
scenario
=
m_scenarios
[
scenarioNumber
];
QTcpSocket
*
clientSocket
=
m_clientSockets
[
scenarioNumber
];
while
(
!
scenario
.
isEmpty
()
&&
(
scenario
.
first
().
startsWith
(
"S: "
)
||
scenario
.
first
().
startsWith
(
"W: "
)))
{
while
(
!
scenario
.
isEmpty
()
&&
(
scenario
.
first
().
startsWith
(
"S: "
)
||
scenario
.
first
().
startsWith
(
"W: "
)))
{
QByteArray
rule
=
scenario
.
takeFirst
();
if
(
rule
.
startsWith
(
"S: "
))
{
...
...
autotests/fakeserver.h
View file @
2cbd60db
...
...
@@ -9,10 +9,10 @@
#ifndef KSMTP_FAKESERVER_H
#define KSMTP_FAKESERVER_H
#include <Q
Thread
>
#include <Q
Mutex
>
#include <QTcpServer>
#include <QTcpSocket>
#include <Q
Mutex
>
#include <Q
Thread
>
Q_DECLARE_METATYPE
(
QList
<
QByteArray
>
)
...
...
@@ -46,7 +46,7 @@ private:
void
writeServerPart
(
int
scenarioNumber
);
void
readClientPart
(
int
scenarioNumber
);
QList
<
QList
<
QByteArray
>
>
m_scenarios
;
QList
<
QList
<
QByteArray
>>
m_scenarios
;
QTcpServer
*
m_tcpServer
;
mutable
QMutex
m_mutex
;
QList
<
QTcpSocket
*>
m_clientSockets
;
...
...
autotests/smtptest.cpp
View file @
2cbd60db
...
...
@@ -8,56 +8,46 @@
#include "smtptest.h"
#include <QTest>
#include "fakeserver.h"
#include "session.h"
#include "loginjob.h"
#include "sendjob.h"
#include "session.h"
#include <QTest>
void
SmtpTest
::
testHello_data
()
{
QTest
::
addColumn
<
QList
<
QByteArray
>
>
(
"scenario"
);
QTest
::
addColumn
<
QList
<
QByteArray
>>
(
"scenario"
);
QTest
::
addColumn
<
QString
>
(
"hostname"
);
QList
<
QByteArray
>
scenario
;
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
<<
"S: 250 Localhost ready to roll"
<<
FakeServer
::
bye
();
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
<<
"S: 250 Localhost ready to roll"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"EHLO OK"
)
<<
scenario
<<
QStringLiteral
(
"127.0.0.1"
);
scenario
.
clear
();
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
<<
"S: 500 Command was not recognized"
<<
"C: HELO 127.0.0.1"
<<
"S: 250 Localhost ready to roll"
<<
FakeServer
::
bye
();
<<
"S: 250 Localhost ready to roll"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"EHLO unknown"
)
<<
scenario
<<
QStringLiteral
(
"127.0.0.1"
);
scenario
.
clear
();
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
<<
"S: 502 Command not implemented"
<<
"C: HELO 127.0.0.1"
<<
"S: 250 Localhost ready to roll"
<<
FakeServer
::
bye
();
<<
"S: 250 Localhost ready to roll"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"EHLO not implemented"
)
<<
scenario
<<
QStringLiteral
(
"127.0.0.1"
);
scenario
.
clear
();
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO 127.0.0.1"
<<
"S: 502 Command not implemented"
<<
"C: HELO 127.0.0.1"
<<
"S: 500 Command was not recognized"
<<
FakeServer
::
bye
();
<<
"S: 500 Command was not recognized"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"ERROR"
)
<<
scenario
<<
QStringLiteral
(
"127.0.0.1"
);
scenario
.
clear
();
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO random.stranger"
<<
"S: 250 random.stranger ready to roll"
<<
FakeServer
::
bye
();
scenario
<<
FakeServer
::
greeting
()
<<
"C: EHLO random.stranger"
<<
"S: 250 random.stranger ready to roll"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"EHLO hostname"
)
<<
scenario
<<
QStringLiteral
(
"random.stranger"
);
}
...
...
@@ -86,53 +76,45 @@ void SmtpTest::testHello()
void
SmtpTest
::
testLoginJob_data
()
{
QTest
::
addColumn
<
QList
<
QByteArray
>
>
(
"scenario"
);
QTest
::
addColumn
<
QList
<
QByteArray
>>
(
"scenario"
);
QTest
::
addColumn
<
QString
>
(
"authMode"
);
QTest
::
addColumn
<
int
>
(
"errorCode"
);
QList
<
QByteArray
>
scenario
;
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN LOGIN"
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN LOGIN"
<<
"C: AUTH PLAIN AGxvZ2luAHBhc3N3b3Jk"
// [\0 + "login" + \0 + "password"].toBase64()
<<
"S: 235 Authenticated"
<<
FakeServer
::
bye
();
<<
"S: 235 Authenticated"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"Plain auth ok"
)
<<
scenario
<<
"Plain"
<<
0
;
scenario
.
clear
();
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN LOGIN"
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN LOGIN"
<<
"C: AUTH LOGIN"
<<
"S: 334 VXNlcm5hbWU6"
// "Username:".toBase64()
<<
"C: bG9naW4="
// "login".toBase64()
<<
"S: 334 UGFzc3dvcmQ6"
// "Password:".toBase64()
<<
"C: cGFzc3dvcmQ="
// "password".toBase64()
<<
"S: 235 Authenticated"
<<
FakeServer
::
bye
();
<<
"S: 334 VXNlcm5hbWU6"
// "Username:".toBase64()
<<
"C: bG9naW4="
// "login".toBase64()
<<
"S: 334 UGFzc3dvcmQ6"
// "Password:".toBase64()
<<
"C: cGFzc3dvcmQ="
// "password".toBase64()
<<
"S: 235 Authenticated"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"Login auth ok"
)
<<
scenario
<<
"Login"
<<
0
;
scenario
.
clear
();
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN"
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN"
<<
"C: AUTH PLAIN AGxvZ2luAHBhc3N3b3Jk"
// [\0 + "login" + \0 + "password"].toBase64()
<<
"S: 235 Authenticated"
<<
FakeServer
::
bye
();
<<
"S: 235 Authenticated"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"Login not supported"
)
<<
scenario
<<
"Login"
<<
0
;
scenario
.
clear
();
scenario
<<
FakeServer
::
greetingAndEhlo
(
false
)
// The login job won't even try to send AUTH, because it does not
// have any mechanisms to use
//<< "C: AUTH PLAIN AGxvZ2luAHBhc3N3b3Jk" // [\0 + "login" + \0 + "password"].toBase64()
//<< "S: 235 Authenticated"
// The login job won't even try to send AUTH, because it does not
// have any mechanisms to use
//<< "C: AUTH PLAIN AGxvZ2luAHBhc3N3b3Jk" // [\0 + "login" + \0 + "password"].toBase64()
//<< "S: 235 Authenticated"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"Auth not supported"
)
<<
scenario
<<
"Login"
<<
100
;
scenario
.
clear
();
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN"
scenario
<<
FakeServer
::
greetingAndEhlo
()
<<
"S: 250 AUTH PLAIN"
<<
"C: AUTH PLAIN AGxvZ2luAHBhc3N3b3Jk"
// [\0 + "login" + \0 + "password"].toBase64()
<<
"S: 535 Authorization failed"
<<
FakeServer
::
bye
();
<<
"S: 535 Authorization failed"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"Wrong password"
)
<<
scenario
<<
"Plain"
<<
100
;
}
...
...
@@ -179,19 +161,16 @@ void SmtpTest::testLoginJob()
void
SmtpTest
::
testSendJob_data
()
{
QTest
::
addColumn
<
QList
<
QByteArray
>
>
(
"scenario"
);
QTest
::
addColumn
<
QList
<
QByteArray
>>
(
"scenario"
);
QTest
::
addColumn
<
int
>
(
"errorCode"
);
QList
<
QByteArray
>
scenario
;
scenario
<<
FakeServer
::
greetingAndEhlo
(
false
)
<<
"C: MAIL FROM:<foo@bar.com>"
<<
"S: 530 Not allowed"
<<
FakeServer
::
bye
();
scenario
<<
FakeServer
::
greetingAndEhlo
(
false
)
<<
"C: MAIL FROM:<foo@bar.com>"
<<
"S: 530 Not allowed"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"Send not allowed"
)
<<
scenario
<<
100
;
scenario
.
clear
();
scenario
<<
FakeServer
::
greetingAndEhlo
(
false
)
<<
"C: MAIL FROM:<foo@bar.com>"
scenario
<<
FakeServer
::
greetingAndEhlo
(
false
)
<<
"C: MAIL FROM:<foo@bar.com>"
<<
"S: 250 ok"
<<
"C: RCPT TO:<bar@foo.com>"
<<
"S: 250 ok"
...
...
@@ -203,12 +182,11 @@ void SmtpTest::testSendJob_data()
<<
"C: .."
// Single dot becomes two
<<
"C: .."
// Single dot becomes two
<<
"C: ..."
// Two dots become three
<<
"C: ..Foo"
// .Foo becomes ..Foo
<<
"C: ..Foo"
// .Foo becomes ..Foo
<<
"C: End"
<<
"C: "
<<
"C: ."
<<
"S: 250 Ok transfer done"
<<
FakeServer
::
bye
();
<<
"S: 250 Ok transfer done"
<<
FakeServer
::
bye
();
QTest
::
newRow
(
"ok"
)
<<
scenario
<<
0
;
scenario
.
clear
();
...
...
autotests/smtptest.h
View file @
2cbd60db
...
...
@@ -31,7 +31,7 @@ private Q_SLOTS:
void
testSendJob
();
void
testSendJob_data
();
//TODO: (CL) Check if SendJob parses properly the data it gets before sending
//
TODO: (CL) Check if SendJob parses properly the data it gets before sending
};
#endif // KSMTP_SMTPTEST_H
src/job.h
View file @
2cbd60db
...
...
@@ -13,7 +13,8 @@
#include <KJob>
namespace
KSmtp
{
namespace
KSmtp
{
class
Session
;
class
SessionPrivate
;
class
JobPrivate
;
...
...
src/job_p.h
View file @
2cbd60db
...
...
@@ -10,13 +10,15 @@
#include "session.h"
namespace
KSmtp
{
namespace
KSmtp
{
class
SessionPrivate
;
class
JobPrivate
{
public:
JobPrivate
(
Session
*
session
,
const
QString
&
name
)
:
m_session
(
session
)
JobPrivate
(
Session
*
session
,
const
QString
&
name
)
:
m_session
(
session
)
,
m_name
(
name
)
{
}
...
...
@@ -40,4 +42,4 @@ public:
};
}
#endif //KSMTP_JOB_P_H
#endif //
KSMTP_JOB_P_H
src/loginjob.cpp
View file @
2cbd60db
...
...
@@ -7,8 +7,8 @@
*/
#include "loginjob.h"
#include "ksmtp_debug.h"
#include "job_p.h"
#include "ksmtp_debug.h"
#include "serverresponse_p.h"
#include "session_p.h"
...
...
@@ -21,20 +21,20 @@ extern "C" {
#include <sasl/sasl.h>
}
namespace
{
static
const
sasl_callback_t
callbacks
[]
=
{
{
SASL_CB_ECHOPROMPT
,
nullptr
,
nullptr
},
{
SASL_CB_NOECHOPROMPT
,
nullptr
,
nullptr
},
{
SASL_CB_GETREALM
,
nullptr
,
nullptr
},
{
SASL_CB_USER
,
nullptr
,
nullptr
},
{
SASL_CB_AUTHNAME
,
nullptr
,
nullptr
},
{
SASL_CB_PASS
,
nullptr
,
nullptr
},
{
SASL_CB_CANON_USER
,
nullptr
,
nullptr
},
{
SASL_CB_LIST_END
,
nullptr
,
nullptr
}
};
namespace
{
static
const
sasl_callback_t
callbacks
[]
=
{{
SASL_CB_ECHOPROMPT
,
nullptr
,
nullptr
},
{
SASL_CB_NOECHOPROMPT
,
nullptr
,
nullptr
},
{
SASL_CB_GETREALM
,
nullptr
,
nullptr
},
{
SASL_CB_USER
,
nullptr
,
nullptr
},
{
SASL_CB_AUTHNAME
,
nullptr
,
nullptr
},
{
SASL_CB_PASS
,
nullptr
,
nullptr
},
{
SASL_CB_CANON_USER
,
nullptr
,
nullptr
},
{
SASL_CB_LIST_END
,
nullptr
,
nullptr
}};
}
namespace
KSmtp
{
namespace
KSmtp
{
class
LoginJobPrivate
:
public
JobPrivate
{
public:
...
...
@@ -167,7 +167,7 @@ void LoginJob::handleResponse(const ServerResponse &r)
}
// Available authentication mechanisms
if
(
r
.
isCode
(
25
)
&&
r
.
text
().
startsWith
(
"AUTH "
))
{
//krazy:exclude=strings
if
(
r
.
isCode
(
25
)
&&
r
.
text
().
startsWith
(
"AUTH "
))
{
//
krazy:exclude=strings
d
->
sessionInternal
()
->
setAuthenticationMethods
(
r
.
text
().
remove
(
0
,
QByteArray
(
"AUTH "
).
count
()).
split
(
' '
));
d
->
authenticate
();
return
;
...
...
@@ -176,8 +176,7 @@ void LoginJob::handleResponse(const ServerResponse &r)
// Send account data
if
(
r
.
isCode
(
334
))
{
if
(
d
->
m_actualAuthMode
==
Plain
)
{
const
QByteArray
challengeResponse
=
'\0'
+
d
->
m_userName
.
toUtf8
()
+
'\0'
+
d
->
m_password
.
toUtf8
();
const
QByteArray
challengeResponse
=
'\0'
+
d
->
m_userName
.
toUtf8
()
+
'\0'
+
d
->
m_password
.
toUtf8
();
sendCommand
(
challengeResponse
.
toBase64
());
}
else
{
if
(
!
d
->
sasl_challenge
(
QByteArray
::
fromBase64
(
r
.
text
())))
{
...
...
@@ -230,17 +229,15 @@ bool LoginJobPrivate::sasl_interact()
while
(
interact
->
id
!=
SASL_CB_LIST_END
)
{
qCDebug
(
KSMTP_LOG
)
<<
"SASL_INTERACT Id"
<<
interact
->
id
;
switch
(
interact
->
id
)
{
case
SASL_CB_AUTHNAME
:
{
//case SASL_CB_USER:
case
SASL_CB_AUTHNAME
:
{
// case SASL_CB_USER:
qCDebug
(
KSMTP_LOG
)
<<
"SASL_CB_[USER|AUTHNAME]: '"
<<
m_userName
<<
"'"
;
const
auto
username
=
m_userName
.
toUtf8
();
interact
->
result
=
strdup
(
username
.
constData
());
interact
->
len
=
username
.
size
();
break
;
}
case
SASL_CB_PASS
:
{
case
SASL_CB_PASS
:
{
qCDebug
(
KSMTP_LOG
)
<<
"SASL_CB_PASS: [hidden]"
;
const
auto
pass
=
m_password
.
toUtf8
();
interact
->
result
=
strdup
(
pass
.
constData
());
...
...
@@ -280,8 +277,7 @@ bool LoginJobPrivate::sasl_challenge(const QByteArray &challenge)
}
Q_FOREVER
{
result
=
sasl_client_step
(
m_saslConn
,
challenge
.
isEmpty
()
?
nullptr
:
challenge
.
constData
(),
challenge
.
size
(),
&
m_saslClient
,
&
out
,
&
outLen
);
result
=
sasl_client_step
(
m_saslConn
,
challenge
.
isEmpty
()
?
nullptr
:
challenge
.
constData
(),
challenge
.
size
(),
&
m_saslClient
,
&
out
,
&
outLen
);
if
(
result
==
SASL_INTERACT
)
{
if
(
!
sasl_interact
())
{
q
->
setError
(
LoginJob
::
UserDefinedError
);
...
...
@@ -319,8 +315,7 @@ bool LoginJobPrivate::authenticate()
return
false
;
}
int
result
=
sasl_client_new
(
"smtp"
,
m_session
->
hostName
().
toUtf8
().
constData
(),
nullptr
,
nullptr
,
callbacks
,
0
,
&
m_saslConn
);
int
result
=
sasl_client_new
(
"smtp"
,
m_session
->
hostName
().
toUtf8
().
constData
(),
nullptr
,
nullptr
,
callbacks
,
0
,
&
m_saslConn
);
if
(
result
!=
SASL_OK
)
{
const
auto
saslError
=
QString
::
fromUtf8
(
sasl_errdetail
(
m_saslConn
));
q
->
setError
(
LoginJob
::
UserDefinedError
);
...
...
@@ -335,8 +330,7 @@ bool LoginJobPrivate::authenticate()
Q_FOREVER
{
qCDebug
(
KSMTP_LOG
)
<<
"Trying authmod"
<<
authMode
;
result
=
sasl_client_start
(
m_saslConn
,
authMode
.
constData
(),
&
m_saslClient
,
&
out
,
&
outLen
,
&
actualMech
);
result
=
sasl_client_start
(
m_saslConn
,
authMode
.
constData
(),
&
m_saslClient
,
&
out
,
&
outLen
,
&
actualMech
);
if
(
result
==
SASL_INTERACT
)
{
if
(
!
sasl_interact
())
{
sasl_dispose
(
&
m_saslConn
);
...
...
src/loginjob.h
View file @
2cbd60db
...
...
@@ -13,7 +13,8 @@
#include "job.h"
namespace
KSmtp
{
namespace
KSmtp
{
class
LoginJobPrivate
;
/**
* @brief The LoginJob class
...
...
@@ -26,25 +27,13 @@ class KSMTP_EXPORT LoginJob : public Job
public:
enum
EncryptionMode
{
Unencrypted
,
SSLorTLS
,
///< Use SSL/TLS encryption
STARTTLS
///< Use STARTTLS to upgrade an unencrypted connection to encrypted
SSLorTLS
,
///< Use SSL/TLS encryption
STARTTLS
///< Use STARTTLS to upgrade an unencrypted connection to encrypted
};
enum
AuthMode
{
UnknownAuth
,
Plain
,
Login
,
CramMD5
,
DigestMD5
,
NTLM
,
GSSAPI
,
Anonymous
,
XOAuth2
};
enum
AuthMode
{
UnknownAuth
,
Plain
,
Login
,
CramMD5
,
DigestMD5
,
NTLM
,
GSSAPI
,
Anonymous
,
XOAuth2
};
enum
LoginError
{
TokenExpired
=
KJob
::
UserDefinedError
+
1
};
enum
LoginError
{
TokenExpired
=
KJob
::
UserDefinedError
+
1
};
explicit
LoginJob
(
Session
*
session
);
~
LoginJob
()
override
;
...
...
src/sendjob.cpp
View file @
2cbd60db
...
...
@@ -8,21 +8,17 @@
#include "sendjob.h"
#include "job_p.h"
#include "serverresponse_p.h"
#include "ksmtp_debug.h"
#include "serverresponse_p.h"
#include <KLocalizedString>
namespace
KSmtp
{
namespace
KSmtp
{
class
SendJobPrivate
:
public
JobPrivate
{
public:
enum
Status
{
Idle
,
SendingReturnPath
,
SendingRecipients
,
SendingData
};
enum
Status
{
Idle
,
SendingReturnPath
,
SendingRecipients
,
SendingData
};
SendJobPrivate
(
SendJob
*
job
,
Session
*
session
,
const
QString
&
name
)
:
JobPrivate
(
session
,
name
)
...
...
@@ -61,7 +57,7 @@ SendJob::SendJob(Session *session)
void
SendJob
::
setFrom
(
const
QString
&
from
)
{
Q_D
(
SendJob
);
qDebug
()
<<
"void SendJob::setFrom(const QString &from) "
<<
from
;
qDebug
()
<<
"void SendJob::setFrom(const QString &from) "
<<
from
;
const
auto
start
=
from
.
indexOf
(
QLatin1Char
(
'<'
));
if
(
start
>
-
1
)
{
const
auto
end
=
qMax
(
start
,
from
.
indexOf
(
QLatin1Char
(
'>'
),
start
));
...
...
@@ -69,7 +65,7 @@ void SendJob::setFrom(const QString &from)
}
else
{
d
->
m_returnPath
=
QStringLiteral
(
"<%1>"
).
arg
(
from
);
}
qDebug
()
<<
"d->m_returnPath "
<<
d
->
m_returnPath
;
qDebug
()
<<
"d->m_returnPath "
<<
d
->
m_returnPath
;
}
void
SendJob
::
setTo
(
const
QStringList
&
to
)
...
...
@@ -131,7 +127,7 @@ void SendJob::handleResponse(const ServerResponse &r)
switch
(
d
->
m_status
)
{
case
SendJobPrivate
::
Idle
:
//TODO: anything to do here?
//
TODO: anything to do here?
break
;
case
SendJobPrivate
::
SendingReturnPath
:
...
...
src/sendjob.h
View file @
2cbd60db
...
...
@@ -13,7 +13,8 @@
#include "job.h"
namespace
KSmtp
{
namespace
KSmtp
{
class
SendJobPrivate
;
/**
* @brief The SendJob class
...
...
src/serverresponse_p.h
View file @
2cbd60db
...
...
@@ -10,7 +10,8 @@
#include <QByteArray>
namespace
KSmtp
{
namespace
KSmtp
{
class
ServerResponse
{
public:
...
...
@@ -28,4 +29,4 @@ private:
};
}
#endif //KSMTP_SERVERRESPONSE_P_H
#endif //
KSMTP_SERVERRESPONSE_P_H
src/session.cpp
View file @
2cbd60db
...
...
@@ -7,20 +7,20 @@
*/
#include "session.h"
#include "session_p.h"
#include "sessionthread_p.h"
#include "job.h"
#include "
serverresponse_p
.h"
#include "
ksmtp_debug
.h"
#include "loginjob.h"
#include "sendjob.h"
#include "ksmtp_debug.h"
#include "serverresponse_p.h"
#include "session_p.h"
#include "sessionthread_p.h"
#include <QEventLoop>
#include <QHostAddress>
#include <QHostInfo>
#include <QUrl>
#include <QEventLoop>
#include <QPointer>
#include <QSslSocket>
#include <QUrl>
using
namespace
KSmtp
;
...
...
@@ -97,14 +97,13 @@ Session::Session(const QString &hostName, quint16 port, QObject *parent)
QHostAddress
ip
;
QString
saneHostName
=
hostName
;
if
(
ip
.
setAddress
(
hostName
))
{
//saneHostName = QStringLiteral("[%1]").arg(hostName);
//
saneHostName = QStringLiteral("[%1]").arg(hostName);
}
d
->
m_thread
=
new
SessionThread
(
saneHostName
,
port
,
this
);
d
->
m_thread
->
start
();
connect
(
d
->
m_thread
,
&
SessionThread
::
sslError
,
d
,
&
SessionPrivate
::
handleSslError
);
connect
(
d
->
m_thread
,
&
SessionThread
::
sslError
,
d
,
&
SessionPrivate
::
handleSslError
);
}
Session
::~
Session
()
...
...
@@ -218,8 +217,7 @@ void Session::quitAndWait()
}
QEventLoop
loop
;
connect
(
this
,
&
Session
::
stateChanged
,
this
,
[
&
](
Session
::
State
state
)
{
connect
(
this
,
&
Session
::
stateChanged
,
this
,
[
&
](
Session
::
State
state
)
{
if
(
state
==
Session
::
Disconnected
)
{
loop
.
quit
();
}
...
...
@@ -246,14 +244,17 @@ void SessionPrivate::setState(Session::State s)
void
SessionPrivate
::
sendData
(
const
QByteArray
&
data
)
{
QMetaObject
::
invokeMethod
(
m_thread
,
[
this
,
data
]
{
m_thread
->
sendData
(
data
);
},
Qt
::
QueuedConnection
);
QMetaObject
::
invokeMethod
(
m_thread
,
[
this
,
data
]
{
m_thread
->
sendData
(
data
);
},
Qt
::
QueuedConnection
);
}
void
SessionPrivate
::
responseReceived
(
const
ServerResponse
&
r
)
{
//qCDebug(KSMTP_LOG) << "S:: [" << r.code() << "]" << (r.isMultiline() ? "-" : " ") << r.text();
//
qCDebug(KSMTP_LOG) << "S:: [" << r.code() << "]" << (r.isMultiline() ? "-" : " ") << r.text();
if
(
m_state
==
Session
::
Quitting
)
{
m_thread
->
closeSocket
();
...
...
@@ -271,11 +272,11 @@ void SessionPrivate::responseReceived(const ServerResponse &r)
return
;
}
}
else
if
(
r
.
isCode
(
25
))
{
if
(
r
.
text
().
startsWith
(
"SIZE "
))
{
//krazy:exclude=strings
if
(
r
.
text
().
startsWith
(
"SIZE "
))
{
//
krazy:exclude=strings
m_size
=
r
.
text
().
remove
(
0
,
QByteArray
(
"SIZE "
).
count
()).
toInt
();
}
else
if
(
r
.
text
()
==
"STARTTLS"
)
{
m_allowsTls
=
true
;
}
else
if
(
r
.
text
().
startsWith
(
"AUTH "
))
{
//krazy:exclude=strings
}
else
if
(
r
.
text
().
startsWith
(
"AUTH "
))
{
//
krazy:exclude=strings
setAuthenticationMethods
(
r
.
text
().
remove
(
0
,
QByteArray
(
"AUTH "
).
count
()).
split
(
' '
));
}
...
...
@@ -335,9 +336,12 @@ void SessionPrivate::socketDisconnected()
void
SessionPrivate
::
startSsl
(
QSsl
::
SslProtocol
version
)
{
QMetaObject
::
invokeMethod
(
m_thread
,
[
this
,
version
]
{
m_thread
->
startSsl
(
version
);
},
Qt
::
QueuedConnection
);