Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Send an Email with attachment
Forum Updated to NodeBB v4.3 + New Features

Send an Email with attachment

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 4 Posters 8.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • O onek24

    If you won't find an appropriate solution, maybe SMTP would be a solution for you. You can write one for yourself using the QSslSocket or use an existing one.

    CharlieGC Offline
    CharlieGC Offline
    CharlieG
    wrote on last edited by
    #6

    @onek24
    Yes this is a solution, but the user will have to configure the server while I wish that he can use his native client (with address book, ...).

    In fact I would like to do like the "Send by mail" options of Word, LibreOffice or Calligra. So I looked at the source code of Calligra and it seems to use the ShellExecuteW command (in KToolInvocation::invokMailer), but I can not get it to work.

    Do you have a track?

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #7

      Actually you might have found the solution yourself, just build KService library and link to it to be able to use invokMailer.
      Unfortunately that module does not work on android so you'll probably have to implement an android-only solution in an #ifdef

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      CharlieGC 1 Reply Last reply
      0
      • VRoninV VRonin

        Actually you might have found the solution yourself, just build KService library and link to it to be able to use invokMailer.
        Unfortunately that module does not work on android so you'll probably have to implement an android-only solution in an #ifdef

        CharlieGC Offline
        CharlieGC Offline
        CharlieG
        wrote on last edited by
        #8

        Hello

        @VRonin
        Do you know build KService ? I don't found the way to do

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by VRonin
          #9

          It's super easy as it uses CMake. what OS and compiler are you on?

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          CharlieGC 1 Reply Last reply
          0
          • VRoninV VRonin

            It's super easy as it uses CMake. what OS and compiler are you on?

            CharlieGC Offline
            CharlieGC Offline
            CharlieG
            wrote on last edited by
            #10

            @VRonin
            I don't use CMake and currently my app have to run on Windows (7, 8 & 10), Mac and Android. For Android I will use Android Extra.

            I think I understood how build KService. I tested this WE.

            Thank.

            1 Reply Last reply
            0
            • CharlieGC Offline
              CharlieGC Offline
              CharlieG
              wrote on last edited by CharlieG
              #11

              Hi,

              By helping me with this topic, I try to send an email with native client of my Android Device.

              Here is my codes

              //JavaClass.java in /android/src/com/company/myapp
              package com.comany.myapp;
              import android.content.Intent;
              import android.app.Activity;
              import android.util.Log;
              import android.net.Uri;
              import org.qtproject.qt5.android.bindings.QtActivity;
              public class JavaClass extends QtActivity {
                  private static JavaClass m_instance;
                  public JavaClass()
                  {
                      Log.d("Mailer::Mailer", "Constructor");
                      m_instance = this;
                  }
                  public static void sendMail(String attachmentFilename)
                  {
                      Log.d("Mailer::sendMail", "java-code: sendMail(): 1 file=" + attachmentFilename);
                      Log.d("Mailer::sendMail", "java-code: m_instance=" + m_instance);
                      String f = "file://" + attachmentFilename;
                      Uri uri = Uri.parse(f);
                      try{
                          Intent intent = new Intent(Intent.ACTION_SEND);
                          intent.setType("message/rfc822");
                          intent.putExtra(Intent.EXTRA_SUBJECT, "CSV export");
                          //intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"abc@gmail.com"});
                          //intent.putExtra(Intent.EXTRA_STREAM, uri);
                          Log.d("Mailer::sendMail", "java-code: sendMail(): 2");
                          Intent mailer = Intent.createChooser(intent, null);
                          Log.d("Mailer::sendMail", "java-code: sendMail(): 3");
                          if(mailer == null){
                              Log.e("Mailer::sendMail", "Couldn't get Mail Intent");
                              return;
                          }
                          Log.d("Mailer", "java-code: mailer    =" + mailer);
                          Log.d("Mailer", "java-code: m_instance=" + m_instance);
                          m_instance.getApplicationContext().startActivity(mailer);
                          Log.d("Mailer::sendMail", "java-code: sendMail(): 4");
                      }
                      catch (android.content.ActivityNotFoundException ex){
                          Log.e("Mailer", "catched android.content.ActivityNotFoundException while starting activity");
                          ex.printStackTrace();
                      }
                      Log.d("Mailer", "java-code: notify(): END");
                  }
              }
              
              
              //My C++ function
              QAndroidJniObject javaFilenameStr = QAndroidJniObject::fromString(attachment);
              qDebug() << "call QAndroidJniObject::callStaticMethod to send " << attachment;
              QAndroidJniObject::callStaticMethod<void>(
              "com/company/myapp/JavaClass",
              "sendMail",
              "(Ljava/lang/String;)V", javaFilenameStr.object<jstring>());
              
              
              //and a part of my AndroidManifest.xml
              <activity
                          android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
                          android:name="com.company.myapp.JavaClass"
                          android:label="-- %%INSERT_APP_NAME%% --"
                          android:screenOrientation="unspecified" android:launchMode="singleTop">
              
              

              Currently, I think have a problem with this line
              m_instance.getApplicationContext().startActivity(mailer);

              Here are the output messages of the application when I run a first time my C++ function :

              ...
              D Mailer::sendMail: java-code: m_instance=com.company.myapp.JavaClass@8a067fd
              D Mailer::sendMail: java-code: sendMail(): 2
              D Mailer::sendMail: java-code: sendMail(): 3
              D Mailer : java-code: mailer =Intent { act=android.intent.action.CHOOSER (has extras) }
              D Mailer : java-code: m_instance=com.company.myapp.JavaClass@8a067fd
              

              If I run a second time my function, the app crash with many messages including :

              F art : art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI NewString called with pending exception android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
              

              What do you think about ?

              Thank you in advance.

              Charlie.

              jsulmJ 1 Reply Last reply
              0
              • CharlieGC CharlieG

                Hi,

                By helping me with this topic, I try to send an email with native client of my Android Device.

                Here is my codes

                //JavaClass.java in /android/src/com/company/myapp
                package com.comany.myapp;
                import android.content.Intent;
                import android.app.Activity;
                import android.util.Log;
                import android.net.Uri;
                import org.qtproject.qt5.android.bindings.QtActivity;
                public class JavaClass extends QtActivity {
                    private static JavaClass m_instance;
                    public JavaClass()
                    {
                        Log.d("Mailer::Mailer", "Constructor");
                        m_instance = this;
                    }
                    public static void sendMail(String attachmentFilename)
                    {
                        Log.d("Mailer::sendMail", "java-code: sendMail(): 1 file=" + attachmentFilename);
                        Log.d("Mailer::sendMail", "java-code: m_instance=" + m_instance);
                        String f = "file://" + attachmentFilename;
                        Uri uri = Uri.parse(f);
                        try{
                            Intent intent = new Intent(Intent.ACTION_SEND);
                            intent.setType("message/rfc822");
                            intent.putExtra(Intent.EXTRA_SUBJECT, "CSV export");
                            //intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"abc@gmail.com"});
                            //intent.putExtra(Intent.EXTRA_STREAM, uri);
                            Log.d("Mailer::sendMail", "java-code: sendMail(): 2");
                            Intent mailer = Intent.createChooser(intent, null);
                            Log.d("Mailer::sendMail", "java-code: sendMail(): 3");
                            if(mailer == null){
                                Log.e("Mailer::sendMail", "Couldn't get Mail Intent");
                                return;
                            }
                            Log.d("Mailer", "java-code: mailer    =" + mailer);
                            Log.d("Mailer", "java-code: m_instance=" + m_instance);
                            m_instance.getApplicationContext().startActivity(mailer);
                            Log.d("Mailer::sendMail", "java-code: sendMail(): 4");
                        }
                        catch (android.content.ActivityNotFoundException ex){
                            Log.e("Mailer", "catched android.content.ActivityNotFoundException while starting activity");
                            ex.printStackTrace();
                        }
                        Log.d("Mailer", "java-code: notify(): END");
                    }
                }
                
                
                //My C++ function
                QAndroidJniObject javaFilenameStr = QAndroidJniObject::fromString(attachment);
                qDebug() << "call QAndroidJniObject::callStaticMethod to send " << attachment;
                QAndroidJniObject::callStaticMethod<void>(
                "com/company/myapp/JavaClass",
                "sendMail",
                "(Ljava/lang/String;)V", javaFilenameStr.object<jstring>());
                
                
                //and a part of my AndroidManifest.xml
                <activity
                            android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
                            android:name="com.company.myapp.JavaClass"
                            android:label="-- %%INSERT_APP_NAME%% --"
                            android:screenOrientation="unspecified" android:launchMode="singleTop">
                
                

                Currently, I think have a problem with this line
                m_instance.getApplicationContext().startActivity(mailer);

                Here are the output messages of the application when I run a first time my C++ function :

                ...
                D Mailer::sendMail: java-code: m_instance=com.company.myapp.JavaClass@8a067fd
                D Mailer::sendMail: java-code: sendMail(): 2
                D Mailer::sendMail: java-code: sendMail(): 3
                D Mailer : java-code: mailer =Intent { act=android.intent.action.CHOOSER (has extras) }
                D Mailer : java-code: m_instance=com.company.myapp.JavaClass@8a067fd
                

                If I run a second time my function, the app crash with many messages including :

                F art : art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI NewString called with pending exception android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
                

                What do you think about ?

                Thank you in advance.

                Charlie.

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #12

                @CharlieG The error message says it actually: you either start your activity from an activity context or set the FLAG_ACTIVITY_NEW_TASK flag (probably in m_instance.getApplicationContext().startActivity(mailer);). I'm not an android expert, so I cannot tell you what exactly you need to change.

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1
                • CharlieGC Offline
                  CharlieGC Offline
                  CharlieG
                  wrote on last edited by
                  #13

                  Hi,

                  In fact, this is very easy :

                  Intent mailer = Intent.createChooser(intent, null);
                  mailer.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                  

                  Now I have to figure out how to do with the desktop device.
                  Unfortunately, for now, I can't run KService's KToolInvocation :: invokMailer function.

                  VRoninV 1 Reply Last reply
                  0
                  • CharlieGC CharlieG

                    Hi,

                    In fact, this is very easy :

                    Intent mailer = Intent.createChooser(intent, null);
                    mailer.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    

                    Now I have to figure out how to do with the desktop device.
                    Unfortunately, for now, I can't run KService's KToolInvocation :: invokMailer function.

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #14

                    @CharlieG said in Send an Email with attachment:

                    Unfortunately, for now, I can't run KService

                    Any more details? can we help?

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    CharlieGC 1 Reply Last reply
                    0
                    • VRoninV VRonin

                      @CharlieG said in Send an Email with attachment:

                      Unfortunately, for now, I can't run KService

                      Any more details? can we help?

                      CharlieGC Offline
                      CharlieGC Offline
                      CharlieG
                      wrote on last edited by
                      #15

                      Hi,

                      Sorry for the late response.

                      @VRonin

                      Any more details? can we help?

                      Maybe ;-)

                      In the first time, I wanted directly try the code of invokMailer in my app :

                      On Windows, here is the code :

                      ...
                      #include "shellapi.h"
                      ...
                      
                      void KToolInvocation::invokeMailer(const QString &_to, const QString &_cc, const QString &_bcc,
                                                              const QString &subject, const QString &body,
                                                              const QString & /*messageFile TODO*/, const QStringList &attachURLs,
                                                              const QByteArray &startup_id)
                      {
                          QUrl url(QLatin1String("mailto:") + _to);
                          QUrlQuery query;
                          query.addQueryItem(QStringLiteral("subject"), subject);
                          query.addQueryItem(QStringLiteral("cc"), _cc);
                          query.addQueryItem(QStringLiteral("bcc"), _bcc);
                          query.addQueryItem(QStringLiteral("body"), body);
                          foreach (const QString &attachURL, attachURLs) {
                              query.addQueryItem(QStringLiteral("attach"), attachURL);
                          }
                          url.setQuery(query);
                      
                           #ifndef _WIN32_WCE
                              QString sOpen = QLatin1String("open");
                              ShellExecuteW(0, (LPCWSTR)sOpen.utf16(), (LPCWSTR)url.url().utf16(), 0, 0, SW_NORMAL);
                          #else
                              SHELLEXECUTEINFO cShellExecuteInfo = {0};
                              cShellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
                              cShellExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
                              cShellExecuteInfo.hwnd = NULL;
                              cShellExecuteInfo.lpVerb = L"Open";
                              cShellExecuteInfo.lpFile = (LPCWSTR)url.url().utf16();
                              cShellExecuteInfo.nShow = SW_SHOWNORMAL;
                              ShellExecuteEx(&cShellExecuteInfo);
                         #endif
                      }
                      

                      I can run the code, but the attachment isn't in the mail.

                      On Linux and Mac OSX, the function is replace by QDesktopService::openUrl(mailtoUrl). If I want directly use the code of invokeMailer, I have a problem with include "shellapi.h"

                      So I turn around...

                      Have you an idea ?

                      Bye and thank.

                      Charlie

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved