'JavaMail API on Android
I'm trying to send an email on Android using the JavaMail API, it's just a simple test
But whenever I try to launch the app, this exception pops up
2020-09-23 13:23:42.442 21860-21971/ae.ucg.mailtest E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-2
Process: ae.ucg.mailtest, PID: 21860
java.lang.VerifyError: Rejecting class com.sun.mail.handlers.text_plain that attempts to sub-type erroneous class com.sun.mail.handlers.handler_base (declaration of 'com.sun.mail.handlers.text_plain' appears in /data/app/~~nyiEJPyVs6-ADHqg-ebklA==/ae.ucg.mailtest-_Q4dGJfXP_9F5CZNfhDVtQ==/base.apk)
at java.lang.Class.newInstance(Native Method)
at javax.activation.MailcapCommandMap.getDataContentHandler(MailcapCommandMap.java:601)
at javax.activation.MailcapCommandMap.createDataContentHandler(MailcapCommandMap.java:555)
at javax.activation.DataHandler.getDataContentHandler(DataHandler.java:597)
at javax.activation.DataHandler.writeTo(DataHandler.java:299)
at javax.mail.internet.MimeUtility.getEncoding(MimeUtility.java:316)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1551)
at javax.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2238)
at javax.mail.internet.MimeMessage.saveChanges(MimeMessage.java:2198)
at javax.mail.Transport.send(Transport.java:99)
at ae.ucg.mailtest.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:38)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Caused by: java.lang.VerifyError: Verifier rejected class com.sun.mail.handlers.handler_base: java.awt.datatransfer.DataFlavor[] com.sun.mail.handlers.handler_base.getTransferDataFlavors() failed to verify: java.awt.datatransfer.DataFlavor[] com.sun.mail.handlers.handler_base.getTransferDataFlavors(): [0x4] can't resolve returned type 'Unresolved Reference: java.awt.datatransfer.DataFlavor[]' or 'Reference: javax.activation.ActivationDataFlavor[]' (declaration of 'com.sun.mail.handlers.handler_base' appears in /data/app/~~nyiEJPyVs6-ADHqg-ebklA==/ae.ucg.mailtest-_Q4dGJfXP_9F5CZNfhDVtQ==/base.apk)
at java.lang.Class.newInstance(Native Method)
at javax.activation.MailcapCommandMap.getDataContentHandler(MailcapCommandMap.java:601)
at javax.activation.MailcapCommandMap.createDataContentHandler(MailcapCommandMap.java:555)
at javax.activation.DataHandler.getDataContentHandler(DataHandler.java:597)
at javax.activation.DataHandler.writeTo(DataHandler.java:299)
at javax.mail.internet.MimeUtility.getEncoding(MimeUtility.java:316)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1551)
at javax.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2238)
at javax.mail.internet.MimeMessage.saveChanges(MimeMessage.java:2198)
at javax.mail.Transport.send(Transport.java:99)
at ae.ucg.mailtest.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:38)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
I'm aware something is wrong in the library itself, but what exactly am I supposed to do?
This is my code
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch(Dispatchers.IO) {
try {
val props = Properties().apply {
this["mail.smtp.host"] = "smtp.gmail.com"
this["mail.smtp.socketFactory.port"] = "465"
this["mail.smtp.socketFactory.class"] = "javax.net.ssl.SSLSocketFactory"
this["mail.smtp.auth"] = "true"
this["mail.smtp.port"] = "465"
}
val session = Session.getDefaultInstance(props, object : Authenticator() {
override fun getPasswordAuthentication() = PasswordAuthentication(Config.EMAIL, Config.PASSWORD)
})
val message = MimeMessage(session).apply {
setFrom(InternetAddress(Config.EMAIL))
addRecipient(Message.RecipientType.TO, InternetAddress("..."))
subject = "Hello world"
setText("This is a hello world message", "UTF-8")
}
Transport.send(message)
} catch (e: Exception) {
Toast.makeText(this@MainActivity, e.message, Toast.LENGTH_LONG).show()
}
}
}
And this is the library I'm using
implementation 'com.sun.mail:android-mail:1.6.5'
implementation 'com.sun.mail:android-activation:1.6.5'
Solution 1:[1]
Apparently is this bug only on SDK level 30 (Android 11) and Google Admins are saying it's a feature... But here I found a solution
Use this in build.gradle
:
android {
...
packagingOptions {
exclude 'META-INF/NOTICE.md'
exclude 'META-INF/LICENSE.md'
}
}
dependencies {
implementation 'com.sun.mail:android-mail:1.6.6'
implementation 'com.sun.mail:android-activation:1.6.6'
...
}
credit to this issue
Solution 2:[2]
I ran into the same issue and there were a couple of things to note in order to resolve it:
- As other's (radda, and this answer) have mentioned, there's a Google Issue Tracker Issue that covers and provides why this issue is happening:
API level 30 adds a new (verifier) feature that verifies that all referenced code actually exists - or fails a build.
- Even in fixing the issue - by referencing and ensuring you're providing the referenced code (by, for instance, updating the dependencies to the latest - which at this time are 1.6.7); you'll find a build still throws a relatively straight forward complaint:
To resolve (and get up-to-date):
- If you were providing the libraries manually via
/app/libs/mail.jar
,/app/libs/activation.jar
, and/app/libs/additionnal.jar
- you can go ahead and remove them; bothgoogle()
andmaven()
repositories are enabled in Android projects - so simply add;
to your project-level gradle file (/build.gradle
):
buildscript {
ext {
// ...
java_mail_version = "1.6.7"
}
// ...
}
// ...
to your app/module-level gradle file (/app/build.gradle
):
//...
dependencies {
// ...
// Dumb Email Sending
implementation "com.sun.mail:android-mail:$java_mail_version"
// REMOVE THESE - DEPS WILL DOWNLOAD AUTOMATICALLY
//implementation 'com.sun.mail:android-activation:1.6.7' // from 1.6.4
//implementation 'com.sun.mail:android-additionnal:1.6.7' // from 1.6.4
}
// ...
...and with that you'll have resolved the 'latest version(s)' issue once and for all (including where to find them).
To resolve issue #2, add;
to that same app/module-level gradle file (/app/build.gradle
):
// ...
android {
// ...
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
excludes += '/META-INF/{NOTICE.md,LICENSE.md}' // <-- This line
}
}
}
// ...
That resolved it for me, and I'm happy not to have to manually lug around the .jar
files anymore:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Rik |