]> git.eshelyaron.com Git - emacs.git/commitdiff
Relay body and attachments within Android e-mails to message-mailto
authorPo Lu <luangruo@yahoo.com>
Thu, 19 Oct 2023 08:19:18 +0000 (16:19 +0800)
committerPo Lu <luangruo@yahoo.com>
Thu, 19 Oct 2023 08:19:36 +0000 (16:19 +0800)
* java/org/gnu/emacs/EmacsOpenActivity.java (onCreate): Infer
e-mail body and subject from its parameters and convey this
information to message-mailto.

* lisp/gnus/message.el (message-mailto): New arguments SUBJECT,
BODY and FILE-ATTACHMENTS.
(message-mailto-1): Insert these arguments as appropriate.

java/org/gnu/emacs/EmacsOpenActivity.java
lisp/gnus/message.el

index 202b3c8c5dca69b491b513b72df0dccee7a9c5f6..0c0da6acd1f7ae3c0ad45f90a4a871673c1ade14 100644 (file)
@@ -55,6 +55,7 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
 
 import android.util.Log;
 
@@ -67,6 +68,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 
+import java.util.List;
+
 public final class EmacsOpenActivity extends Activity
   implements DialogInterface.OnClickListener,
   DialogInterface.OnCancelListener
@@ -396,6 +399,7 @@ public final class EmacsOpenActivity extends Activity
      Finally, display any error message, transfer the focus to an
      Emacs frame, and finish the activity.  */
 
+  @SuppressWarnings ("deprecation") /* getParcelableExtra */
   @Override
   public void
   onCreate (Bundle savedInstanceState)
@@ -407,6 +411,11 @@ public final class EmacsOpenActivity extends Activity
     ParcelFileDescriptor fd;
     byte[] names;
     String errorBlurb, scheme;
+    String subjectString, textString, attachmentString;
+    CharSequence tem;
+    String tem1;
+    StringBuilder builder;
+    List<Parcelable> list;
 
     super.onCreate (savedInstanceState);
 
@@ -425,6 +434,7 @@ public final class EmacsOpenActivity extends Activity
     if (action.equals ("android.intent.action.VIEW")
        || action.equals ("android.intent.action.EDIT")
        || action.equals ("android.intent.action.PICK")
+       || action.equals ("android.intent.action.SEND")
        || action.equals ("android.intent.action.SENDTO"))
       {
        /* Obtain the URI of the action.  */
@@ -452,8 +462,110 @@ public final class EmacsOpenActivity extends Activity
            /* Escape the special characters $ and " before enclosing
               the string within the `message-mailto' wrapper.  */
            fileName = uri.toString ();
-           fileName.replace ("\"", "\\\"").replace ("$", "\\$");
-           fileName = "(message-mailto \"" + fileName + "\")";
+           fileName = (fileName
+                       .replace ("\\", "\\\\")
+                       .replace ("\"", "\\\"")
+                       .replace ("$", "\\$"));
+           fileName = "(message-mailto \"" + fileName + "\" ";
+
+           /* Parse the intent itself to ascertain if any
+              non-standard subject, body, or something else of the
+              like is set.  Such fields, non-standard as they are,
+              yield to fields provided within the URL itself; refer
+              to message-mailto.  */
+
+           textString = attachmentString = subjectString = "()";
+
+           tem = intent.getCharSequenceExtra (Intent.EXTRA_SUBJECT);
+
+           if (tem != null)
+             subjectString = ("\"" + (tem.toString ()
+                                      .replace ("\\", "\\\\")
+                                      .replace ("\"", "\\\"")
+                                      .replace ("$", "\\$"))
+                              + "\" ");
+
+           tem = intent.getCharSequenceExtra (Intent.EXTRA_TEXT);
+
+           if (tem != null)
+             textString = ("\"" + (tem.toString ()
+                                   .replace ("\\", "\\\\")
+                                   .replace ("\"", "\\\"")
+                                   .replace ("$", "\\$"))
+                           + "\" ");
+
+           /* Producing a list of attachments is prey to two
+              mannerisms of the system: in the first instance, these
+              attachments are content URIs which don't allude to
+              their content types; and in the second instance, they
+              are either a list of such URIs or one individual URI,
+              subject to the type of the intent itself.  */
+
+           if (Intent.ACTION_SEND.equals (action))
+             {
+               /* The attachment in this case is a single content
+                  URI.  */
+
+               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+                 uri = intent.getParcelableExtra (Intent.EXTRA_STREAM,
+                                                  Uri.class);
+               else
+                 uri = intent.getParcelableExtra (Intent.EXTRA_STREAM);
+
+               if (uri != null
+                   && (scheme = uri.getScheme ()) != null
+                   && scheme.equals ("content"))
+                 {
+                   tem1 = EmacsService.buildContentName (uri);
+                   attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\")
+                                                 .replace ("\"", "\\\"")
+                                                 .replace ("$", "\\$"))
+                                       + "\")");
+                 }
+             }
+           else
+             {
+               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+                 list
+                   = intent.getParcelableArrayListExtra (Intent.EXTRA_STREAM,
+                                                         Parcelable.class);
+               else
+                 list
+                   = intent.getParcelableArrayListExtra (Intent.EXTRA_STREAM);
+
+               if (list != null)
+                 {
+                   builder = new StringBuilder ("'(");
+
+                   for (Parcelable parcelable : list)
+                     {
+                       if (!(parcelable instanceof Uri))
+                         continue;
+
+                       uri = (Uri) parcelable;
+
+                       if (uri != null
+                           && (scheme = uri.getScheme ()) != null
+                           && scheme.equals ("content"))
+                         {
+                           tem1 = EmacsService.buildContentName (uri);
+                           builder.append ("\"");
+                           builder.append (tem1.replace ("\\", "\\\\")
+                                           .replace ("\"", "\\\"")
+                                           .replace ("$", "\\$"));
+                           builder.append ("\"");
+                         }
+                     }
+
+                   builder.append (")");
+                   attachmentString = builder.toString ();
+                 }
+             }
+
+           fileName += subjectString;
+           fileName += textString;
+           fileName += attachmentString;
+           fileName += ")";
 
            /* Execute emacsclient in order to execute this code.  */
            currentActivity = this;
