Problem mit JavaMail API

Dann07

Aktives Mitglied
Guten Tag/Abend!
Ich habe ein Problem mit der JavaMail API das Problem ist das ich bei start des Programms immer eine Exception bekomme!
Der Zweck des Programms besteht darin das man mit der login Methode eine Instance der Klasse erstellt und verschiedene Sachen mit den Emails machen kann.

Exception:

javax.mail.MessagingException: 220 smtp.gmail.com ESMTP k8sm4882723edn.52 - gsmtp;
nested exception is:
com.sun.mail.iap.ConnectionException: 220 smtp.gmail.com ESMTP k8sm4882723edn.52 - gsmtp
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:738)
at javax.mail.Service.connect(Service.java:366)
at javax.mail.Service.connect(Service.java:246)
at ********.Mail.<init>(Mail.java:80)
at ********.Mail.login(Mail.java:29)
at Main.main(Main.java:7)
Caused by: com.sun.mail.iap.ConnectionException: 220 smtp.gmail.com ESMTP k8sm4882723edn.52 - gsmtp
at com.sun.mail.imap.protocol.IMAPProtocol.processGreeting(IMAPProtocol.java:341)
at com.sun.mail.iap.Protocol.<init>(Protocol.java:141)
at com.sun.mail.imap.protocol.IMAPProtocol.<init>(IMAPProtocol.java:131)
at com.sun.mail.imap.IMAPStore.newIMAPProtocol(IMAPStore.java:763)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:698)
... 5 more

Code:

Java:
package ******;

import java.util.*;
import javax.mail.*;
import javax.mail.Flags.Flag;
import javax.mail.internet.*;

import com.sun.mail.imap.IMAPStore;

import *******.providers.Providers;

public class Mail {

    private String email;
    private Session session;
    private IMAPStore imapStore;
    private String username;
    private int imap_port;
    private String imap_host;
    private int smtp_port;
    private String smtp_host;
    private int pop3_port;
    private String pop3_host;
    
    public static Mail login(String email, String password, String username, Providers provider) {
        System.out.println("Anbieter: " + provider.getName());
        provider.printInfos();
        
        return new Mail(email, password, username, provider.getIMAPHost(), provider.getIMAPPort(), provider.getSMTPHost(), provider.getSMTPPort(), provider.getPOP3Host(), provider.getPOP3Port());
    }
    
