Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Send attachment by email



  • Hi to all,

    I'm on Windows and I'm using curl to send HTML content by adding it to the body email.
    It works fine with gmail accounts, but I noticed that some mail providers (i.e. yahoo, libero, and others) doesn't display the content.

    To fix this, I was thinking to send the HTML content as an attached web page, but I'm not able to correctly include the attachment.

    Here is my current code used to include the HTML content in the email body:

          QString prova = html_scheda_base64.toUtf8().toBase64();
          QString email_recipient = ui->email_edit->toPlainText();
          qDebug() << "utente selezionato" << ui->listautenti->currentText() << "Email: " << email_recipient;
          QString email_content= "From: test <test@test.com>\r";
          QString recipient = "To: <" + email_recipient + ">\r";
                  email_content += recipient;
                  email_content +="Subject: test!\r"
                                  "Reply-To: test <test@test.com>\r"
                                  "Cc:\r"
                                  "MIME-Version: 1.0\r"
                                  "Content-Type: multipart/mixed; boundary=\"MULTIPART-MIXED-BOUNDARY\"\r"
                                  "--MULTIPART-MIXED-BOUNDARY\r"
                                  "Content-Type: multipart/alternative; boundary=\"MULTIPART-ALTERNATIVE-BOUNDARY\"\r"
                                  "--MULTIPART-ALTERNATIVE-BOUNDARY\r"
                                  "Content-Type: text/html; charset=utf-8\r"
                                  "Content-Transfer-Encoding: base64\r"
                                  "Content-Disposition: inline\";\r";
          email_content+=prova;
          email_content+="\r--MULTIPART-ALTERNATIVE-BOUNDARY--\r"
                         "--MULTIPART-MIXED-BOUNDARY\r";
    
    
          QString filename = "C:/PUMP/email/mail.txt";
          QFile file_out(filename);
             // Trying to open in WriteOnly and Text mode
             if (!file_out.open(QIODevice::WriteOnly | QIODevice::Text))
             {
                 qDebug() << " Could not open file for writing: " << filename << "\n";
                 return;
             }
    
             QTextStream out(&file_out);
             out << email_content;
             file_out.flush();
             file_out.close();
    
          QString system_ctrl = "curl.exe --ssl-reqd -k --url smtp://smtp.gmail.com:587 --mail-from test@test.com --mail-rcpt test@test.com --user test@test.com:passwd --cacert cacert.pem --upload-file mail.txt --TLSv1.2 --tls-max 1.2 --verbose";
    
          ofstream batch_file;
          batch_file.open( "commands.cmd", ios::trunc );
          batch_file <<
              "cd C:\\PUMP\\email\\" << endl <<
              "curl.exe --ssl-reqd -k --url smtp://smtp.gmail.com:587 --mail-from test@test.com --mail-rcpt " << email_recipient.toStdString() << " --user test@test.com:passwd --cacert cacert.pem --upload-file mail.txt --TLSv1.2 --tls-max 1.2 --verbose" << endl;
          batch_file.close();
    
          int batch_exit_code = system( "cmd.exe /c commands.cmd" ); // blocks until the child process is terminated
          if( batch_exit_code != 0 ) {
              cout << "Batch file exited with code " << batch_exit_code << endl;
          }
    
          remove( "commands.cmd" ); // delete the batch file
          html_scheda_base64.clear();
    

    and this is the created TXT file:

    From: test <myemail@mail.com>
    To: <myemail@mail.com>
    Subject: test!
    Reply-To: <myemail@mail.com>
    Cc:
    MIME-Version: 1.0
    Content-Type: multipart/mixed; boundary="MULTIPART-MIXED-BOUNDARY"
    --MULTIPART-MIXED-BOUNDARY
    Content-Type: multipart/alternative; boundary="MULTIPART-ALTERNATIVE-BOUNDARY"
    --MULTIPART-ALTERNATIVE-BOUNDARY
    Content-Type: text/html; charset=utf-8
    Content-Transfer-Encoding: base64
    Content-Disposition: inline";
    
    MY BASE64 STRING
    
    --MULTIPART-ALTERNATIVE-BOUNDARY--
    --MULTIPART-MIXED-BOUNDARY
    

    How can I modify the code to include the attachment?
    Or, is there any other smart way to send an email in QT?



  • @Marcus-Barnet
    I tried Googling curl attachment for you, but beware this results in pages about either bench-press equipment or hair products! :) Better results from curl email attachment!

    https://sendgrid.com/docs/for-developers/sending-email/curl-examples/ or https://stackoverflow.com/questions/44728855/curl-send-html-email-with-embedded-image-and-attachment or others.

    If you want to send email internally from your Qt program instead of via an external command, there are quite a few hits for qt5 send email. I note that in this forum's https://forum.qt.io/topic/70601/how-to-send-email-using-qt-5-5-1 @VRonin suggested using libcurl which is a C++ library to do what the curl.exe program does, so you might want to go that way.



  • Maybe worth taking a look? http://trojita.flaska.net



  • @artwaw
    That is an IMAP client. Which means it is for retrieving (reading) email. The OP asks about sending email. Which will be SMTP, and IMAP client has nothing to do with that.



  • @JonB Yes but I think it would be easier to derive code from this library (which is written in Qt) in order to try and not to use external software.



  • @artwaw
    Sorry I don't agree with you or see the connection. Qt as distributed does not come with particular support for either IMAP or SMTP. SMTP code is required to send mail, and that is quite different code from IMAP. The OP will need SMTP code, and might as well use libcurl as that seems to be C++ and "standard". There is a lot to SMTP code and he won't want to write it from scratch. Whatever useful the IMAP has for Qt should be small compared to what is required for SMTP itself.

    However, if you say there are some ideas in the IMAP code you reference he might want to look at from the Qt perspective so be it.

    I would search for qt5 SMTP. There are a few hits out there. Maybe https://morf.lv/simple-tls-ssl-smtp-client-for-qt5 is useful, or I see there is cutelyst at https://github.com/cutelyst/simple-mail which says it is for Qt. Actually this looks like it might be quite appropriate:

    The SimpleMail is small library writen for Qt 5 or 6 (C++11) that allows applications to send complex emails (plain text, html, attachments, inline files, etc.) using the Simple Mail Transfer Protocol (SMTP).

    It includes support for the user's question about attachment.



  • @JonB Ok, indeed seems to be easier that way.



  • @JonB said in Send attachment by email:

    @artwaw
    Sorry I don't agree with you or see the connection. Qt as distributed does not come with particular support for either IMAP or SMTP. SMTP code is required to send mail, and that is quite different code from IMAP. The OP will need SMTP code, and might as well use libcurl as that seems to be C++ and "standard". There is a lot to SMTP code and he won't want to write it from scratch. Whatever useful the IMAP has for Qt should be small compared to what is required for SMTP itself.

    However, if you say there are some ideas in the IMAP code you reference he might want to look at from the Qt perspective so be it.

    I would search for qt5 SMTP. There are a few hits out there. Maybe https://morf.lv/simple-tls-ssl-smtp-client-for-qt5 is useful, or I see there is cutelyst at https://github.com/cutelyst/simple-mail which says it is for Qt. Actually this looks like it might be quite appropriate:

    The SimpleMail is small library writen for Qt 5 or 6 (C++11) that allows applications to send complex emails (plain text, html, attachments, inline files, etc.) using the Simple Mail Transfer Protocol (SMTP).

    It includes support for the user's question about attachment.

    Very interesting! I checked these two solutions and they seem to be very useful for what I would like to do!
    I'm going to explore better the second one since it looks like easier to implement.

    I'll keep you updated during next days! Thank you!!



  • The SmtpClient-for-Qt worked like a charm!

    Thanks for the support!



  • I'm sorry to re-open this topic, but I found out that there is an issue with my code.

    Everything works fine on the laptop I use to develop the code with QtCreator since I'm able to successfully send the emails with the SmtpClient-for-Qt library. I run the program from a folder I created by including all the DLLs that are necessary to run all the functions I used.

    The program runs and works fine also on other laptops, but when I try to send emails, I receveid the error: "cannot connect to the host".

    It was very strange to me since the same program runs correctly on my laptop, so I think the problem should be connected to some library or DLL that the program is able to find on my development laptop but it is not able to find on other computers even if I get no DLL missing errors when I start it.

    How do you think I can solve the problem?

    SmtpClient smtp("smtp.gmail.com", 465, SmtpClient::SslConnection);
    ..
    smtp.connectToHost();
    smtp.login();
    smtp.sendMail(message);
    

    I copied the SMTPEmail.dll into the program folder.
    Should I set some specific configuration during the build in QtCreator?

    I used several libraries and they perfectly work without problems!
    Only the SmptClient library is giving the issue.

    P.S. The same program is able to correctly send email via smtp by using curl (curl.exe --ssl-reqd -k --url smtp://smtp.gmail.com:587) on every laptop.



  • @Marcus-Barnet
    Here are several sundry possibilities:

    • Does the target have the OpenSSL libraries/support installed, which I understand is required for Qt SSL support?
    • Does the SMTP DLL have all its dependencies on the target machine (maybe run Dependency Walker on it)?
    • You are supposed to deploy a Qt program to a target machine, since it is not in the same state as a Qt development machine. Did you do that (e.g. windeployqt)?

  • Moderators

    @Marcus-Barnet
    if you're using the online installer, than you can download the correct openssl dlls there directly

    d4f9706f-11d4-4a5a-a080-1e28c446dfc7-image.png



  • Thank you for the support!
    The program worked fine on every laptop without errors, so I think all the previos libraries were correctly installed.
    I'm only having the problem with the SmtpClient-for-Qt.

    I used windeployqt to create the folder by following the instruction on https://doc.qt.io/qt-5/windows-deployment.html

    I'm trying to run Dependency Walker, but it as soon as I loaded the SMTPEmail.dll it got stuck.



  • This is the output of Dependency Walker:

    Error: At least one required implicit or forwarded dependency was not found.
    Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module.
    Error: Modules with different CPU types were found.
    Error: A circular dependency was detected.
    Warning: At least one delay-load dependency module was not found.
    Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.

    However, I'm able to run the program from its standalone folder from my development laptop.
    The problem occurs when I need to run it on other laptops even if I copy the whole folder.



  • @Marcus-Barnet said in Send attachment by email:

    Error: Modules with different CPU types were found.

    I don't know if this great. Compare the DW output with the machine where it does work?



  • @JonB said in Send attachment by email:

    @Marcus-Barnet said in Send attachment by email:

    Error: Modules with different CPU types were found.

    I don't know if this great. Compare the DW output with the machine where it does work?

    The output I posted has been generated by running DW from my delopment computer. I picked up the DLL from the folder I use to run the program standalone.

    I really can't understand since the program works fine if I run it both from the QtCreator run utility and from the folder I created on my development computer where I copied all the DLLs.



  • @Marcus-Barnet
    I don't think I understand. Why are you testing the running one and not the bad one?

    Can you please state clearly where it does not work? You said earlier it does not work on other machines?



  • The developed program is very simple: it connects to a MySQL database and retrieves some data depending on the user's input.
    The program works fine both on my development laptop and on ALL other laptops.
    To distribute the program on all other laptops, I created a folder where I put the executable and also all the required DLLs from QT and from the MySQL library.
    The executable works fine both on my computer and on the other laptops.

    Two days ago, I decided to include the SmtpClient-for-Qt library as you suggested in this topic but I need to provide the user to send some information by email.

    I integrated the smtp code in my program, I built it and I put the executable in the folder used to redistribute the program together with the SMTPEmail.dll (If I run the executable without this DLL, it gives me the missing DLL error for SMTPEmail.dll and for Qt5Network.dll, so I added them to the folder ).

    Now, the executable works fine and correctly send emails IF I run it from the folder ON MY laptop.
    The executable opens and runs fine also on all other computers but WHEN the user tries to SEND the email, it gives the error: "CANNOT connect to host".

    So the program runs correctly on ALL the laptops, but it gives the connection error when the user tries to send email from all other laptops (it works fine only on my development laptop).

    At the beginning, I thought about a network error, but all the laptops (included my laptop) are in the same network.

    This is the file list for the folder from where I run the program (it's the same both for my laptop and the other ones):

    27/05/2021  00:22    <DIR>          email
    07/03/2021  19:37    <DIR>          imageformats
    13/07/2017  13:29         4,879,360 libmysql.dll
    06/06/2021  21:11            16,996 myapp.res
    28/05/2021  22:43    <DIR>          pics
    07/03/2021  19:37    <DIR>          platforms
    06/06/2021  23:27         4,460,032 PUMP.exe
    17/05/2021  21:54           140,242 pump_db (1).sql
    20/05/2021  08:25           218,138 pump_db_20_05_21.sql
    11/05/2020  10:46         5,998,712 Qt5Core.dll
    11/05/2020  10:47         7,085,176 Qt5Gui.dll
    11/05/2020  10:47         1,349,240 Qt5Network.dll
    11/05/2020  10:47           208,504 Qt5Sql.dll
    11/05/2020  17:05           329,848 Qt5Svg.dll
    11/05/2020  10:47         5,516,920 Qt5Widgets.dll
    05/06/2021  00:21            74,240 SMTPEmail.dll
    07/03/2021  19:37    <DIR>          sqldrivers
    07/03/2021  19:37    <DIR>          styles
    

  • Moderators

    Like @JonB and I said in Send attachment by email:

    Does the target have the OpenSSL libraries/support installed, which I understand is required for Qt SSL support?

    Your open SSL DLLs are missing from the installation folder, they are apparently part of your system path (on your development pc) but you can't guarantee that for all systems-> The reason why it fails on other machines.
    Provide them.

    26752d2d-0799-4661-b9aa-3943a4e3398e-image.png



  • I'm going to check this even if I receive no errors about these missing DDLs when I run the program on the other systems.
    Shouldn't I receive an error as soon as I try to run the program?


  • Moderators

    @Marcus-Barnet said in Send attachment by email:

    I'm going to check this even if I receive no errors about these missing DDLs when I run the program on the other systems.
    Shouldn't I receive an error as soon as I try to run the program?

    no, in this case its a silent fail,

    silent, in so much as, you should (technically) a get a console output about a failed loading



  • @Marcus-Barnet said in Send attachment by email:

    Shouldn't I receive an error as soon as I try to run the program?

    Not if the OpenSSL stuff is dynamically loaded (e.g. when the first call is made to send using encryption) instead of statically linked. Which may be what @J-Hilk is indicating is the case.



  • Thank you, guys!

    Now, it works fine! I copied both files to the folder and the program runs fine on all laptops.


Log in to reply