Mail versenden in Kotlin

  • Antworten:37
  • Bentwortet
Robbiani Renato
  • Forum-Beiträge: 606

30.04.2020, 21:16:31 via Website

Hallo zusammen

Ich möchte mit Kotlin ein Mail versenden. Ich finde aber nur Beispiele für Java.

Kann man in Kotlin keine Mail versenden. Falls es doch geht, hat jemand ein Beispiel dafür.

Ich habe es mal auf diesem Weg versucht. Aber der führt nur zu einem Absturz.

private fun sendMail(){
    var to : String
    var cc : String
    val mailsender = Intent(ctx, Intent.ACTION_SEND::class.java)

    to = "renato_robbiani@bluewin.ch"
    cc = "renato.robbiani@robbisoft.ch"

    mailsender.setData(Uri.parse("mailto:"))
    mailsender.setType("text/plain")
    mailsender.putExtra(Intent.EXTRA_EMAIL, to)
    mailsender.putExtra(Intent.EXTRA_CC, cc)
    mailsender.putExtra(Intent.EXTRA_SUBJECT, "Test")
    mailsender.putExtra(Intent.EXTRA_TEXT, "Das ist eine E-Mail")

    startActivity(Intent.createChooser(mailsender, "Send mail..."));
}

Gruss Renato

Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.528

02.05.2020, 12:34:33 via Website

Solltest du wirklich nichts Passendes finden. Hier eine Klasse die eine Mail mit Datei Anhang sendet. Mit der Java API.
Hatte ich in Java und habe sie in Kotlin übersetz.

class SendMail(private val attachFilePath: String) : AsyncTask<Void?, Void?, Void?>() {

private val EMAIL = "..." // SMTP Mail Account
private val PASSWORD = "..." // SMTP PW
private val SMTPHOST = "..." // SMTP Adresse
private var session: Session? = null

//Information to send email
private val email = "...@..." // Empfänger Adresse
private val subject = "Hallo"
private val message = "Neue Daten"

protected override fun doInBackground(vararg params: Void?): Void? {
    //Creating properties
    val props = Properties()
    props.setProperty("mail.transport.protocol", "smtp")
    props["mail.smtp.host"] = SMTPHOST
    props["mail.smtp.socketFactory.port"] = "465"
    props["mail.smtp.port"] = "465"
    props["mail.smtp.socketFactory.class"] = "javax.net.ssl.SSLSocketFactory"
    props["mail.smtp.auth"] = "true"
    props["mail.smtp.socketFactory.fallback"] = "false"
    props.setProperty("mail.smtp.quitwait", "false")

    //Creating a new session
    session = Session.getDefaultInstance(props, object : Authenticator() {
        //Authenticating the password
        override fun getPasswordAuthentication(): PasswordAuthentication {
            return PasswordAuthentication(EMAIL, PASSWORD)
        }
    })
    try {
        //Creating MimeMessage object
        val mm = MimeMessage(session)
        //Setting sender address
        mm.setFrom(InternetAddress(EMAIL))
        mm.addRecipient(Message.RecipientType.TO, InternetAddress(email))
        mm.subject = subject
        val mp: Multipart = MimeMultipart()
        val htmlPart = MimeBodyPart()
        htmlPart.setContent(message, "text/plain")
        mp.addBodyPart(htmlPart)
        val attachment = MimeBodyPart()
        val source: DataSource = FileDataSource(attachFilePath)
        attachment.dataHandler = DataHandler(source)
        attachment.fileName = File(attachFilePath).name
        mp.addBodyPart(attachment)
        mm.setContent(mp)
        //Sending email
        Transport.send(mm)
    } catch (e: MessagingException) {
        e.printStackTrace()
    }
    return null
}

}

aufruf der Klasse

    var sm2 =  SendMail("path zum Mail Anhang")
    sm2.execute()

natürlich brauchst du auch die libs und musst sie auch unter dependencies einbinden.

so nun viel Erfolg.

— geändert am 02.05.2020, 12:39:07

Hilfreich?
Robbiani RenatoPascal P.
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

30.04.2020, 21:29:13 via Website

Was ist denn die Fehlermeldung?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

30.04.2020, 22:23:08 via Website

Hallo auch wenn du kein beispiel dazu finden solltest ist es doch auch möglich java Code nach kotlin übersetzen zu lassen.
Klar der do erstellte code ist dann meist nicht so schön kompakt aber lauffähig.

Aber eigentlich kannst du ja java und hast dir die Grundlagen von kotlin beigebracht.
Anhand einen Java Beispiel sollte es ohne große Aufwand möglich sein ein Java Email intent nach kotlin zu übersetzen.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

01.05.2020, 12:28:51 via Website

Hallo
eigentlich willst du einen Impliziten Intent und nicht einen Expiziten Intent.

val mailsender = Intent(Intent.ACTION_SEND)

Hilfreich?
Pascal P.
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

01.05.2020, 21:19:38 via Website

Ciao Jokel

So geht es. Aber es wird nur die Mail App geöffnet. Aber ich möchte, dass das Mail direkt versandt wird. Ich denke, dass es auf diesem Weg nicht geht.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

01.05.2020, 22:37:02 via Website

Genau mit einem intent habe ich es noch nicht geschaft das eine Mail ohne eine Bestätigung des Users zu senden.
Gleich ob java oder kotlin.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

02.05.2020, 10:45:04 via App

Nein ohne Bestätigung geht aus gutem Grund nicht.
Sonst können Apps ja Spam von deinem Mail Account senden ohne dass du es merkst.
Wenn du selber einen Mailserver oder eine Domain mit Mailserver hast kannst du darüber Mails verschicken, aber dann halt nicht mit Namen des Users.
Was willst du damit machen?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

02.05.2020, 11:29:38 via Website

Hallo

Nein ohne Bestätigung geht aus gutem Grund nicht.

Na ganz so dass es überhaupt nicht geht ist es nicht. Mit einen Intent sicher nicht den da rufst du die Android eigene App auf, und da ist es eben so das auf eine User Eingabe gewartet wird.

Um eine E-Mail im Hinderung ohne User Eingabe verschicken zu könne. Musst selber den SMTP Server deines Providers benutzen. Entweder du machst alles selber oder benutzt die Standard Java Bibliotheken.
Die du aber erst laden und dem Projekt hinzufügen musst.

Hier ein Link dafür.
Ist zwar in Java aber wie ich aus deinen vorherigen Threads weis kannst du das ja. Also sollte es dir möglich sein das nach Kotlin zu übersetzen. Das bietet dir AS auch an, eine Java Kasse nach Kotlin zu übersetzen.

https://www.simplifiedcoding.net/android-email-app-using-javamail-api-in-android-studio/

— geändert am 02.05.2020, 11:33:31

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

02.05.2020, 11:36:03 via Website

Ciao Pascal

Ich bin daran eine Wetterstation zu bauen. Ich möchte die Messdaten sammeln und einmal am Tag per Mail an mein PC senden. Ich möchte das Mail nicht jeden Tag anstossen müssen. Vielleicht gibt es einen anderen Weg um die Daten zu übertragen. Mal schauen vielleicht kommt mir noch eine Idee. Trotzdem Danke für die Hilfe.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

02.05.2020, 11:41:54 via Website

Hallo @Robbiani Renato
habe dir doch schon einen Link gesucht wie du „Mails im Background“ ohne Intent senden kannst.
Genau danach solltest du im Netz suchen. Da wirst du auch fündig werden.

— geändert am 02.05.2020, 11:42:19

Hilfreich?
Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.528

02.05.2020, 12:34:33 via Website

Solltest du wirklich nichts Passendes finden. Hier eine Klasse die eine Mail mit Datei Anhang sendet. Mit der Java API.
Hatte ich in Java und habe sie in Kotlin übersetz.

class SendMail(private val attachFilePath: String) : AsyncTask<Void?, Void?, Void?>() {

private val EMAIL = "..." // SMTP Mail Account
private val PASSWORD = "..." // SMTP PW
private val SMTPHOST = "..." // SMTP Adresse
private var session: Session? = null

//Information to send email
private val email = "...@..." // Empfänger Adresse
private val subject = "Hallo"
private val message = "Neue Daten"

protected override fun doInBackground(vararg params: Void?): Void? {
    //Creating properties
    val props = Properties()
    props.setProperty("mail.transport.protocol", "smtp")
    props["mail.smtp.host"] = SMTPHOST
    props["mail.smtp.socketFactory.port"] = "465"
    props["mail.smtp.port"] = "465"
    props["mail.smtp.socketFactory.class"] = "javax.net.ssl.SSLSocketFactory"
    props["mail.smtp.auth"] = "true"
    props["mail.smtp.socketFactory.fallback"] = "false"
    props.setProperty("mail.smtp.quitwait", "false")

    //Creating a new session
    session = Session.getDefaultInstance(props, object : Authenticator() {
        //Authenticating the password
        override fun getPasswordAuthentication(): PasswordAuthentication {
            return PasswordAuthentication(EMAIL, PASSWORD)
        }
    })
    try {
        //Creating MimeMessage object
        val mm = MimeMessage(session)
        //Setting sender address
        mm.setFrom(InternetAddress(EMAIL))
        mm.addRecipient(Message.RecipientType.TO, InternetAddress(email))
        mm.subject = subject
        val mp: Multipart = MimeMultipart()
        val htmlPart = MimeBodyPart()
        htmlPart.setContent(message, "text/plain")
        mp.addBodyPart(htmlPart)
        val attachment = MimeBodyPart()
        val source: DataSource = FileDataSource(attachFilePath)
        attachment.dataHandler = DataHandler(source)
        attachment.fileName = File(attachFilePath).name
        mp.addBodyPart(attachment)
        mm.setContent(mp)
        //Sending email
        Transport.send(mm)
    } catch (e: MessagingException) {
        e.printStackTrace()
    }
    return null
}

}

aufruf der Klasse

    var sm2 =  SendMail("path zum Mail Anhang")
    sm2.execute()

natürlich brauchst du auch die libs und musst sie auch unter dependencies einbinden.

so nun viel Erfolg.

— geändert am 02.05.2020, 12:39:07

Hilfreich?
Robbiani RenatoPascal P.
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

02.05.2020, 13:08:27 via Website

Ich würde die Daten an einen HTTP Server übermitteln und dort speichern.
Von dort kannst du dann auch einfacher E-Mails versenen.
Oder natürlich wie es dir @Jockel gezeigt hat.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

03.05.2020, 11:17:53 via Website

Ciao Jokel

Herzlichen Dank für deine Klasse. Die ist ja echt super.
In einem bin ich noch hängen geblieben. Welche jar Dateien muss ich einbinden. Gefunden habe ich folgende:

mail.jar
additionnal.jar
activation.jar

Wahrscheinlich benötige ich noch weitere. Denn in der Klasse möchte Android-Studio noch weiter Klassen erstellen.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

03.05.2020, 13:31:22 via Website

Hallo alle drei wenndu es nicht so wie bei Pascal machen willst.

implementation files('libs/additionnal.jar')
implementation files('libs/mail.jar')
implementation files('libs/activation.jar')

die drei Dtein in den Lib Ordner /app/libs

Das steht alle in dem Link den ich dir zuerst gegeben habe lesen bildet.

Hilfreich?
Pascal P.
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

03.05.2020, 15:23:07 via Website

wenn es über das Repos. sein soll.
dann so

implementation 'javax.mail:javax.mail-api:1.6.2'
implementation 'javax.activation:javax.activation-api:1.2.0'

du brauchst beide sonst kannst du keinen Anhang verschicken.

Hilfreich?
Pascal P.
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

03.05.2020, 18:49:40 via Website

Ciao Jokel

Irgend was mache ich falsch. Es will einfach nicht funktionieren. Meine build.gradle sieht wie folgt aus:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 28

defaultConfig {
    applicationId "ch.robbisoft.sendmail"
    minSdkVersion 19
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'javax.mail:javax.mail-api:1.6.2'
implementation 'javax.activation:javax.activation-api:1.2.0'
}

Die jar-Dateien habe ich unter app/libs abgelegt. Wenn ich nun kompiliere werden die Verknüpfungen nicht gefunden.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

03.05.2020, 19:07:25 via Website

Wenn du das mit dem repos machst.
Brauchst du die jar Dateien darfst sie auch nicht in dem lib Ordner haben.

Entweder die jar Dateien und die erste Variante im gradle.
Oder ohne jar Dateien die werden dann über das repos geladen.

Dachte das wäre klar gewesen.

— geändert am 03.05.2020, 19:08:15

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

03.05.2020, 19:07:26 via Website

Jetzt hat es funktioniert mit dem "import javax.mail.*"

Jetzt sind nur noch zwei Probleme noch offen. Folgende Zeile will er nicht kennen.

