Search code examples
androidhtmlgmailcodenameonemessage

Codename One Android sendMessage HTML


My app compiles and sends an HTML message with the following code:

String s = ...; // html text with normal & bold face, proportional & monospaced fonts, etc.
Message msg = new Message(s);
msg.setMimeType(Message.MIME_HTML);
sendMessage(subject, msg, recipients);

On iOS (iPhone X) this works, the Mail app opens with a correct html rendering of the text.

On Android (Samsung Tab A) this doesn't work:

  • Gmail app: shows plain text with newlines (no bold face etc.)
  • Email app (Samsung): plain text without newlines (dito)

(In the simulator with an email client I see the correct html source text.)

How can this be solved?

Perhaps this is related to https://github.com/codenameone/CodenameOne/issues/3101.

EDIT

Tested with the following HTML example:

<!DOCTYPE html>
<html>
<body>
<h2>Example</h2>
Text with <b>bold</b> and <i>italics</i>.<br>
This text on a new line.
</body>
</html>

With the following output (screenshots of reading the sent mails):

Output

By the way, when sending plain text instead of HTML, newlines don't show up in Gmail while they do in Samsung Email (see issue 3101).


Solution

  • It seems that things have changed quite a bit over the years. Html.fromHtml is deprecated for Build.VERSION.SDK_INT >= 24. It now requires an extra flag parameter, Html.FROM_HTML_MODE_LEGACY. However, the old version is still supported and does exactly that. There is also a version HtmlCompat.fromHtml, which is equivalent. Class Html supports a HTML subset, e.g. <b>, <i> and <font> are supported but not <html> and <body>.

    Next, the recommended way to send an html message has changed. Instead of using type "text/html", parameter EXTRA_TEXT and method fromHtml, we should use type "text/plain", supply a plain text using parameter EXTRA_TEXT (see below) and supply the raw HTML source text using parameter EXTRA_HTML_TEXT. Email clients that support (full) HTML will use EXTRA_HTML_TEXT, Email clients that don't fall back to EXTRA_TEXT.

    Then, it appears that Google has removed HTML support for Gmail a few years ago (why??). Using the above method, Gmail falls back to EXTRA_TEXT while Samsung Email supports EXTRA_HTML_TEXT and that gives correctly rendered HTML!

    What happens in Gmail is that HTML input is "sanitized", which seems to mean that only plain text comes out, with appropriate line breaks for <h1>, <br>, etc. No other formatting such as bold, italics or fonts is supported. The Html.fromHtml method is still useful to create the EXTRA_TEXT fallback text for Gmail.

    I tried many things using native code for Android but I could not get Gmail to render HTML correctly. I found a few different ways to get it working in Samsung Email; I will present the one that I think is how it should be done.

    Conclusion

    The code below is a workaround for issues https://github.com/codenameone/CodenameOne/issues/3101 and https://github.com/codenameone/CodenameOne/issues/3386.

    If you want to send HTML formatted text this will work in some e-mail clients (such as Samsung Email) and not in others (most notably Gmail). In the latter case you have to settle for sending plain text with some line break formatting only.

    If you want to send a mail containing plain text with line breaks, generate a String containing the text and <br> tags only, and send this as HTML using the code below. This gives the correct result in both Samsung Email and Gmail.

    package com.xx.yy;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Build;
    import android.text.Html;
    
    import com.codename1.impl.android.AndroidNativeUtil;
    import com.codename1.impl.android.IntentResultListener;
    import com.codename1.io.Log;
    
    public class AndroidNativeInterfaceImpl {
    
        // adapted from com.codename1.impl.android.AndroidImplementation.sendMessage()
        // pass HTML String, not Message; no attachments
        public void sendHTMLMessage(String recipient, String subject, String msg) {
    
            String[] recipients = new String[] { recipient };
    
            Intent emailIntent = new Intent(Intent.ACTION_SEND);
            emailIntent.putExtra(Intent.EXTRA_EMAIL, recipients);
            emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
    
            // deprecated
            //emailIntent.setType("text/html");
            //emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(msg));
    
            // new
            emailIntent.setType("text/plain");
            emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(msg, Html.FROM_HTML_MODE_LEGACY)); // fallback text for e.g. Gmail
            emailIntent.putExtra(Intent.EXTRA_HTML_TEXT, msg); // raw (full) HTML for e.g. Samsung Email
    
            AndroidNativeUtil.startActivityForResult(Intent.createChooser(emailIntent, "Send mail..."), new IntentResultListener() {
                public void onActivityResult (int requestCode, int resultCode, Intent data) {
                    Log.p("native sendHTMLMessage done");
                }
            });
        }
    
        public boolean isSupported() {
            return true;
        }
    }
    

    EDIT: Some useful links

    https://developer.android.com/reference/android/content/Intent.html#ACTION_SEND

    https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/text/Html.java

    Android - Send email with styled HTML

    Has Android's Gmail app removed the ability to send HTML emails via Intent?

    Sending HTML based email body using android intent