17.04.21 9829 Views 6

credit: ©Song_about_summer

JAVA Blog

E-Mails mit Java senden

E-Mails mit Java zu versenden ist einfach. Für JavaSE-Nutzer genügt das Einbinden der externen JavaMail API. Die Programmierung des Mail-Versands über SMTP ist eine einmalige Sache. Wir erklären dir in diesem Kapitel ganz genau, wie das geht. Wenn du für Erklärungen keine Zeit hast, kopier dir einfach den Code und leg los.

Falconbyte unterstüzen

Betrieb und Pflege von Falconbyte brauchen viel Zeit und Geld. Um dir auch weiterhin hochwertigen Content anbieten zu können, kannst du uns sehr gerne mit einem kleinen "Trinkgeld" unterstützen.

  • Achtung: Seit Java JDK 11 muss zusätzlich das java.activation in die Projekt-Bibliothek eingebunden werden.

    Inhaltsverzeichnis

  1. Vorbereitungen
  2. Wie JavaMail funktioniert
  3. E-Mail mit Java senden
  4. Vollständiger Code
  5. Mail mit Datei-Anhang verschicken
  6. JavaMail mit neuen Java-Versionen

Vorbereitungen

E-Mail-Adresse bereitstellen

Um das Versenden von E-Mails mit Java Mail zu demonstrieren, haben wir eine E-Mail-Adresse bei GMail angelegt (marcus.algo@gmail.com). Am Besten du registriert dir eine eigene GMail-Adresse, um den E-Mail-Versand damit selbst zu testen.

