# Email via Googlemail versenden



## Scythe1988 (27. Sep 2011)

Hi
ich bin es mal wieder und verzweifel grade (mal wieder) etwas.
Folgendes Ziel will ich erreichen:
Mit meinem Programm eine Email über den Anbieter Googlemail versenden. Dieser beinhaltet einen sich nicht veränderbaren Text und einen PDF Anhang(heißt immer gleich und liegt immer an gleicher Stelle).
Ich habe mich also erstmal eingelesen und eine nette Klasse angepasst für googlemail gefunden

```
import com.sun.mail.pop3.POP3SSLStore;
import java.util.Date;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.FetchProfile;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.ContentType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.ParseException;

public class EmailGooglemail {

    private Session session = null;
    private Store store = null;
    private String username, password;
    private Folder folder;

    public EmailGooglemail() {
    }

    public void setUserPass(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public void connect() throws Exception {
        String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
        Properties pop3Props = new Properties();
        pop3Props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
        pop3Props.setProperty("mail.pop3.socketFactory.fallback", "false");
        pop3Props.setProperty("mail.pop3.port", "995");
        pop3Props.setProperty("mail.pop3.socketFactory.port", "995");
        URLName url = new URLName("pop3", "pop.gmail.com", 995, "",username, password);

        session = Session.getInstance(pop3Props, null);
        store = new POP3SSLStore(session, url);
        store.connect();

    }
```

Damit verbindet er. Habe testhalber hiermit:

```
public void openFolder(String folderName) throws Exception {

        // Open the Folder
        folder = store.getDefaultFolder();
        folder = folder.getFolder(folderName);
        if (folder == null) {
            throw new Exception("Invalid folder");
        }
        // try to open read/write and if that fails try read-only
        try {
            folder.open(Folder.READ_WRITE);
        } catch (MessagingException ex) {
            folder.open(Folder.READ_ONLY);
        }
    }
```
 und hiermit:

```
public void printAllMessages() throws Exception {
        // Attributes & Flags for all messages ..
        Message[] msgs = folder.getMessages();
        // Use a suitable FetchProfile
        FetchProfile fp = new FetchProfile();
        fp.add(FetchProfile.Item.ENVELOPE);
        folder.fetch(msgs, fp);
        for (int i = 0; i < msgs.length; i++) {
            System.out.println("--------------------------");
            System.out.println("MESSAGE #" + (i + 1) + ":");
            dumpPart(msgs[i]);
        }
    }
```
die Emails ausgeben lassen --> geht. 
So ich habe also eine funktionierende Verbindung zu googlemail aufgebaut.
Jetzt hab ich mir gedacht mach ich mir eine Methode in der Klasse die Emails versendet und da geht das elend dann los

```
public void sendMail() throws Exception {
        try {
            // Eine neue Message erzeugen
            Message msg = new MimeMessage(session);

            // Hier werden die Absender- und Empfängeradressen gesetzt
            msg.setFrom(new InternetAddress("absender@googlemail.com"));
            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("Empfaenger@bla.de", false));

            // Der Betreff und Body der Message werden gesetzt
            msg.setSubject("Ihr Ticket");
            msg.setText("Anbei übersenden wir Ihnen ihr Ticket");

            // Hier lassen sich HEADER-Informationen hinzufügen
            msg.setHeader("Test", "Test");
            msg.setSentDate(new Date());

            // Zum Schluss wird die Mail natürlich noch verschickt
            Transport.send(msg);

        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }
```

Leider bekomme ich wenn ich diese methode (nach erfolgreichem connecten) aufrufe folgenden Fehler:


> run:
> javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25;
> nested exception is:
> java.net.ConnectException: Connection refused: connect
> ...



Habe diesen natürlich mal gegooglet und dort habe ich rausgefunden, dass es eventuell etwas mti Sessions zutun haben könnte. Ich stehe grade echt wie nen Ochs vorm Berg und habe keine ahnung wo ich weiter schauen soll.
Hat jemand einen Tipp für mich? Und sry falls die Frage wieder zur allgemeinen belustigung hier im Forum beiträgt, aber ich bin ja noch dabei zu lernen


----------



## HoaX (27. Sep 2011)

Scythe1988 hat gesagt.:


> Could not connect to SMTP host: localhost, port: 25;



In deinem Code oben konfigurierst du nur den Zugriff auf den POP3-Server, und der dient nur dem Abruf von Mails.
Wenn du Mails senden willst, dann musst du auch entsprechend den SMTP-Server konfigurieren. Dazu sollten sich einige Beispiele finden lassen bei google...


----------



## Scythe1988 (27. Sep 2011)

ah das klingt logisch (schande über mein Haupt). das probier ich erstmal und meld mich dann ggf nochmal


----------



## Scythe1988 (27. Sep 2011)

So habe es jetzt wie oben gelassen und für den smtp ne eigenständige Session gemacht" smtpSession"

```
Properties smtpProps = new Properties();
        smtpProps.setProperty("smtp.gmail.com", "smtp");
        smtpProps.setProperty("mail.smtp.user",username);
        smtpProps.setProperty("mail.smtp.password", password);
        smtpProps.setProperty("mail.smtp.port", "465");
        smtpProps.setProperty("mail.smtp.auth", "true");
   
        smtpSession=Session.getInstance(smtpProps,null);
```

In der Methode die Emails senden soll verwende ich natürlich auch diese Session:

```
public void sendMail() throws Exception {
        try {
            // Eine neue Message erzeugen
            Message msg = new MimeMessage(smtpSession);

            // Hier werden die Absender- und Empfängeradressen gesetzt
            msg.setFrom(new InternetAddress("Filmtheater.Universum@googlemail.com"));
            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("mysticreaver1988@googlemail.com", false));

            // Der Betreff und Body der Message werden gesetzt
            msg.setSubject("Ihr Ticket");
            msg.setText("Anbei übersenden wir Ihnen ihr Ticket");

            // Hier lassen sich HEADER-Informationen hinzufügen
            msg.setHeader("Test", "Test");
            msg.setSentDate(new Date());

            // Zum Schluss wird die Mail natürlich noch verschickt
            Transport.send(msg);

        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }
```

jetzt bekomme ich diese Meldung:


> javax.mail.AuthenticationFailedException: failed to connect, no password specified?


Da er aber das pw und den username verwendet den auch das connecten zu pop3 verwendet muss es ja richtig sein(pop3 geht, smtp nicht).
Habe sicherlich irgendwo was google spezifisches vergessen kann das sein?


----------



## nillehammer (27. Sep 2011)

Hallo,
[Java]smtpProps.setProperty("smtp.gmail.com", "smtp");[/Java]
So ein Property kenne ich bei smtp nicht. Ich glaub, dass da was nicht richtig ist.

Und zu Deinem Authentifizierungsproblem:
Es gibt zwei Möglichkeiten, beim stmp-Transport user und Passwort zu spezifizieren. Bei keiner wird das Passwort als smtp-Property übergeben. Wie es richtig geht, wird hier beschrieben: com.sun.mail.smtp (JavaMail API documentation)
Für Deinen UseCase ist Authenticator das Stichwort.


----------



## HoaX (27. Sep 2011)

nillehammer hat gesagt.:


> 1
> 
> 
> 
> ...




Ich denke dass sollte ehr

```
smtpProps.setProperty("mail.smtp.host", "smtp.gmail.com");
```
heißen, zumindest so in der richtung. So wie momentan macht es jedenfalls keinen sinn.


----------



## Scythe1988 (27. Sep 2011)

also was ich da fabriziert habe weiß ich nicht xX habe das geändert, aber noch den gleichen Fehler. hmm bei meiner Suche habe ich desöfteren auch "Authenticator" gelesen. Ich werde mich mal schlau machen was das ist und ob/wie es mir helfen kann ^^


----------



## Scythe1988 (27. Sep 2011)

So anscheinend benötigt man den Authenticator wirklich, also wie folgt abgeändert:

```
//Erstelle smtp Eigenschaften
        Properties smtpProps = new Properties();
        smtpProps.setProperty("mail.smtp.host", "smtp.googlemail.com");
        smtpProps.setProperty("mail.smtp.user", username);
        smtpProps.setProperty("mail.smtp.password", password);
        smtpProps.setProperty("mail.smtp.socketFactory.port", "465");
        smtpProps.setProperty("mail.smtp.auth", "true");
        smtpProps.setProperty("mail.smtp.ssl.enable", "true");
        smtpProps.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
       
        Session smtpSession = Session.getDefaultInstance(smtpProps, new javax.mail.Authenticator() {

            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
```