    private Authenticator getAuthenticator(String email, String password) {
        PasswordAuthentication passAuth = new PasswordAuthentication(email, password);
        Authenticator auth = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return passAuth;
            }
        };
        
        return auth;
    }
    
    private Properties getProps() {
        Properties props = new Properties();
        
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", this.smtp_host);
        props.put("mail.smtp.socketFactory.port", String.valueOf(this.smtp_port));
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", String.valueOf(this.smtp_port));
        
        props.put("mail.store.protocol", "imaps");
        
        props.put("mail.imaps.port", String.valueOf(this.imap_port));
        props.put("mail.imaps.starttls.enable", "true");
        
        props.put("mail.pop3.starttls.enable", "true");
        props.put("mail.pop3.host", this.pop3_host);
        props.put("mail.pop3.port", String.valueOf(this.pop3_port));
        
        return props;
    }
    
    private Mail(String fromEmail, String password, String username, String imap_host, int imap_port, String smtp_host, int smtp_port, String pop3_host, int pop3_port) {
        try {
            this.imap_host = imap_host;
            this.imap_port = imap_port;
            this.smtp_host = smtp_host;
            this.smtp_port = smtp_port;
            this.pop3_host = pop3_host;
            this.pop3_port = pop3_port;
            
            System.out.println("Einloggen...");
            
            session = Session.getDefaultInstance(getProps(), getAuthenticator(fromEmail, password));
            Store store = session.getStore("imaps");
            
            store.connect(this.imap_host, username, password);
            
            imapStore = (IMAPStore) store;
            
            System.out.println("Eingeloggt!");
            System.out.println("E-Mail: " + fromEmail);
            System.out.println("Benutzername: " + username);
            System.out.println("Passwort: " + password);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public void send(String email, String subject, String text, String description, String charset) {
        try {
            MimeMessage message = new MimeMessage(session);
            
            System.out.println("Versende...");
            
            message.setFrom(new InternetAddress(this.email, username));
            message.setReplyTo(InternetAddress.parse(email, false));
            message.setSubject(subject);
            message.setText(text, charset);
            message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(email));
            message.setSentDate(new Date());
            message.setDescription(description, charset);
            
            Transport.send(message);
            System.out.println("E-Mail versendet!");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public void check() {
        try {
            Folder folder = imapStore.getFolder("INBOX");
            
            folder.open(Folder.READ_ONLY);
            
            System.out.println("Nachrichten: " + folder.getMessageCount());
            System.out.println("Neue Nachrichten: " + folder.getNewMessageCount());
            System.out.println("Ungelesene Nachrichten: " + folder.getUnreadMessageCount());
            System.out.println("Gelöschte Nachrichten: " + folder.getDeletedMessageCount());
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public void checkEmail(int i) {
        try {
            Folder folder = imapStore.getFolder("INBOX");
            
            folder.open(Folder.READ_ONLY);
            
            Message message = folder.getMessage(i);
            
            if(!message.isSet(Flag.SEEN)) {
                System.out.println("Datum/Uhrzeit: " + message.getReceivedDate());
                System.out.println("Von: " +  Arrays.toString(message.getFrom()));
                System.out.println("Betreff: " + message.getSubject());
                System.out.println("Inhalt: " + message.getContent());
                System.out.println("Beschreibung: " + message.getDescription());
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public void checkEmails() {
        try {
            Folder folder = imapStore.getFolder("INBOX");
            
            folder.open(Folder.READ_ONLY);

            for(int i = 1; i < folder.getMessageCount(); i++) {
                System.out.println("====================================");
                checkEmail(i);
                System.out.println("====================================");
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public String[] getEmails() {
        try {
            Folder folder = imapStore.getFolder("INBOX");
            String[] str = new String[folder.getMessageCount()];
            
            folder.open(Folder.READ_ONLY);
            
            for(int i = 1; i < folder.getMessageCount(); i++) {
                str[i] = folder.getMessage(i).getSubject();
            }
            
            return str;
        } catch(Exception e) {
            e.printStackTrace();
        }
        
        return null;
    }
    
    public void setEmailFlag(int i, Flag flag, boolean bool) {
        try {
            Folder folder = imapStore.getFolder("INBOX");
            
            folder.open(Folder.HOLDS_FOLDERS);
            folder.getMessage(i).setFlag(flag, bool);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
}

Was den Code angeht ist er nicht der beste.
 
Welches Protokoll denn und welcher Provider? Empfangen oder Verschicken?

In dem Programm wird SMTP und IMAP verwendet.

Zu deiner zweiten Frage:

Man soll senden und empfangen können.

Und ich habe mir eine eigene Provider Klasse/Enum erstellt:

Java:
package *******.providers;

public enum Providers {

    GOOGLE("Google", "smtp.gmail.com", 465 , "imap.gmail.com", 993, "pop.gmail.com", 995),
    STRATO("STRATO", "smtp.strato.de", 465, "imap.strato.de", 993, "pop3.strato.de", 995),
    GMX("GMX", "mail.gmx.net", 587, "imap.gmx.net", 993, "pop.gmx.net", 995),
    YAHOO("Yahoo", "smtp.mail.yahoo.com", 465, "imap.mail.yahoo.com", 993, "pop.mail.yahoo.com", 995),
    OUTLOOK("Outlook", "SMTP.office365.com", 587, "Outlook.office365.com", 993, "Outlook.office365.com", 995),
    MAIL_DE("Mail.de", "smtp.mail.de", 465, "imap.mail.de", 993, "pop.mail.de", 995),
    WEB_DE("WEB.DE", "smtp.web.de", 587, "imap.web.de", 993, "pop3.web.de", 995);
    
    String name;
    String smtp_host;
    int smtp_port;
    String imap_host;
    int imap_port;
    String pop3_host;
    int pop3_port;
    
    Providers(String providerName, String smtp_host, int smtp_port, String imap_host, int imap_port, String pop3_host, int pop3_port) {
        this.name = providerName;
        this.smtp_host = smtp_host;
        this.smtp_port = smtp_port;
        this.imap_host = imap_host;
        this.imap_port = imap_port;
        this.pop3_host = pop3_host;
        this.pop3_port = pop3_port;
    }
    
    public String getName() {
        return name;
    }
    
    public String getSMTPHost() {
        return smtp_host;
    }
    
    public int getSMTPPort() {
        return smtp_port;
    }
    
    public String getIMAPHost() {
        return smtp_host;
    }
    
    public int getIMAPPort() {
        return smtp_port;
    }
    
    public String getPOP3Host() {
        return pop3_host;
    }
    
    public int getPOP3Port() {
        return pop3_port;
    }
    
    public void printInfos() {
        System.out.println("IMAP-Host: " + imap_host);
        System.out.println("IMAP-Port: " + imap_port);
        System.out.println("SMTP-Host: " + smtp_host);
        System.out.println("SMTP-Port: " + smtp_port);
        System.out.println("POP3-Host: " + pop3_host);
        System.out.println("POP3-Port: " + pop3_port);
    }
    
}
 
Also es sieht so aus, als ob Du irgendwo Ports durcheinander wirfst. Die Exception tritt bei einer IMAP Verbindung auf aber die Exception gibt im Text klar, dass Du auf dem smtp Port gelandet bist.
 
Wie kann ich das Problem denn nun beheben?
Ich habe eigentlich schon alles versucht.

(Und wirklich alles)
Das sehe ich so auf Anhieb auch nicht ... gib doch mal vor dem connect etwas mehr Infos aus oder starte im Debugger, so dass Du Dir das ansehen kannst so dass Du siehst, ob die Werte richtig sind oder nicht.

sieht doch richtig aus
Im Stacktrace der Exception ist klar zu sehen, dass smtp.gmail.com sich mit 220 meldet (==> smtp) und er im Code aber im IMAPStore ist. Und natürlich können die IMAP Klassen kein smtp. Daher muss da irgendwo der Wurm drin sein.
 
Es passiert aber alles hier:

Java:
store.connect(this.imap_host, username, password);

Aber es wird alles richtig übergeben.
Nur versteh ich nicht warum denn der Fehler kommt obwohl alles richtig ist.
 
Hier mal die ganze Konsole:

Anbieter: Google
IMAP-Host: imap.gmail.com
IMAP-Port: 993
SMTP-Host: smtp.gmail.com
SMTP-Port: 465
POP3-Host: pop.gmail.com
POP3-Port: 995
Einloggen...
smtp.gmail.com <- Das wird vor connect ausgegeben.
Dann07 <----------
*********** <- Passwort Zensiert
javax.mail.MessagingException: 220 smtp.gmail.com ESMTP c32sm4670507eda.97 - gsmtp;
nested exception is:
com.sun.mail.iap.ConnectionException: 220 smtp.gmail.com ESMTP c32sm4670507eda.97 - gsmtp
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:738)
at javax.mail.Service.connect(Service.java:366)
at javax.mail.Service.connect(Service.java:246)
at *******.Mail.<init>(Mail.java:83)
at *******.Mail.login(Mail.java:29)
at Main.main(Main.java:7)
Caused by: com.sun.mail.iap.ConnectionException: 220 smtp.gmail.com ESMTP c32sm4670507eda.97 - gsmtp
at com.sun.mail.imap.protocol.IMAPProtocol.processGreeting(IMAPProtocol.java:341)
at com.sun.mail.iap.Protocol.<init>(Protocol.java:141)
at com.sun.mail.imap.protocol.IMAPProtocol.<init>(IMAPProtocol.java:131)
at com.sun.mail.imap.IMAPStore.newIMAPProtocol(IMAPStore.java:763)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:698)
... 5 more
 
Nach dem Einloggen gibst du smtp.gmail.com aus. Woher kommt diese Ausgabe?

Einloggen... gibst du vor dem imap connect aus, also erwarte ich da dann immer den imap host und nicht smtp.
 
Ich kapier auch nicht warum da steht SMTP.
Obwohl ich ja eigentlich IMAP übergebe nix anderes.
Entweder bin ich zu dumm oder ich lass die Sache.
 
Ich habe nun die Lösung gefunden.
Es lag an dem Enum!

Es wurde immer SMTP übergeben.

Java:
    public String getIMAPHost() {
        return smtp_host;
    }
    
    public int getIMAPPort() {
        return smtp_port;
    }

Richtig währe:

Java:
    public String getIMAPHost() {
        return imap_host;
    }
    
    public int getIMAPPort() {
        return imap_port;
    }
 
Ich habe nun die Lösung gefunden.
Es lag an dem Enum!

Es wurde immer SMTP übergeben.

Java:
    public String getIMAPHost() {
        return smtp_host;
    }
   
    public int getIMAPPort() {
        return smtp_port;
    }

Richtig währe:

Java:
    public String getIMAPHost() {
        return imap_host;
    }
   
    public int getIMAPPort() {
        return imap_port;
    }

Super. Generell evtl. Noch ein paar Hinweise:
a) schau mal, ob Dir ein Logging Framework gefällt. Statt Ausgaben zu machen logst du dann nur. Hat den Vorteil, dass dies dann drin bleibt und du immer über den Loglevel sagen kannst, was Dich interessiert. Ich bin viel mit slf4j unterwegs, aber es gibt da ganz viel wie z.B, log4j und co.
Und wenn du das nicht willst: gib immer mehr als nur eine Variable aus, so dass du weißt, was wann wo ausgegeben wird, sonst wird die Zuweisung ggf schwer.

Ansonsten wünsche ich weiter viel Erfolg und schön, dass das Problem gelöst werden konnte.
 
Also das klappt bei mir:
Java:
import java.io.IOException;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeMultipart;

public class Mail {
  public static void main(String[] args) throws MessagingException, IOException {
    String host = "?.?.?";
    String user = "";
    String password = "";

    Properties properties = System.getProperties();
    properties.setProperty("mail.pop3.ssl.trust", "*"); // Trust all Servers
    Session session = Session.getDefaultInstance(properties);
    Store store = session.getStore("pop3s");
    store.connect(host, 995, user, password);
    Folder inbox = store.getFolder("Inbox");
    inbox.open(Folder.READ_ONLY);

    Message[] messages = inbox.getMessages();

    if (messages.length == 0)
      System.out.println("No messages found.");

    for (int i = 0; i < messages.length; i++) {
      if (i > 10) {
        System.exit(0);
        inbox.close(true);
        store.close();
      }

      System.out.println("Message " + (i + 1));
      System.out.println("From : " + messages[i].getFrom()[0]);
      System.out.println("Subject : " + messages[i].getSubject());
      System.out.println("Sent Date : " + messages[i].getSentDate());
      System.out.println("Type : " + messages[i].getContentType());
      if (messages[i].getContentType().contains("text")) {
        String o = messages[i].getContent().toString();
        System.out.println("text : " + o);
      } else if (messages[i].getContentType().contains("multipart")) {
        String o = ((MimeMultipart) messages[i].getContent()).getBodyPart(0).getContent().toString();
        System.out.println("mime : " + o);
      }
      System.out.println();
    }

    inbox.close(true);
    store.close();
  }
}


Vielleicht solltest Du Deinen Code dahingehend mal anpassen... und verwende bitte nicht Java 11.
 
Eine einzige Frage bleibt mir bestehen.
Bei der Methode checkEmail wird alles wichtige über die Email ausgegeben.
Nur das komische ist das bei message.getContent() javax.mail.internet.MimeMultipart@(ZAHLEN) ausgegeben wird.
Sollte bei message.getContent() nicht eigentlich der Inhalt der Email ausgegeben werden?
 
Also meine Sicht weicht deutlich von der Sicht von Tobias ab. Ich würde sogar explizit zu einem aktuellen Java raten.
Die aktuelle LTS Version ist Java 11. Aber wenn man bereit, etwas öfter zu wechseln, dann kann man auch ein noch aktuelleres verwenden.

Weshalb der Code von Tobias nicht "ohne Weiteres" laufen soll, kann ich nicht nachvollziehen. Dieser lief bei mir 1:1 unter Java 11 sofort. (Ok, mit Anpassung der Variablen um da einen gültigen IMAP Account samt Server anzugeben und natürlich habe ich in gradle die Dependency eigetragen... Das wäre aber auch bei Java 8 notwendig.)

Daher kann ich nur vermuten: Vermutlich denkt Tobias an die Module, welche mit Java 9 eingeführt wurden, weshalb er zu Java 8 rät. Das sehe ich aber nicht wirklich als Problem an, denn wenn man das erst einmal ignoriert (keine module-info.java), dann ist der Code in einem "unnamed module" und dieses hat automatisch ein "requires" auf alle anderen Module. Somit läuft dann so eine kleine Beispiel-App sofort.

Wenn man bei altem Java 8 bleibt, dann wird man regelmäßig beim nachvollziehen von Codevorschlägen hier im Forum Probleme kriegen. Mit jeder Java Version wurde das Framework erweitert und bestehende Klassen haben teilweise neue Member bekommen.
Das nur um einen Grund zu nennen, wieso ich zu aktuellen Java Versionen raten würde.

Ausnahme kann natürlich sein, dass die Java Version in der Anforderung bereits festgelegt wurde. Wenn da der Kunde z.B. auf Java 8 besteht, dann nutzt man das auch... Und wenn man Abhängigkeiten hat, die Abhängigkeiten zu dem eigenen Modul/Code haben (z.B. im Bereich von AOP), dann ist eine module-info.java wohl notwendig, aber wenn man in die Bereiche geht, dann sollte man auch die Module von Java verstanden haben...
 
Also bei mir traten bei eclipse und Java 11 und maven beim Einbinden der Mail Api verschiedene Probleme u. a. mit dem Logger auf, die bei Java 8 wohl noch nicht auftraten. Daher nur der Hinweis...
 

Zurück
Oben