index 969589bb942f9bf7195c27291893f18d27d253f4..0071c02c081caa62e210a5382b7851cda05a5288 100644 (file)
@@ -8971,32 +8971,61 @@ used to take the screenshot."
     retval))
 
 ;;;###autoload
-(defun message-mailto (&optional url)
+(defun message-mailto (&optional url subject body file-attachments)
   "Command to parse command line mailto: links.
 This is meant to be used for MIME handlers: Setting the handler
 for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
 will then start up Emacs ready to compose mail.  For emacsclient use
-  emacsclient -e \\='(message-mailto \"%u\")'"
+  emacsclient -e \\='(message-mailto \"%u\")'
+
+To facilitate the use of this function within window systems that
+provide message subject, body and attachments independent of URL
+itself, the arguments SUBJECT, BODY and FILE-ATTACHMENTS may also
+provide alternative message subject and body text, which is
+inserted in lieu of nothing if URL does not incorporate such
+information itself, and a list of files to insert as attachments
+to the E-mail."
   (interactive)
   ;; <a href="mailto:someone@example.com?subject=This%20is%20the%20subject&cc=someone_else@example.com&body=This%20is%20the%20body">Send email</a>
   (message-mail)
-  (message-mailto-1 (or url (pop command-line-args-left))))
+  (message-mailto-1 (or url (pop command-line-args-left))
+                    subject body file-attachments))
 
-(defun message-mailto-1 (url)
-  (let ((args (message-parse-mailto-url url)))
+(defun message-mailto-1 (url &optional subject body file-attachments)
+  (let ((args (message-parse-mailto-url url))
+        (need-body nil) (need-subject nil))
     (dolist (arg args)
       (unless (equal (car arg) "body")
        (message-position-on-field (capitalize (car arg)))
        (insert (string-replace
                 "\r\n" "\n"
                 (mapconcat #'identity (reverse (cdr arg)) ", ")))))
-    (when (assoc "body" args)
-      (message-goto-body)
-      (dolist (body (cdr (assoc "body" args)))
-       (insert body "\n")))
+    (if (assoc "body" args)
+        (progn
+          (message-goto-body)
+          (dolist (body (cdr (assoc "body" args)))
+           (insert body "\n")))
+      
+      (setq need-body t))
     (if (assoc "subject" args)
        (message-goto-body)
-      (message-goto-subject))))
+      (setq need-subject t)
+      (message-goto-subject))
+    ;; If either one of need-subject and need-body is non-nil then
+    ;; attempt to insert the absent information from an external
+    ;; SUBJECT or BODY.
+    (when (or need-body need-subject)
+      (when (and need-body body)
+        (message-goto-body)
+        (insert body))
+      (when (and need-subject subject)
+        (message-goto-subject)
+        (insert subject)
+        (message-goto-body)))
+    ;; Subsequently insert each attachment enumerated within
+    ;; FILE-ATTACHMENTS.
+    (dolist (file file-attachments)
+      (mml-attach-file file nil 'attachment))))
 
 (provide 'message)