Can't send file via SMTP protocol
-
@razorqhex
That is not adding error handling, and does not tell us for sure what the situation is. You should follow @jsulm's suggestion.@JonB, I wrote an error handler and this is what it outputs.

It seems to me that the problem is in this block of code:
QByteArray boundary = "boundary_12345"; QByteArray messageData; messageData.append("From: <YOUR_MAIL>\r\n"); messageData.append(QString("To: <%1>\r\n").arg(ui->lEdit_addrFrom->text()).toUtf8()); messageData.append(QString("Subject: %1\r\n").arg(subject).toUtf8()); messageData.append("\r\n"); messageData.append(QString(body).toUtf8() + "\r\n.\r\n"); messageData.append(QString("Content-Type: multipart/mixed; boundary=%1\r\n").arg(boundary).toUtf8()); messageData.append("\r\n"); messageData.append(QString("--%1\r\n").arg(boundary).toUtf8()); messageData.append("Content-Type: text/plain\r\n"); messageData.append("\r\n"); messageData.append(body.toUtf8()); messageData.append("\r\n"); messageData.append(QString("--%1\r\n").arg(boundary).toUtf8()); messageData.append(QString("Content-Disposition: attachment; filename=\"%1\"\r\n").arg(QFileInfo(fileName).fileName()).toUtf8()); messageData.append(QString("Content-Type: %1\r\n").arg(mime.name()).toUtf8()); messageData.append("Content-Transfer-Encoding: base64\r\n"); messageData.append("\r\n"); socket.flush(); messageData.append(fileData.toBase64()); messageData.append("\r\n"); messageData.append(QString("--%1--\r\n").arg(boundary).toUtf8()); socket.write(messageData); socket.flush();But I don't know exactly what the problem is.
-
@razorqhex You should add error handling. For example connect a slot to
https://doc.qt.io/qt-6/qabstractsocket.html#errorOccurred and print out the error. -
@JonB, I wrote an error handler and this is what it outputs.