Damit unser Java-Programm auf die Gmail-Adresse zugreifen kann, muss in den GMail-Sicherheitseinstellungen (https://myaccount.google.com/security) die Option Zugriff durch weniger sichere Apps erst noch eingeschaltet werden:

Java E-Mails senden gmail Security

Andere E-Mail-Anbieter verfahren übrigens ähnlich. Sieh dir am Besten die Sicherheitseinstellungen auch dort einmal an.

Java Mail API einbinden

Die JavaMail API ist das Framework, mit dem wir Mail-Anwendungen bauen können. In Java EE ist JavaMail bereits inklusive. Für die Java Standard Edition (Java SE) musst du sie erst noch als optionales Paket in das Java-Projekt einbinden.

Lade dir hierzu die Bibliotheks-Datei javax.mail.jar runter.

  • Entweder bei github
  • Oder bei uns (Version 1.6.2): hier

Als nächsten binden wir die JavaMail API in unser Java-Projekt ein:

  • IntelliJ: Klicke in der Seitenleiste links ein Java-Projekt an. Gehe anschließend im Programm-Menu auf file > project structure... > libraries. Klicke im Project Structure-Menu auf das + Zeichen und füge jetzt die externe Klassenbibliothek dem Projekt hinzu, indem du die gedownloadete jar-Datei javax.mail.jar auswählst.
  • Eclipse: Wähle in der Seitenleiste links ein Java-Projekt aus. Gehe im Programm-Menu oben auf File > Properties. Es erscheint das Menu für die Properties. Wähle darin Java Build Path > Libraries > Add External JARs... und füge die gedownloadete jar-Datei javax.mail.jar hinzu.

Fertig - wir sind nun startbereit ☺️

Wie JavaMail funktioniert

Die JavaMail API besteht aus einem Zusammenspiel verschiedener Klassen. Einige dieser Klassen sehen wir hier:

Java Mail API

  • Session repräsentiert die Verbindung zum Mailserver und hält die Server-Daten sowie ein Authentificator-Objekt.
  • Message ist eine abstrakte Klasse, welche für die Modellierung der E-Mail zuständig ist.
  • Multipart ist eine abstrakte Klasse, die als eine Art "Wrapper" für Inhalte der E-Mail dient. Die einzelnen Inhalte der E-Mail sind vom Typ BodyPart.
  • Transport modelliert den Transport-Mechanismus für das Senden einer E-Mail.

Die Infografik zeigt uns, dass eine Message eine Instanz von Session und Multipart aufnimmt. Transport benötigt dann wiederum die Message.

Da es sich bei Message, Multipart und BodyPart und abstrakte Klassen handelt, können wir nur mit Objekten von konkreten Unterklassen arbeiten:

Message message = new MimeMessage(session);
Multipart multipart = new MimeMultipart();
BodyPart messageBodyPart = new MimeBodyPart();

E-Mail mit Java senden

Starten wir nun also den Bau unseres Programms zum Versand von E-Mails! Dieser Vorang ist etwas komplexer und du solltest dir Zeit nehmen, ihn zu verstehen. Falls du diese Zeit nicht hast, kann man auch nichts machen. Spring dann einfach zum fertigen Code.

Properties und Adressen setzen

Erstellen wir zunächst eine neue Klasse namens JavaMail. Innerhalb der Main-Methode setzen wir die Daten für den Mail-Server. Für einen GMail-Account sind es folgende Daten:

Properties properties = new Properties();
properties.put("mail.smtp.auth",  "true");
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", "smtp.gmail.com");
properties.put("mail.smtp.port", "587");

Die einzelnen Elemente werden als Schlüssel-Wert-Paare in einem Properties-Objekt gespeichert.

Gleich darauf speichern wir die Sender-Adresse unseres GMail-Kontos mitsamt Passwort. Außerdem legen wir auch gleich eine Empfänger-Adresse fest:

String myAccount = "marcus.algo@gmail.com"; // GMail-Sender
String myPassword = "*********";
String empfaenger = "empfaenger@irgendwo.de";

Session erstellen

Als nächstes erzeugen wir das Session-Objekt:

Session session = Session.getInstance(properties, new Authenticator() {
   @Override
   protected PasswordAuthentication getPasswordAuthentication() {
       return new PasswordAuthentication(myAccount, myPassword);
   }
});

Die statische Methode Session.getInstance() liefert ein Objekt vom Typ Session zurück. Der Methode werden dabei unser Properties-Objekt von oben sowie ein neues Authenticator-Objekt als Argumente übergeben.

Der Code hinter new Authentificator() beschreibt eine sogenannte anonyme Klasse. "Anonym" deshalb, weil die Klasse keinen Namen hat und "mitten im Code" spontan erzeugt wird. Anonyme Klassen sind praktisch für eine einmalige Objekterzeugung "on the fly". Sie können Methoden von existierenden Klassen überschreiben - und genau das passiert hier auch.

Die Methode getPasswordAuthentication() liefert dann mit PasswordAuthentication eine gültiges Unterklassen-Objekt des benötigten Authenticator-Objekts zurück.

Message erstellen

Kommen wir nun zum Bau der eigentlichen Message. Dieser Vorang kann je nach Komplexität der abzuschickenden Nachricht mehr oder weniger umfangreich sein. Deshalb legen wir für die Message neue eigene Methode an, die wir prepareMessage() nennen:

private static Message prepareMessage(Session session, String myAccount, String empfaenger) throws Exception{

    Message message = new MimeMessage(session);

    message.setFrom(new InternetAddress(myAccount));
    message.setRecipient(Message.RecipientType.TO, new InternetAddress(empfaenger));
    message.setSubject("Mail Test");

    // Multipart-Message ("Wrapper") erstellen
    Multipart multipart = new MimeMultipart();
    // Body-Part setzen:
    BodyPart messageBodyPart = new MimeBodyPart();
    // Textteil des Body-Parts
    messageBodyPart.setText("Text-Inhalt der E-Mail zum Testen");
    // Body-Part dem Multipart-Wrapper hinzufügen
    multipart.addBodyPart(messageBodyPart);
    // Message fertigstellen, indem sie mit dem Multipart-Content ausgestattet wird
    message.setContent(multipart);

    return message;
}

Die Methode nimmt in den Parametern das schon vorhandene Session-Objekt sowie Sender- und Empfänger-Adresse auf.

Innerhalb der Methode wird dann sogleich das MimeMessage-Objekt erstellt.

Anschließend werden mit drei Setter-Methoden für den Sender, Empfänger und den Betreff der Mail festgelegt.

Jetzt wird es spannend, denn wir basteln den Inhalt der E-Mail als Multipart-Nachricht. Der Multipart dient dabei als eine Art "Wrapper", dem die einzelnen Inhalts-Bestandteile, das sind die BodyPart-Objekte, hinzugefügt werden können.

Gegen Ende der Methode wird der vollständige Multipart der Message mit setContent() hinzugefügt. Die so fertiggebaute Message wird schließlich mit return zurückgeliefert.

Message mit Transport senden

Wir sind fast am Ziel!

Wir führen jetzt unsere eben erstellte prepareMessage()-Methode aus. Die durch die Methode gebastelte Message übergeben wir als Argument dem Transporter zum finalen Mail-Versand:

try {
    Message message = prepareMessage(session, myAccount, empfaenger);
    Transport.send(message);
    System.out.println("E-Mail erfolgreich versendet!");
} catch (Exception e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

Ab geht die Post 😁

Vollständiger Code

Hier noch der vollständige Code. Feel free to copy and paste:

import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class JavaMail {

    private static Message prepareMessage(Session session, String myAccount, String empfaenger) throws Exception{
    		Message message = new MimeMessage(session);

            message.setFrom(new InternetAddress(myAccount));
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(empfaenger));
            message.setSubject("Mail Test");

            // Multipart-Message ("Wrapper") erstellen
            Multipart multipart = new MimeMultipart();
            // Body-Part setzen:
            BodyPart messageBodyPart = new MimeBodyPart();
            // Textteil des Body-Parts
            messageBodyPart.setText("Text-Inhalt der E-Mail zum Testen");
            // Body-Part dem Multipart-Wrapper hinzufügen
            multipart.addBodyPart(messageBodyPart);
            // Message fertigstellen, indem sie mit dem Multipart-Content ausgestattet wird
            message.setContent(multipart);

            return message;
    }

    public static void main(String[] args) {

    	Properties properties = new Properties();
		properties.put("mail.smtp.auth",  "true");
		properties.put("mail.smtp.starttls.enable", "true");
		properties.put("mail.smtp.host", "smtp.gmail.com");
		properties.put("mail.smtp.port", "587");

		String myAccount = "marcus.algo@gmail.com";
		String myPassword = "*********";
		String empfaenger = "stefan.heller@falconbyte.net";

       Session session = Session.getInstance(properties, new Authenticator() {
           @Override
           protected PasswordAuthentication getPasswordAuthentication() {
               return new PasswordAuthentication(myAccount, myPassword);
           }
       });

        // Message-Objekt erzeugen und senden!
		try {
			Message message = prepareMessage(session, myAccount, empfaenger);
			Transport.send(message); // E-Mail senden!
			System.out.println("E-Mail erfolgreich versendet!");
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
    }

}

Mail mit Datei-Anhang verschicken

Das Versenden vom Mails mit Anhang ist jetzt nur noch eine Kleinigkeit.

Wir fügen innerhalb der Methode prepareMessage() dem Multipart einfach einen weiteren BodyPart hinzu, der den Datei-Anhang modelliert:

BodyPart anhang = new MimeBodyPart();
String file = "beispieldatei.pdf";
DataSource source = new FileDataSource(file);
anhang.setDataHandler(new DataHandler(source));
anhang.setFileName(file);

multipart.addBodyPart(anhang);
message.setContent(multipart);

Thats' it!

JavaMail mit neuen Java-Versionen

Seit der Änderung von OracleJDK8 zu OpenJDK 11 funktioniert JavaMail nicht mehr ohne Weiteres und E-Mails können nicht mehr versandt werden. Eine java.lang.ClassNotFoundException wird geworfen:

java.lang.NoClassDefFoundError: javax/activation/DataSource (Abbreviation)
Caused by: java.lang.ClassNotFoundException: javax.activation.DataSource                

Grund für die Exception ist, dass JavaMail das java.activation Package nutzt, das seit Java Version 11 aber aus der Standard-Bibliothek entfernt worden ist. Deshalb auch die ClassNotFoundException: Die darin enthaltenen Klassen können schlicht nicht gefunden werden.

Also holen wir uns das java.activation Paket, um unsere Mail-Anwendung zum Laufen zu bringen.

jar-Bibliothek einbinden

Wenn wir das Activation Framework in unser bestehendes Projekt einbinden, stehen die fehlenden Klassen wieder zur Verfügung. Dies kann über den klassischen jar-Bibliothekts-Import geschehen. Die jar-Datei gibt es hier oder bei uns zum Download.

Maven

Natürlich lässt sich das java.activation Paket auch über ein Maven Repository reinholen:

<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>javax.activation</artifactId>
    <version>1.2.0</version>
</dependency>                

Sieh dir das auch als youtube-Tutorial an:

Java lernen

text text

PHP Lernen

zur PHP

JavaScript lernen

move nove move

FALCONBYTE.NET

Handmade with 🖤️

© 2018-2023 Stefan E. Heller

Impressum | Datenschutz | Changelog

Falconbyte Youtube Falconbyte GitHub facebook programmieren lernen twitter programmieren lernen discord programmieren lernen