How can an Android app send an email using K-9?

Hi

I am new to Android app development and writing an app which I want to send a plain text email using K-9. For that to work, AIUI K-9’s AndroidManifest.xml must include an activity with an intent-filter for android.intent.action.SENDTO, something like

            <intent-filter>
                <action android:name="android.intent.action.SENDTO" />
                <data android:scheme="mailto" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

As best I can tell K-9 does not have that.

Is there another way for an app to send a plain text email using K-9?

Here’s what I tried (/ and . in links changed to spaces because of new user restriction):

  • Viewed github com thunderbird thunderbird-android blob main app-k9mail src main AndroidManifest.xml and github com thunderbird thunderbird-android blob main app-k9mail src main AndroidManifes xml
  • Read FAQ
  • Searched all issues at github com thunderbird thunderbird-android issues for intent
  • Searched this forum for intent
  • Found related enhancement request github com thunderbird thunderbird-android issues 3231 “k9mail as default email app #3231” opened 2018 closed 2020
  • Found related enhancement request github com thunderbird thunderbird-android issues 7755 Add support for mailto URI on NFC tag.

The app supports android.intent.action.SENDTO.

GitHub supports searching code (if you have an account and are logged in). The code search has no trouble finding the relevant code.

1 Like

Thanks! Thanks too for the tip about searching github.

1 Like

In case anybody finds this thread while looking for how to write an app to send email using K-9, here’s my working solution.

It was built and tested in “Android Studio Ladybug | 2024.2.1 Patch 1” using emulator “Pixel Fold API 35 running Android 15 VanillaIceCream” (on Debian Bookworm, not that it should make any difference).

The most time consuming gotcha was changes in package visibility introduced in “Android 11 (API level 30)” requiring a queries section in AndroidManifest.xml. Ref (/ and . in links changed to spaces because of new user restriction) https developer android com training package-visibility use-cases

Here’s the queries section added to AndroidManifest.xml

    <queries>
        <intent>
            <action android:name="android.media.action.SENDTO" />
            <data android:scheme="mailto" />
        </intent>
    </queries>

The function developed to send email, in file MainActivity.kt, in class MainActivity, was:

    fun sendEmail(recipient: String, subject: String, body: String) {
        val emailIntent = Intent(Intent.ACTION_SENDTO).apply {
            data = Uri.parse("mailto:")
            putExtra(Intent.EXTRA_EMAIL, arrayOf(recipient))
            putExtra(Intent.EXTRA_SUBJECT, subject)
            putExtra(Intent.EXTRA_TEXT, body)
        }
        try {
            startActivity(emailIntent)
        } catch (e: ActivityNotFoundException) {
            Log.e(TAG, "sendEmail: startActivity exception caught")
        }
        finish()
    }

It is simple for proof of concept; it sends to a single recipient, no CC or BCC, plain text. The finish() is to close the app after sending the email.

It is called from function onCreate, in the same class:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sendEmail("<redacted>", "MyEmailSender: test", "Body text")
    }

The includes in MainActivity.kt were:

import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity

This does not actually send an email; it opens a K-9 compose window with fields populated. The user must click the send button.

1 Like

You might also be interested in Sending Email using Intents

Thanks I was very interested in Sending Email using Intents. I had searched widely and deeply using Brave, DuckDuckGo and Google but not found that page.

I migrated my app to use EmailIntentBuilder for robustness. The line added to app/build.gradle.kts was

implementation("de.cketti.mailto:email-intent-builder:2.0.0")

The import was

import de.cketti.mailto.EmailIntentBuilder

Then function sendEmail was

    fun sendEmail(recipient: String, subject: String, body: String) {
        val success: Boolean = EmailIntentBuilder.from(this)
            .to(recipient)
            .subject(subject)
            .body(body)
            .start()
        if (!success) Log.e(TAG, "sendEmail: EmailIntentBuilder exception caught")
        finish()
    }

That tested OK.

Then I removed the @ from the recipient address and re-tested. Got a Java traceback Caused by: java.lang.IllegalArgumentException: Argument is not a valid email address (according to Patterns.EMAIL_ADDRESS)

OK but better to trap and report the error so I changed to

fun sendEmail(recipient: String, subject: String, body: String) {
        val emailIntentBuilder = EmailIntentBuilder.from(this)
            .to(recipient)
            .subject(subject)
            .body(body)
        try {
            emailIntentBuilder.start()
        } catch (e: ActivityNotFoundException) {
            Log.e(TAG, "sendEmail: No email client installed or invalid intent")
        } catch (e: SecurityException) {
            Log.e(TAG, "sendEmail: Insufficient permissions")
        } catch (e: IllegalArgumentException) {
            Log.e(TAG, "sendEmail: IllegalArgumentException")
        }
        finish()
    }

When that was tested the app crashed with no Logcat message. An EmailIntentBuilder bug? I would like to discuss that before creating a bug report. If OK, where would you like to do that? I am not a twitter user.

Is it possible to bypass the K-9 compose window? So there’s no need for the user to click the send button? So no window is opened? So K-9 is used as a service, not an activity?

I would not like that an app which I did not configure for mail sending could just do it by coding with Intents… - IMO a security issue!

Don’t you still need to explicitly grant the app permission to use that intent?

If that is the case then it would be OK I guess…

1 Like