session = PackageInstaller.Session.getDefaultInstance(props, object : Authenticator()

Das getDefaultInstance sticht ihm in die Nase und

mm.addRecipient(Message.RecipientType.TO, InternetAddress(email))

der RecipienType will er auch nicht kennen. Mal schauen vielleicht finde ich eine Lösung. Oder weiss jemand woran das liegt.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

03.05.2020, 19:10:09 via Website

Mache deine Imports neu und richtig.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 11:04:13 via Website

Hallo zusammen

Ich habe das Projekt platt gemacht und neu angelegt. Die Jar-Dateien nochmals vom Internet bezogen. Und neu eingebunden. Trotzdem kommen immer noch dieselben Fehler zum Vorschein.

import javax.mail.Session.getDefaultInstance

Ist grau hinterlegt. Durch dass können folgende Zeilen nicht ausgeführt werden.

session = PackageInstaller.Session.getDefaultInstance(props, object : Authenticator()

und

mm.addRecipient(Message.RecipientType.TO, InternetAddress(email))

vielleicht weiss jemand Rat?

Gruss Renato

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

04.05.2020, 11:23:54 via Website

Dein Import ist nicht richtig...

import javax.mail.Session

so sieht das besser aus, nur die Klasse/Package importieren und nicht die Methode...

Bzw. schmeiss die Imports raus und lasse sie über Alt+Enter auf dem Error selbst erstellen, dann sind die auf jeden Fall richtig...

— geändert am 04.05.2020, 11:24:56

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Jokel
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 18:05:17 via Website

Ciao Pascal

Bringt nichts. Der Import ist immer noch grau und die Methode rot. Habe ich möglicherweise die falschen Dateien. Ist es dir möglich einen Link zu den richtigen Dateien hin zu stellen.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

04.05.2020, 18:17:48 via Website

Zeige mal deine Imports.
bemerken möchte ich hier noch.

"import javax.mail.*"
geht nicht mit java libs kotlin libs ja.

@Robbiani Renato sollte es nichtst werden kann ich dir meine komplette Klasse mit Import erst morgen schicken.

— geändert am 04.05.2020, 18:26:21

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

04.05.2020, 18:32:25 via Website

Also ich habs mit Gradle eingebunden und da funktionieren folgende Imports:

import android.os.AsyncTask
import java.io.File
import java.util.*
import javax.activation.DataHandler
import javax.activation.DataSource
import javax.activation.FileDataSource
import javax.mail.*
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMessage
import javax.mail.internet.MimeMultipart

Sollte das bei dir nicht gehen, werden die Libs nicht passend eingebunden.
@Jokel: javax.mail.* funktioniert bei mir min Kotlin Projekt :) Kann aber auch sein, dass die Gradle auf die Kotlin Lib auflöst, falls es da eine gibt.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

04.05.2020, 18:49:19 via Website

@Pascal ja kann auch sein .

das Hauptproblem sehe ich bei diesem import

"import javax.activation.DataSource"

Denn DataSource gibt es auch von Android und der Geladenen LIB.
Du musst da natürlich die von der LIB benutzen.

denke das es so wie von Pascal richtig ist . Wie gesagt kann ich im moment nicht nachschauen.

Mich würde aber deine Imports auch interesiren Renato.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 19:05:50 via Website

Wie gewünscht meine Imports

import android.content.pm.PackageInstaller
import android.os.AsyncTask
import android.os.Message
import java.io.File
import java.net.Authenticator
import java.util.*
import javax.activation.DataHandler
import javax.activation.FileDataSource
import javax.mail.*
import javax.mail.Session.*
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMessage
import javax.mail.internet.MimeMultipart
import javax.mail.PasswordAuthentication

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

04.05.2020, 19:29:55 via Website

import java.net.Authenticator
löschen

import javax.mail.Session.*
import javax.mail.PasswordAuthentication

auch löschen sollte duch das wildcard import vorhanden sein.

@Pascal ja auch in Kotlin gibt es „wildcard imports“ „*“. Kommt auch auf die Einstellung des Studios an. Die IDE macht das aber erst wenn mindestens 5 Methoden aus dem Paket benutzt werden.

https://javaee.github.io/javamail/docs/api/index.html?javax/mail/package-summary.html

ps.
import android.os.Message / für was ist das?
import android.content.pm.PackageInstaller / für was ist das?

PS. wenn du mit ALT ENTER den import machst musst du immer schauen welchen du machst und den richtigen auswählen

— geändert am 04.05.2020, 19:48:37

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 20:22:24 via Website

Der PackageInstaller wird für diese Zeile benötigt.

private var session: PackageInstaller.Session? = null

Oder welchen Import muss ich nehmen?

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 20:30:36 via Website

Nun habe ich PackageInstaller entfernt und nun geht es.
Super Danke für eure Hilfe. Wenn ihr in meiner nähe Wohnen würdet, ich würde galt ein Fass Bier ausgeben!

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

04.05.2020, 20:30:40 via Website

In meinem Code wird das so nicht benutzt. Schaue nach.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

04.05.2020, 20:31:37 via Website

Wie weit bist du denn weg?

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 20:42:58 via Website

Bern. Aber wenn du mal in der nähe bist, dann komm doch einfach vorbei. Habe immer welches im Kühlschrank

Hilfreich?
Jokel
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

04.05.2020, 20:56:49 via Website

Ich München. ca. 350 km ist doch etwas weit. Aber danke für das Angebot.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 20:58:24 via Website

Dann komm ich doch mal ans Oktober Fest. Wenn es wieder mal statt findet.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.528

04.05.2020, 20:59:29 via Website

Corona fällt aus dieses Jahr.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 606

04.05.2020, 21:30:42 via Website

Darum meinte ich wenn es mal wieder statt findet.(laughing)

Hilfreich?
Kommentieren