From 97c04923c88402ba64aaee8da35cfb66857ec023 Mon Sep 17 00:00:00 2001 From: saturneric Date: Sat, 12 Sep 2026 20:17:25 +0200 Subject: feat(smtp): add AUTH LOGIN support - support servers that offer LOGIN without other mechanisms - encode username and password as base64 prompt responses - restrict LOGIN authentication to secured connections - mark the connection authenticated after a successful exchange --- src/vmime/net/smtp/SMTPConnection.cpp | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src') diff --git a/src/vmime/net/smtp/SMTPConnection.cpp b/src/vmime/net/smtp/SMTPConnection.cpp index 07d03765..e7620f79 100644 --- a/src/vmime/net/smtp/SMTPConnection.cpp +++ b/src/vmime/net/smtp/SMTPConnection.cpp @@ -359,6 +359,47 @@ void SMTPConnection::authenticate() { return; } } + + // AUTH LOGIN, for the many servers that offer it and nothing else we + // can speak. Without SASL, PLAIN alone leaves those servers + // unreachable. Still inside the m_secured guard above: LOGIN sends the + // username and password as bare base64, which is encoding and not + // encryption, so it must never touch a cleartext socket. + const string login("LOGIN"); + + if (std::find(authMechs.begin(), authMechs.end(), login) != authMechs.end()) { + + const string username = getAuthenticator()->getUsername(); + const string password = getAuthenticator()->getPassword(); + + // LOGIN is a three-step conversation: the server prompts for each + // field with a 334 and we answer with one base64 line. + const auto sendBase64 = [&](const string& value) -> int { + utility::inputStreamStringAdapter in(value); + string encoded; + utility::outputStreamStringAdapter out(encoded); + + vmime::utility::encoder::b64Encoder encoder; + encoder.encode(in, out); + + m_socket->send(encoded + "\r\n"); + + shared_ptr resp = readResponse(); + return resp ? resp->getCode() : -1; + }; + + sendRequest(SMTPCommand::AUTH(login)); + + shared_ptr response = readResponse(); + + if (response && response->getCode() == 334) { + + if (sendBase64(username) == 334 && sendBase64(password) == 235) { + m_authenticated = true; + return; + } + } + } } #endif // VMIME_HAVE_SASL_SUPPORT -- cgit