It seems to me that the problem is in this block of code:
QByteArray boundary = "boundary_12345"; QByteArray messageData; messageData.append("From: <YOUR_MAIL>\r\n"); messageData.append(QString("To: <%1>\r\n").arg(ui->lEdit_addrFrom->text()).toUtf8()); messageData.append(QString("Subject: %1\r\n").arg(subject).toUtf8()); messageData.append("\r\n"); messageData.append(QString(body).toUtf8() + "\r\n.\r\n"); messageData.append(QString("Content-Type: multipart/mixed; boundary=%1\r\n").arg(boundary).toUtf8()); messageData.append("\r\n"); messageData.append(QString("--%1\r\n").arg(boundary).toUtf8()); messageData.append("Content-Type: text/plain\r\n"); messageData.append("\r\n"); messageData.append(body.toUtf8()); messageData.append("\r\n"); messageData.append(QString("--%1\r\n").arg(boundary).toUtf8()); messageData.append(QString("Content-Disposition: attachment; filename=\"%1\"\r\n").arg(QFileInfo(fileName).fileName()).toUtf8()); messageData.append(QString("Content-Type: %1\r\n").arg(mime.name()).toUtf8()); messageData.append("Content-Transfer-Encoding: base64\r\n"); messageData.append("\r\n"); socket.flush(); messageData.append(fileData.toBase64()); messageData.append("\r\n"); messageData.append(QString("--%1--\r\n").arg(boundary).toUtf8()); socket.write(messageData); socket.flush();But I don't know exactly what the problem is.
@razorqhex Your mail data is malformed (see my previous)
This is what a well-formed SMTP conversation should look like:
EHLO host.example.com MAIL FROM: sender@example.com RCPT TO: recipient@example.com DATA From: sender@example.com To: recipient@example.com Subject: Test email Content-Type: multipart/mixed; boundary="test-boundary" This is the preamble. It is to be ignored, though it is a handy place for mail composers to include an explanatory note to non-MIME compliant readers. --test-boundary Content-Type: text/plain; charset=utf-8 Body text --test-boundary Content-Disposition: attachment; filename="test.png" Content-Type: image/png Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9 kT1Iw1AUhU/TiiIVBzuoOGSoThZERQQXrUIRKoRaoVUHk5f+QZOGJMXFUXAtOPizWHVwcdbVwVUQ BH9AXF2cFF2kxPuSQosYLzzex3n3HN67DxDqZaZZoTFA020zlYiLmeyq2PmKIAYQQAgzMrOMOUlK wre+7qmT6i7Gs/z7/qweNWcxICASzzLDtIk3iKc2bYPzPnGEFWWV+Jx41KQLEj9yXfH4jXPBZYFn Rsx0ap44QiwW2lhpY1Y0NeJJ4qiq6ZQvZDxWOW9x1spV1rwnf2E4p68sc53WEBJYxBIkiFBQRQll 2IjRrpNiIUXncR//oOuXyKWQqwRGjgVUoEF2/eB/8Hu2Vn5i3EsKx4GOF8f5GAY6d4FGzXG+jx2n cQIEn4ErveWv1IHpT9JrLS16BPRuAxfXLU3ZAy53gP4nQzZlVwrSEvJ54P2MvikL9N0C3Wve3Jrn OH0A0jSr5A1wcAiMFCh73efdXe1z+7enOb8fV1pynAvpCcAAAAAJcEhZcwAALiMAAC4jAXilP3YA AAAHdElNRQfnAxkBBS96QEB0AAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAA AChJREFUSMftzUENAAAIBKDT/p01hQ83KEBNbnUEAoFAIBAIBALBk2ABo8QBP1gd7ycAAAAASUVO RK5CYII= --test-boundary This is the epilogue. It is also to be ignored. . QUIT -
@razorqhex Your mail data is malformed (see my previous)
This is what a well-formed SMTP conversation should look like:
EHLO host.example.com MAIL FROM: sender@example.com RCPT TO: recipient@example.com DATA From: sender@example.com To: recipient@example.com Subject: Test email Content-Type: multipart/mixed; boundary="test-boundary" This is the preamble. It is to be ignored, though it is a handy place for mail composers to include an explanatory note to non-MIME compliant readers. --test-boundary Content-Type: text/plain; charset=utf-8 Body text --test-boundary Content-Disposition: attachment; filename="test.png" Content-Type: image/png Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9 kT1Iw1AUhU/TiiIVBzuoOGSoThZERQQXrUIRKoRaoVUHk5f+QZOGJMXFUXAtOPizWHVwcdbVwVUQ BH9AXF2cFF2kxPuSQosYLzzex3n3HN67DxDqZaZZoTFA020zlYiLmeyq2PmKIAYQQAgzMrOMOUlK wre+7qmT6i7Gs/z7/qweNWcxICASzzLDtIk3iKc2bYPzPnGEFWWV+Jx41KQLEj9yXfH4jXPBZYFn Rsx0ap44QiwW2lhpY1Y0NeJJ4qiq6ZQvZDxWOW9x1spV1rwnf2E4p68sc53WEBJYxBIkiFBQRQll 2IjRrpNiIUXncR//oOuXyKWQqwRGjgVUoEF2/eB/8Hu2Vn5i3EsKx4GOF8f5GAY6d4FGzXG+jx2n cQIEn4ErveWv1IHpT9JrLS16BPRuAxfXLU3ZAy53gP4nQzZlVwrSEvJ54P2MvikL9N0C3Wve3Jrn OH0A0jSr5A1wcAiMFCh73efdXe1z+7enOb8fV1pynAvpCcAAAAAJcEhZcwAALiMAAC4jAXilP3YA AAAHdElNRQfnAxkBBS96QEB0AAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAA AChJREFUSMftzUENAAAIBKDT/p01hQ83KEBNbnUEAoFAIBAIBALBk2ABo8QBP1gd7ycAAAAASUVO RK5CYII= --test-boundary This is the epilogue. It is also to be ignored. . QUIT@ChrisW67, I rewrote the code like this:
QByteArray boundary = "my_boundary"; QByteArray message; message.append(QString("From: ").toUtf8() + QString(from).toUtf8() + QString("\r\n").toUtf8()); message.append(QString("To: %1").arg(ui->lEdit_addrFrom->text()).toUtf8() + QString(to).toUtf8() + QString("\r\n").toUtf8()); message.append("Subject: " + QString(subject).toUtf8() + "\r\n"); message.append("MIME-Version: 1.0\r\n"); message.append("Content-Type: multipart/mixed; boundary=" + boundary + "\r\n\r\n"); // Body message.append("--" + boundary + "\r\n"); message.append("Content-Type: text/plain\r\n\r\n"); message.append(QString(body).toUtf8() + "\r\n\r\n"); // Attachment message.append("--" + boundary + "\r\n"); message.append("Content-Disposition: attachment; filename=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Type: " + mime.name().toUtf8() + "; name=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Transfer-Encoding: base64\r\n\r\n"); message.append(fileData.toBase64() + "\r\n\r\n"); // Completing a message message.append("--" + boundary + "--\r\n"); socket.write(message); socket.write(".\r\n"); socket.flush();And then I get a message with the correct attachment. But it still gets an error in this function:
//Message if (!socket.waitForBytesWritten()) { qDebug() << "Error MESSAGE on SMTP-server"; return; } if (!socket.waitForReadyRead()) { qDebug() << "Error"; return; }And with all this, the error handler is not called.
Is it still a mistake in the structure of the message or what? I don't understand anything in this world
-
@ChrisW67, I rewrote the code like this:
QByteArray boundary = "my_boundary"; QByteArray message; message.append(QString("From: ").toUtf8() + QString(from).toUtf8() + QString("\r\n").toUtf8()); message.append(QString("To: %1").arg(ui->lEdit_addrFrom->text()).toUtf8() + QString(to).toUtf8() + QString("\r\n").toUtf8()); message.append("Subject: " + QString(subject).toUtf8() + "\r\n"); message.append("MIME-Version: 1.0\r\n"); message.append("Content-Type: multipart/mixed; boundary=" + boundary + "\r\n\r\n"); // Body message.append("--" + boundary + "\r\n"); message.append("Content-Type: text/plain\r\n\r\n"); message.append(QString(body).toUtf8() + "\r\n\r\n"); // Attachment message.append("--" + boundary + "\r\n"); message.append("Content-Disposition: attachment; filename=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Type: " + mime.name().toUtf8() + "; name=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Transfer-Encoding: base64\r\n\r\n"); message.append(fileData.toBase64() + "\r\n\r\n"); // Completing a message message.append("--" + boundary + "--\r\n"); socket.write(message); socket.write(".\r\n"); socket.flush();And then I get a message with the correct attachment. But it still gets an error in this function:
//Message if (!socket.waitForBytesWritten()) { qDebug() << "Error MESSAGE on SMTP-server"; return; } if (!socket.waitForReadyRead()) { qDebug() << "Error"; return; }And with all this, the error handler is not called.
Is it still a mistake in the structure of the message or what? I don't understand anything in this world
@razorqhex said in Can't send file via SMTP protocol:
And then I get a message with the correct attachment. But it still gets an error in this function:
waitForBytesWritten()has a default value of 30 seconds as a timeout. If your operation takes longer than 30 seconds this function will return false and you'll see "Error MESSAGE on SMTP-server". -
@razorqhex said in Can't send file via SMTP protocol:
And then I get a message with the correct attachment. But it still gets an error in this function:
waitForBytesWritten()has a default value of 30 seconds as a timeout. If your operation takes longer than 30 seconds this function will return false and you'll see "Error MESSAGE on SMTP-server".@SimonSchroeder, I know, but the fact is that without any pauses, the waitForBytesWritten () function immediately executes
-
@SimonSchroeder, I know, but the fact is that without any pauses, the waitForBytesWritten () function immediately executes
@razorqhex Then you should try
qDebug() << socket.errorString();to figure out what's happening. -
@razorqhex Then you should try
qDebug() << socket.errorString();to figure out what's happening.@SimonSchroeder, this command show me "Unknown error"
-
@ChrisW67, I rewrote the code like this:
QByteArray boundary = "my_boundary"; QByteArray message; message.append(QString("From: ").toUtf8() + QString(from).toUtf8() + QString("\r\n").toUtf8()); message.append(QString("To: %1").arg(ui->lEdit_addrFrom->text()).toUtf8() + QString(to).toUtf8() + QString("\r\n").toUtf8()); message.append("Subject: " + QString(subject).toUtf8() + "\r\n"); message.append("MIME-Version: 1.0\r\n"); message.append("Content-Type: multipart/mixed; boundary=" + boundary + "\r\n\r\n"); // Body message.append("--" + boundary + "\r\n"); message.append("Content-Type: text/plain\r\n\r\n"); message.append(QString(body).toUtf8() + "\r\n\r\n"); // Attachment message.append("--" + boundary + "\r\n"); message.append("Content-Disposition: attachment; filename=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Type: " + mime.name().toUtf8() + "; name=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Transfer-Encoding: base64\r\n\r\n"); message.append(fileData.toBase64() + "\r\n\r\n"); // Completing a message message.append("--" + boundary + "--\r\n"); socket.write(message); socket.write(".\r\n"); socket.flush();And then I get a message with the correct attachment. But it still gets an error in this function:
//Message if (!socket.waitForBytesWritten()) { qDebug() << "Error MESSAGE on SMTP-server"; return; } if (!socket.waitForReadyRead()) { qDebug() << "Error"; return; }And with all this, the error handler is not called.
Is it still a mistake in the structure of the message or what? I don't understand anything in this world
@razorqhex This could be because your call to QAbstractSocket::flush() has already written all the bytes to the underlying operating system. You then wait for more bytes to be written but there are none so you time out.
-
@razorqhex This could be because your call to QAbstractSocket::flush() has already written all the bytes to the underlying operating system. You then wait for more bytes to be written but there are none so you time out.
@ChrisW67, Yes! You're right! Thank you very much. The error was only that the logic of the code was incorrect.
I have corrected the structure of creating a message:
QByteArray boundary = "my_boundary"; QByteArray message; message.append(QString("From: ").toUtf8() + QString(from).toUtf8() + QString("\r\n").toUtf8()); // message.append(QString("To: %1").arg(ui->lEdit_addrFrom->text()).toUtf8() + QString(to).toUtf8() + QString("\r\n").toUtf8()); message.append(QString("To: ").toUtf8() + QString(to).toUtf8() + QString("\r\n").toUtf8()); message.append("Subject: " + QString(subject).toUtf8() + "\r\n"); message.append("MIME-Version: 1.0\r\n"); message.append("Content-Type: multipart/mixed; boundary=" + boundary + "\r\n\r\n"); // Body message.append("--" + boundary + "\r\n"); message.append("Content-Type: text/plain\r\n\r\n"); message.append(QString(body).toUtf8() + "\r\n\r\n"); // Attachment message.append("--" + boundary + "\r\n"); message.append("Content-Disposition: attachment; filename=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Type: " + mime.name().toUtf8() + "; name=\"" + fileInfo.fileName().toUtf8() + "\"\r\n"); message.append("Content-Transfer-Encoding: base64\r\n\r\n"); message.append(fileData.toBase64() + "\r\n\r\n"); // Completing a message message.append("--" + boundary + "--\r\n"); //==================================================================================== socket.write(message); socket.write(".\r\n"); // socket.flush();And also removed
socket.flush();when sending the MESSAGE command and when sending the QUIT commandAnd now everything works as it should. Once again thank you very much.
Now there is only one problem left to fix. Some SMTP servers do not understand Ukrainian and Russian encodings. Incomprehensible letters are shown instead of Cyrillic
UPD: I also corrected the encoding.
Where is the comment BODY
Instead of a linemessage.append("Content-Type: text/plain\r\n\r\n");Need to add
message.append("Content-Type: text/plain; charset=UTF-8\r\n\r\n");And above, where the addressee is formed, you need instead of this line
message.append("Content-Type: multipart/mixed; boundary=" + boundary + "\r\n\r\n");Write this line:
message.append("Content-Type: multipart/mixed; charset=UTF-8; boundary=" + boundary + "\r\n\r\n");Thank you all for your help :)
-
R razorqhex has marked this topic as solved on