```
public void sendMail() throws Exception {
        try {
            // Eine neue Message erzeugen
            Message msg = new MimeMessage(smtpSession);

            // Hier werden die Absender- und Empfängeradressen gesetzt
            msg.setFrom(new InternetAddress("absender@googlemail.com"));
            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("empfaenger@googlemail.com", false));

            // Der Betreff und Body der Message werden gesetzt
            msg.setSubject("Ihr Ticket");
            msg.setText("Anbei übersenden wir Ihnen ihr Ticket");

            // Hier lassen sich HEADER-Informationen hinzufügen
            msg.setHeader("Test", "Test");
            msg.setSentDate(new Date());

            // Zum Schluss wird die Mail natürlich noch verschickt
            Transport.send(msg);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
```

Der Fehler hat sich allerdings geändert



> java.lang.SecurityException: Access to default session denied


klingt ja schon einmal besser als die erste Fehlermeldung, aber wirklich was damit anfangen kann ich nicht


----------



## nillehammer (27. Sep 2011)

Der erste Gedanke bei SecurityException ist immer ein aktivierter Security Manager, in dessen Policy eine benötigter Grant fehlt.

Aber eine Google-Suche nach der von Dir geposteten Fehlermeldung ergibt als ersten Treffer das hier: Troubleshooting Java Libraries: [Java>JavaMail] java.lang.SecurityException: "Access to default session denied" occures.

Mögliche Fehlerursachen:
-Die MailApi-Jars sind in Deinem Classpath mehrfach vorhanden (z.B. unter common/lib und unter WEB-INF/lib). Dann entferne diese aus common/lib.
-Die MailApi-Jars sind nur in common/lib vorhanden. Dann verschiebe sie entweder nach WEB-INF/lib oder besorg Dir die Mail-Session über JNDI mit Container-Auth und erzeuge sie nicht in Deinem Code.


----------



## Scythe1988 (27. Sep 2011)

Das hatte ich natürlich auch gesehen, aber als ich einen blick in den classpath geworfen habe:





habe ich das ausgeschloßen, ist ja alles nur einmal drinne.

Wie genau meinst du das mit dem security Manager? Erstmal von der Programmierung her sollte jetzt alles stimmen richtig?


----------



## HoaX (27. Sep 2011)

Ansonsten poste doch mal ein KSKB wo man nurnoch oben User/Pw/EMail ändern muss ...


----------



## nillehammer (27. Sep 2011)

Scythe1988 hat gesagt.:
			
		

> habe ich das ausgeschloßen, ist ja alles nur einmal drinne.


Leider nein. Das mail.jar enthält alle Klassen der Mail-API. Also auch die, die Du dann noch mal mit den anderen jars (mailapi, pop3, smtp...) einbindest.


----------



## Scythe1988 (27. Sep 2011)

ok hab alle bis auf die mail.jar rausgeworfen --> gleicher Fehler
das KSKB kann ich gleich mal machen.


----------



## nillehammer (27. Sep 2011)

Scythe1988 hat gesagt.:
			
		

> ok hab alle bis auf die mail.jar rausgeworfen --> gleicher Fehler


Ist Deine Anwendung eine Stand-Alone Anwendung oder läuft sie evtl. in einem Web-Container (z.B. Tomcat) oder in einem JEE-Container (z.B. Glassfish). Dann könnte es nämlich sein, dass die mail-Jars dort bereits in lib-Ordnern liegen und Du sie selber garnicht mit deployen musst/darfst.


----------



## Scythe1988 (27. Sep 2011)

ne ist stand alone. Folgende neue Erkenntnis:

```
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.swing.JOptionPane;

public class SendMailSSL {
	public static void main(String[] args) {
		Properties props = new Properties();
                props.put("mail.smtp.host", "smtp.gmail.com");
		props.put("mail.smtp.socketFactory.port", "465");
		props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.port", "465");

		Session session = Session.getDefaultInstance(props,
			new javax.mail.Authenticator() {
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication("loginname","pw");
				}
			});

		try {

			Message message = new MimeMessage(session);
			message.setFrom(new InternetAddress("sender@googlemail.com"));
			message.setRecipients(Message.RecipientType.TO,
					InternetAddress.parse("empfaenger@googlemail.com"));
			message.setSubject("Testing Subject");
			message.setText("Dear Mail Crawler," +
					"\n\n No spam to my email, please!");

			Transport.send(message);

			System.out.println("Done");

		} catch (MessagingException e) {
			throw new RuntimeException(e);
		}
	}
}
```
Das läuft, aber mache ich es so (gleicher Code!):
EmailGooglemail.java:

```
public void connectsmtp() throws Exception {

        //Erstelle smtp Eigenschaften
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");

        Session smtpSession = Session.getDefaultInstance(props,
                new javax.mail.Authenticator() {

                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication("Loginname", "pw");
                    }
                });
    }
```


```
public void sendMail() throws Exception {
        
        try {

            Message message = new MimeMessage(smtpSession);
            message.setFrom(new InternetAddress("sender@googlemail.com"));
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse("emfaenger@googlemail.com"));
            message.setSubject("Testing Subject");
            message.setText("Dear Mail Crawler,"
                    + "\n\n No spam to my email, please!");

            Transport.send(message);

            System.out.println("Done");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }



    }
```

Emailtesten.java:

```
public static void main(String[] args) {

        try {
            EmailGooglemail gmail = new EmailGooglemail();
            gmail.setUserPass("Loginname", "pw");
           
            //verbinde via smtp für Emailversand
            gmail.connectsmtp();
            gmail.sendMail();


       

           
        } catch(Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }

    }
```
Da kommt dann der Fehler, obwohl es eigentlich der gleiche Code ist(nur eben anders aufgeteilt).

€: gibt mit sicherheit probleme wegen der session seh ich das richtig?

€²: wisst ihr was es macht eigentlich garkein sinn das connecten und versenden in 2 methoden zu packen (die nutzen eh nur einen anbieter). Werde das alles in eins schreiben und dann funktioniert es ja


----------



## HoaX (27. Sep 2011)

Dein Problem mit den zwei Methoden ist, dass du smtpSession in der connect-Methode als lokale Variable definiert hast. Ich vermute mal dass du noch eine weitere Variable gleiche Namens als Attribut der Klasse definiert hast und dass in deiner sende-Methode dann einfach immer null ist.


----------



## TheRealSpikee (29. Sep 2011)

Ich vermute du hast es nach einem Beispiel wie diesem versucht : JavaMail API – Sending email via Gmail SMTP example

Das Problem bei diesen Beispielen ist : es wird eine Session und ein Transport erstellt ... und dann die STATIC Methode Transport.send(Message) verwendet ... das heißt das komplette set-up der Connection ist sinnlos da diese STATIC Methode ihre eigene Verbindung verwendet ... zu lesen in der Doc ..

Ich habe mir darauf hin mal die Mühe eines Tutorials gemacht was auch wirklich funktioniert da ich diesen FEHLER beseitigt habe
E-Mails mit JavaMail versenden @ tutorials.de: Tutorials, Forum & Hilfe
An deine Wünsche angepasst sollte es funktionieren.


Und warum macht ihr alle immer wieder den selben Fehler was das angeht : weil keiner die DOC liest in der das drin steht und niemand merkt das Transport.send(Message) ein STATIC call ist ... und damit alle Objekte die man erstellt und verbunden hat überflüssig werden ...


----------



## HoaX (29. Sep 2011)

Junge, bitte verzapf doch nicht immer so einen Bullshit und tu nich immer so als hättest du den Durchblick!

Der von dir genannte Fehler hat nichts mit Javamail zu tun sondern mit mangelndem Verständnis des Entwicklers! Klar muss sich die statische Methode selbst ihre Connection erstellen, wie soll sie auch an die andere ran kommen? Dafür brauch ich keine Doc lesen...
Und wieso machen wir *alle* den Fehler?

Transport#send funktioniert einwandfrei, wenn man seine Session passend konfiguriert hat, denn über diese holt sich Transport dann seine Connection.


----------

