Line data Source code
1 : #pragma once
2 :
3 : #include <QObject>
4 : #include <QSslSocket>
5 : #include <QStringList>
6 : #include <QTimer>
7 :
8 : #include "data/AccountConfig.h"
9 :
10 : // SmtpService handles sending emails via SMTP with STARTTLS or SSL.
11 : // Asynchronous: emits sendSuccess/sendFailed signals.
12 : class SmtpService : public QObject {
13 15 : Q_OBJECT
14 : #ifdef MAILJD_UNIT_TEST
15 : friend class TestSmtpService;
16 : #endif
17 :
18 : public:
19 : explicit SmtpService(QObject *parent = nullptr);
20 : ~SmtpService() override;
21 :
22 : // Send an email. The message should be a complete RFC 5322 message.
23 : // from: envelope sender, recipients: all envelope recipients
24 : void sendMail(const SmtpConfig &config, const QString &from,
25 : const QStringList &recipients, const QByteArray &message);
26 :
27 : #ifdef MAILJD_UNIT_TEST
28 : static bool ehloResponseSupportsAuthLoginForTest(const QString &response);
29 : static bool ehloResponseSupportsStartTlsForTest(const QString &response);
30 : #endif
31 :
32 : signals:
33 : void sendSuccess();
34 : void sendFailed(const QString &error);
35 : void statusMessage(const QString &message);
36 :
37 : private slots:
38 : void onConnected();
39 : void onEncrypted();
40 : void onReadyRead();
41 : void onError(QAbstractSocket::SocketError error);
42 :
43 : private:
44 : enum class State {
45 : Disconnected,
46 : Connecting,
47 : WaitGreeting,
48 : WaitEhlo,
49 : WaitStartTls,
50 : WaitEhloAfterTls,
51 : WaitAuth,
52 : WaitAuthUser,
53 : WaitAuthPass,
54 : WaitMailFrom,
55 : WaitRcptTo,
56 : WaitData,
57 : WaitDataContent,
58 : WaitQuit,
59 : };
60 :
61 : struct EhloCapabilities {
62 : bool supportsStartTls = false;
63 : QStringList authMechanisms;
64 : };
65 :
66 : static EhloCapabilities parseEhloCapabilities(const QString &response);
67 : void resetSessionState();
68 : void failResponseTooLarge();
69 : bool appendResponseText(const QString &text);
70 : void processResponse(const QString &line);
71 : bool beginAuthLogin();
72 : void sendCommand(const QString &cmd);
73 : void nextRcptTo();
74 :
75 : QSslSocket *m_socket = nullptr;
76 : State m_state = State::Disconnected;
77 : SmtpConfig m_config;
78 : QString m_from;
79 : QStringList m_recipients;
80 : QByteArray m_message;
81 : int m_rcptIndex = 0;
82 : QString m_responseBuffer;
83 : EhloCapabilities m_ehloCapabilities;
84 : QTimer *m_timeoutTimer = nullptr; // T-612/SEC-11: Timeout for each SMTP phase
85 : static constexpr qint64 MaxResponseBufferSize = 64 * 1024;
86 : };
|