# Java Mail - Multipart anzeigen



## GUI-Programmer (7. Dez 2011)

Hallo

Ich habe vor einiger Zeit ein Programm geschrieben, das ich als "Google Mail Desktop Application" bezeichne. Dieses Programm ermöglicht es Googlemail Nutzern ihr Mails auserhalb eines Browsers zu checken, zu schreiben und zu löschen.
Das funktioniert auch alles ohne Weiteres, bis darauf, dass es mir nicht gelingt, manche Nachrichten zu lesen, deren ContentType vom Typ multipart ist, und deren BodyPart Typ wieder vom Typ mulitpart ist.

Hier mal die wichtigste Klasse:

```
import java.io.File;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.ContentType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

/**
 * Klasse MailTool
 * 
 * @author GUI-Programmer
 * @version 07.12.2011
 */
public class MailTool {
	// Attribute
	private String username, password;
	private Session session1;
	private Transport transport;
	private Store store;
	private Message[] message;
	private ArrayList<DataHandler> datahandlers;
	private ArrayList<Integer> bodyPartSizes;
	private Folder folder;
	private boolean showDialog;
	private int mailNumber;
	private String userhome;
	private String separator;
	
	// Konstruktor
	public MailTool() {
		username = null;
		password = null;
		session1 = null;
		transport = null;
		store = null;
		datahandlers = new ArrayList<DataHandler>();
		bodyPartSizes = new ArrayList<Integer>();
		showDialog = false;
		mailNumber = -1;
		userhome = System.getProperty("user.home");
		separator = System.getProperty("file.separator");
	}
	
	// Methoden
	/**
	 * Es wird versucht eine Verbindung zu Googlemail aufzubauen und sich
	 * dort mit den Benutzernamen und den Passwort einzuloggen.
	 * @param username
	 * @param password
	 * @throws Exception
	 */
	public void login(final String username, final String password) throws Exception {
		MailTool.this.username = username;
		MailTool.this.password = password;
		
		Properties props1=new Properties();
		props1.put("mail.smtp.port", "587");
        props1.put("mail.smtp.auth", "true");
        props1.put("mail.smtp.starttls.enable", "true");
        session1 = Session.getInstance(props1);
        transport = session1.getTransport("smtp");
		transport.connect("smtp.googlemail.com", username, password);
		
		Properties props2 = System.getProperties();
		props2.setProperty("mail.store.protocol", "imaps");
		props2.setProperty("mail.imaps.partialfetch", "false");
    	props2.setProperty("mail.imap.host", "imap.gmail.com");
    	props2.setProperty("mail.imap.port", "993");
    	props2.setProperty("mail.imap.connectiontimeout", "5000");
    	props2.setProperty("mail.imap.timeout", "5000");
    	Session session2 = Session.getDefaultInstance(props2, null);
    	store = session2.getStore("imaps");
    	store.connect("imap.gmail.com", username, password);
    	folder = store.getFolder("INBOX");
    	folder.open(Folder.READ_WRITE);
	}
	
	/**
	 * Versucht eine E-Mail an die angegebene Addresse/-n zu senden.
	 * @param recipientAddresses
	 * @param subject
	 * @param mailText
	 * @throws Exception
	 */
	public void sendMail(String recipientAddresses, String subject, String mailText, ArrayList<File> filelist) throws Exception {
		login(username, password);
    	Address[] addresses = InternetAddress.parse(recipientAddresses);
		Message message = new MimeMessage(session1);
        message.setFrom(new InternetAddress(username));
        message.setRecipients(Message.RecipientType.TO, addresses);
        message.setSubject(subject);
        // create the message part 
        Multipart multipart = new MimeMultipart();
        MimeBodyPart textBodyPart = new MimeBodyPart();
        textBodyPart.setText(mailText);
        multipart.addBodyPart(textBodyPart);
        for(int i=0; i<filelist.size(); i++) {
        	MimeBodyPart attachementBodyPart = new MimeBodyPart();
            DataSource source = new FileDataSource(filelist.get(i));
            attachementBodyPart.setDataHandler(new DataHandler(source));
            attachementBodyPart.setFileName(filelist.get(i).getName());
            multipart.addBodyPart(attachementBodyPart);
        }
        message.setContent(multipart);
        
        transport.sendMessage(message, addresses);
        transport.close();
	}
	
	public void deleteMail(int number) throws Exception {
		message = folder.getMessages();
		int index = message.length - number-1;
		message[index].setFlag(Flags.Flag.DELETED, true);
		folder.close(true);
		folder.open(Folder.READ_WRITE);
	}
	
	/**
	 * Die Anhänge der ausgewählten E-Mail werden ermittelt und als Strings zurückgegeben.
	 * @param number
	 * @return
	 * @throws Exception
	 */
	public ArrayList<String> getAttachments(int number) throws Exception {
		final ArrayList<String> attachments = new ArrayList<String>();
		datahandlers.removeAll(datahandlers);
		bodyPartSizes.removeAll(bodyPartSizes);
		
		login(username, password);
		message = folder.getMessages();
		int index = message.length - number;
		
		if(message[index].getContentType().toString().startsWith("multipart")) {
			Multipart content = (Multipart) message[index].getContent();
			for(int i=0; i<content.getCount(); i++) {
				BodyPart part = (BodyPart) content.getBodyPart(i);
				String fileName = part.getFileName();
				if(isAttachement(part.getContentType(), fileName)) {
					fileName = encordeAttachement(fileName);
					attachments.add(fileName);
					
					datahandlers.add(part.getDataHandler());
					bodyPartSizes.add(part.getSize());
				}
			}
		}
		return attachments;
	}
	
	private boolean isAttachement(String contentType, String fileName) {
		boolean isAttachement = false;
		if(!contentType.startsWith("text/html")
		&& !contentType.startsWith("text/rtf")
		&& !contentType.startsWith("text/plain")
		&& fileName != null) {
			isAttachement = true;
		}
		return isAttachement;
	}
	
	private String encordeAttachement(String s) throws UnsupportedEncodingException {
		String temp = MimeUtility.decodeText(s);
		String decoded = Normalizer.normalize(temp, Normalizer.Form.NFC);
		return decoded;
	}
	
	/**
	 * Der Text der ausgewählten E-Mail wird ermittelt und als String zurückgegeben.
	 * @param number
	 * @return
	 * @throws Exception
	 */
	public String readMail(int number) throws Exception {
		mailNumber = number;
		String text = null;
		
		message = folder.getMessages();
		int index = message.length - number;
		ContentType contentType = new ContentType(message[index].getContentType());
		String type = contentType.getPrimaryType()+"/"+contentType.getSubType();
		if(type.equals("TEXT/PLAIN")) {
			System.out.println("TEXT/PLAIN");
			text = message[index].getContent().toString();
		} else if(type.equals("TEXT/HTML")) {
			System.out.println("TEXT/HTML");
			text = HTML2Text.convert(message[index].getContent().toString());
		} else if(contentType.toString().startsWith("multipart")) {
			System.out.println("multipart");
			text = getMultiPartText(message[index]);
		}
		
		return text;
	}
	
	/**
	 * Behandelt den Inhalt einer E-Mail als multipart-Typ und versucht
	 * ihn als String zu konvertieren.
	 * @param m
	 * @return
	 * @throws Exception
	 */
	private String getMultiPartText(Message m) throws Exception {
		String text = null;
		StringBuffer buffer = new StringBuffer();
		MimeMultipart content = (MimeMultipart) m.getContent();
	     for(int i=0; i<content.getCount(); i++) {
	      BodyPart part = content.getBodyPart( i );
	      ContentType ct = new ContentType(part.getContentType());
	      String type = ct.getPrimaryType()+"/"+ct.getSubType();
	      if(type.equals("TEXT/PLAIN")) {
	    	  buffer.append(part.getContent().toString());
	      } else if(type.equals("TEXT/HTML")) {
	    	  buffer.append(HTML2Text.convert(part.getContent().toString()));
	      } else if(type.startsWith("multipart")) {
	    	  // Wie komme ich an die Nachricht ???
	      }
	      text = buffer.toString();
	     }
		return text;
	}
	
	/**
	 * Gibt den Benutzernamen das Nutzers zurück.
	 * @return
	 */
	public String getUsername() {
		String user;
		if(username.endsWith("@googlemail.com")) {
			user = username.replaceAll("@googlemail.com", "");
		} else {
			user = username;
		}
		return user;
	}
	
	/**
	 * Liefert 2 String-Arrays. Das 1. enthält die Namen aller Absender
	 * der E-Mails, das 2. die dazugehörigen Betreffe.
	 * @return
	 */
	public String[][] getMails(final JProgressBar progress) {
		progress.setValue(0);
		String[][] mails = null;
		try {
			message = folder.getMessages();
			mails = new String[message.length][message.length];
			final String[] from = new String[message.length];
			final String[] subject = new String[message.length];
			progress.setMaximum(message.length);
			
			for (int i=message.length-1; i>0; i--) {
				try {
					int temp = message.length-i;
					Address[] froms = message[i].getFrom();
					String email = froms == null ? null : ((InternetAddress) froms[0]).getAddress();
					from[temp] = email;
					subject[temp] = message[i].getSubject();
					if(subject[temp] == null) subject[temp] = "<Kein Betreff>";
					progress.setValue(temp);
				} catch(Exception ignore) { }
			}
			progress.setValue(progress.getMaximum());
			
			mails = new String[][] {from, subject};
		} catch(Exception ex) {
			ex.printStackTrace();
		}
		return mails;
	}
	
	public void downloadFile(final String filename, final int attachmentNumber, final Downloads dialogDownloads, final File directory) {
		dialogDownloads.setTitle("Aktiver Download");
		dialogDownloads.setVisible(true);
		dialogDownloads.lblFileName.setText(filename+" wird heruntergeladen...");
		dialogDownloads.prgrsbr.setValue(0);
		
		final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
			@Override
			protected Void doInBackground() throws Exception {
				showDialog = true;
				
				Thread.sleep(200);
				dialogDownloads.prgrsbr.setIndeterminate(true);
				
				File file = new File(directory.getAbsolutePath()+separator+filename);
				if(!file.exists()) file.createNewFile();
				
				FileOutputStream fos = new FileOutputStream(file);
				datahandlers.get(attachmentNumber).writeTo(fos);
				fos.close();
				return null;
			}
			
			@Override
			public void done() {
				showDialog = false;
				dialogDownloads.prgrsbr.setIndeterminate(false);
				dialogDownloads.prgrsbr.setValue(100);
				dialogDownloads.setTitle("Download abgeschlossen");
				
				Thread t = new Thread() {
					boolean run = true;
					public void run() {
						while(run) {
							try {
								sleep(3000);
							}
							catch(InterruptedException ex) {
								ex.printStackTrace();
							}
							run = false;
							dialogDownloads.setVisible(showDialog);
						}
					}
				};
				t.start();
			}
		};
		worker.execute();
	}
	
	public void downloadAllFiles(final Downloads dialogDownloads, final File directory) {
		System.out.println(directory.getAbsolutePath());
		dialogDownloads.setTitle("Aktiver Download");
		dialogDownloads.prgrsbr.setValue(0);
		dialogDownloads.setVisible(true);
		SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
			private ArrayList<String> fileList = null;
			@Override
			protected Void doInBackground() throws Exception {
				Thread.sleep(200);
				dialogDownloads.prgrsbr.setIndeterminate(true);
				
				Thread t1 = new Thread(new Runnable() {
					public void run() {
						try { fileList = getAttachments(mailNumber); }
						catch(Exception ex) { ex.printStackTrace(); }
					}
				}); t1.start(); t1.join();
				
				for(int i=0; i<fileList.size(); i++) {
					dialogDownloads.lblFileName.setText(fileList.get(i)+" wird heruntergeladen...");
					final int k = i;
					Thread t2 = new Thread(new Runnable() {
						public void run() {
							try {
								File file = new File(directory.getAbsolutePath()+separator+fileList.get(k));
								if(!file.exists()) file.createNewFile();
								
								FileOutputStream fos = new FileOutputStream(file);
								datahandlers.get(k).writeTo(fos);
								fos.close();
							}
							catch(Exception ex) { ex.printStackTrace(); }
						}
					}); t2.start(); t2.join();
					dialogDownloads.prgrsbr.setIndeterminate(false);
					dialogDownloads.prgrsbr.setValue(100);
					Thread.sleep(100);
				}
				return null;
			}
			
			@Override
			protected void done() {
				dialogDownloads.setTitle("Downloads abgeschlossen");
				Thread t3 = new Thread(new Runnable() {
					public void run() {
						try {
							Thread.sleep(3000);
							dialogDownloads.setVisible(false);
						}
						catch(InterruptedException ex) { ex.printStackTrace(); }
					}
				}); t3.start();
			}
		};
		worker.execute();
	}
	
	public boolean logout() {
		boolean logout = false;
		Thread t = new Thread(new Runnable() {
			public void run() {
				try {
					store.close();
				}
				catch(MessagingException ex) {
					ex.printStackTrace();
				}
			}
		});
		t.start();
		try {
			t.join();
			logout = true;
		} catch(InterruptedException ex) {
			ex.printStackTrace();
		}
		return logout;
	}
	
	
}
```
Um das Programm auszuführen, muss sich der resources Ordner im selben Verzeichnis befinden wie die executable jar bzw. die class Dateien.

P.S. Später hab ich auch mal vor den Text in der JEditorPane mit Formatierung anzuzeigen, d.h. bie Html ist dies ja leicht, allerdings, was wenn nur Teile der Nachricht aus Html bestehen?


----------



## GUI-Programmer (8. Dez 2011)

Ach ja, um das Programm auszuführen, so wie es ist, benötigt ihr noch das TinyLookAndFeel, welches ihr z.B, hier herunterladen könnt.


----------



## GUI-Programmer (14. Dez 2011)

Hat irgendjemand ne Idee oder vielleicht gar nen komplett anderen Ansatz/Vorgehnsweise?


----------



## AlexSpritze (14. Dez 2011)

Wo ist jetzt genau das Problem?

So wie ich das bisher gesehen hatte, kannst du eine schöne, baumartige Struktur in deiner MimeMessage haben:


```
multipart/mixed
--multipart/related
----multipart/alternative
------text/plain << body der nachricht ohne HTML
------text/html << body der Nachricht mit HTML
----image/jpeg << eine Inline-Grafik, die in dem HTML referenziert wird
--application/whatever << irgendein Anhang
```

Das heißt, du musst dich da irgendwie durchhangeln.


----------



## GUI-Programmer (14. Dez 2011)

AlexSpritze hat gesagt.:


> Das heißt, du musst dich da irgendwie durchhangeln.



Genau das ist mein Problem!!! Ich weiß eben nicht wie ich in dieser Baumstruktur weiter nach unten kommen soll, bzw. wie ich das rekursiv implementieren kann.


----------



## AlexSpritze (14. Dez 2011)

```
Multipart part = (Multipart)mehl.getContent(); // davon ausgehend, dass getContent() ein Multipart liefert
for (int i = 0 ; i < part.getCount(); i++){
  BodyPart bodyPart = part.getBodyPart(i);
  Object content = bodyPart.getContent();
  if(content instanceof Multipart) {
    // hier dann wieder oben anfangen
  }
}
```


----------



## GUI-Programmer (14. Dez 2011)

Danke, werd ich demnächst mal ausprobieren!


----------



## GUI-Programmer (14. Dez 2011)

Super hat geklappt! Nun wird der gesamte Text einer Nachricht angezeigt.

Doch in manchen fällen funktioniert irgendwie die Umwandlung des HTML-Textes zu Plain-Text nicht. Die Klasse die dies macht, habe ich mir (ich glaube sogar hier) aus irgendnen Forum kopiert und sie etwas angepasst.

Jedoch ist mein Plan folgender: 
Irgendwie den HTML Text richtig in der JEditorPane darstellen. Ich weis zwar, dass ich den ContentType der JEditorPane auf "text/html" umstellen kann. Dann allerdings wird der gesamte Text ohne Zeiilenumbrüche dargestellt. Ist es denn möglich dies zu verhindern, sodass, wenn der 'Bodypartcontenttype' "text/html", dieser auch so richtig dargestellt wird?


----------



## AlexSpritze (14. Dez 2011)

Zeilenumbrüche werden bei der Anzeige von HTML ja ignoriert, stehen in dem HTML denn wenigstens 
	
	
	
	





```
<br/>
```
?


----------



## GUI-Programmer (14. Dez 2011)

AlexSpritze hat gesagt.:


> Zeilenumbrüche werden bei der Anzeige von HTML ja ignoriert, stehen in dem HTML denn wenigstens
> 
> 
> 
> ...



Das Problem bei einer multipart message ist ja, dass eben nicht nur html sondern auch text/plain mit darin vorkommt. D.h. wenn ich die JEditorPane auf html einstelle, kann ich die html teile zwar schön (mit unterschiedlichen textgrößen, untrerstreichung, farben, etc.) darstellen lassen, die normalen text teile jedoch müsste ich anders behandeln. Evtl. hilft es ja die \n bei bei einem "text/plain" String zu <br/> zu machen???


----------



## GUI-Programmer (14. Dez 2011)

Das Austauschen von "\n" zu "<br/>" hat perfekt geklappt. So wird zum Beispiel eine Webung von Amazon nun perfekt (wie in Googlemail selbst) darsgestellt. Allerdings werden manche Nachrichten garnicht dargestellt, was aber mit den Tausch nichts zu tun hat. Bei den Lesevorgang ertönt dass bekannte Windows-Ping und es wird garnichts in der JEditorPane angezeigt.
Meine Vermutung ist, dass irgendwelche Sicherheitsverstöße vorliegen, wenn zum Beispiel ein Bild von einer Website benutzt werden soll oder sowas ähnliches. Wie kann ich das Problem umgehen? Bzw. liegt es daran?

Hier ist der HTML Nachrichtentext bei dem der Fehler/Block mit Ping Geräusch entsteht:

```
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.6002.18457" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2>Hallo NameXY,</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>habe Info über MATSE unter</FONT></DIV>
<DIV><FONT face=Arial size=2><A 
href="http://www.kischuni.de/ausbildung/Wie-werde-ich-Mathematisch-technischer-Softwareentwickler-33.html">http://www.kischuni.de/ausbildung/Wie-werde-ich-Mathematisch-technischer-Softwareentwickler-33.html</A></FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Infos über diesen und ähnliche Berufe unter 
</FONT></DIV>
<DIV><FONT face=Arial size=2><A 
href="http://berufenet.arbeitsagentur.de/berufe/start?dest=profession&amp;prof-id=51029">http://berufenet.arbeitsagentur.de/berufe/start?dest=profession&amp;prof-id=51029</A></FONT></DIV>
<DIV><FONT face=Arial size=2>&nbsp;</DIV>
<DIV>Ausbildungsplatz 2012 Fresenius</DIV>
<DIV><A 
href="http://azubi-bei-fmc.de/ausbildung/systeminformatikerin.html">http://azubi-bei-fmc.de/ausbildung/systeminformatikerin.html</A></DIV>
<DIV><BR style="CLEAR: both" xmlns="http://www.w3.org/1999/xhtml" 
xmlns:xalan="http://xml.apache.org/xalan"></FONT><FONT face=Arial size=2>Viele 
Grüße Name2XY</FONT></DIV></BODY></HTML>
```


----------



## AlexSpritze (15. Dez 2011)

GUI-Programmer hat gesagt.:


> Das Problem bei einer multipart message ist ja, dass eben nicht nur html sondern auch text/plain mit darin vorkommt. D.h. wenn ich die JEditorPane auf html einstelle, kann ich die html teile zwar schön darstellen lassen, die normalen text teile jedoch müsste ich anders behandeln. Evtl. hilft es ja die \n bei bei einem "text/plain" String zu <br/> zu machen???



Das ist eigentlich kein Problem. Du kannst aus der Multipart-Message genau die Teile rausziehen, die dich interessieren. Wie oben in dem Schema angedeutet, kann eine solche Nachricht ihre Body in HTML und Plain-Text enthalten. Dabei ist davon auszugehen, dass Plain-Text dem HTML gleicht, nur eben ohne die ganzen Auszeichnungen. Das heißt, du kannst aktiv schauen, ob einen HTML-Nachrichtentext anzeigen kannst, oder ob du nur Plain-Text zur Verfügung hast.

Wenn dir ein Multipart per 
	
	
	
	





```
getContentType()
```
 mitteilt, dass es "multipart/alternative" ist, kannst du davon ausgehen, dass darin zwei Bodyparts sind: einer für HTML und einer für "text/plain", welcher welcher ist, bekommst du auch wieder mit 
	
	
	
	





```
getContentType()
```
 raus.


----------



## GUI-Programmer (15. Dez 2011)

Weiß jemand woher der Fehler/Block mit dem Windows Ping Sound kommt? Schließlich könnte man ja selbst so eine HTML Datei irgenwo gespeichert haben, dann sollte doch eigentlich auch sowas nicht geschehen.


----------



## GUI-Programmer (15. Dez 2011)

Habe etwas seltsames festgestellt:
Hab diesen HTML Text in einer .html Datei abgespeichert und diese dann per setPage() Methode in die EditorPane geladen, und siehe da, es funktioniert!

Daraus komme ich zur Schlussfolgerung, dass es nicht möglich ist in einer EditorPane mehrer HTML Texte, also mit mehreren <HTML> </HTML> Tags, sowie den <!DOCTYPE HTML PUBLIC " Zeug darzustellen. Das ist die Fehlermeldung.


Deswegen meine nächste Frage:
Kann man irgendwie mehrere HTML-Texte zu einem zusammenfügen, also dass nur einmal <!DOCTYPE HTML PUBLIC "... und <HTML> </HTML> in den Text drin vorkommt, oder ist das unmöglich?
Wenn ja, dann frag ich mich aber, wie es die ganzen Mail - Programme machen!!!


----------



## GUI-Programmer (15. Dez 2011)

Oder kann man vielleicht die Htmls zu einer Rtf machen, und die dann anzeigen lassen?

Oder muss man tatsächlich jeden HTML-Part in einer seperaten JEditorPane anzeigen lassen, denn das würde nämlich funktionieren. Allerdings wäre dabei dann der Aufwand wieder sehr hoch, da man dann ein JPanel braucht mit nen ganz bestimmten LayoutManager, bei dem JEditorPanes hinzugfügen kann nach Bedarf. Dann müsste man zusätzlich noch das Copy & Past für mehrere JEditorPanes irgendwie auf die Reihe bekommen.

Das wäre ne menge Arbeit, die ich mir gerne ersparen möchte, bzw. vielleicht werde, falls es nicht anders geht.

Nochmals vielen Dank für die Beiträge!!!!



P.S. Wenn das dann alles mal klappen sollte gibts selbstverständlich noch mal das ganze Projekt mir Sources!!!


----------



## AlexSpritze (15. Dez 2011)

Also du hast jetzt mehrere HTML-Bodyparts in deiner Mail oder wie? Eine davon wird der Nachrichtentext sein, sozusagen der Body der E-Mail. Und etwaige andere sind Anhänge. 

Das sind alles Mails, die von googlemail.com generiert worden sind? Die sollten eigentlich schon vernünftig zusammengebaut sein.


----------



## GUI-Programmer (16. Dez 2011)

AlexSpritze hat gesagt.:


> Also du hast jetzt mehrere HTML-Bodyparts in deiner Mail oder wie? Eine davon wird der Nachrichtentext sein, sozusagen der Body der E-Mail. Und etwaige andere sind Anhänge.
> 
> Das sind alles Mails, die von googlemail.com generiert worden sind? Die sollten eigentlich schon vernünftig zusammengebaut sein.



Nicht immer...
Meist liegt es wirklich daran, dass es sich um Anhänge handelt, manchmal aber auch nicht, da diese Beispiel HTML Nachricht keinen Anhang enthält!


----------



## AlexSpritze (16. Dez 2011)

Um mal wirklich die ultimative Debugging Anzeige deiner Mails zu realisieren, solltest du dich mit einem IMAP-Client, vorzugsweise Thunderbird, auf googlemail.com verbinden und dir den Quelltext der Nachrichten anschauen. Da siehst du dann sofort was wirklich drin ist  So hab ich das auch gemacht, und es wurde vieles klarer, als immer nur mit Multipart und BodyPart zu hantieren.


----------



## GUI-Programmer (16. Dez 2011)

Bedeutet dass, dass ich Thunderbird 8.0 (z.B. von Chip) runterladen soll? Kann ich damit dann auch meine Mails auf dem Server lassen und mit Thunderbird von dort löschen? Denn das war nämlich erstmal der Hauptgrund warum ich mir überhaupt ein Mail Programm geschrieben habe. Denn bei Outlook ist mir auch nach langer Internet Recherche nicht gelungen Mails mit dem Programm selbst zu löschen.

Wann das Thunderbird kann, bräuchte ich eigentlich mein derzeititges Mail Programm nicht mehr weiterzuschreiben, wobei ich dass dann vermutlich aus Interesse und des Lernens wegen wohl doch machen werde.


----------



## GUI-Programmer (16. Dez 2011)

@AlexSpritze: Noch mal Danke!!! Thunderbird ist echt super!!!

1. Die Mails werden richtig dargestellt (Was mir ja nicht so gelungen ist!)
2. Ganz wichtig: Man kann Mails mit nur einen Klick sofort direkt vom Server löschen!
3. Thunderbird (8.0 Final) löscht nicht ohne weiteres die Mails vom Server nachdem sie runtergeladen wurden.
4. Man kann alles "mit dem Server handhaben" (Papierkorb vom Server benutzten, Postausgang vom Server, etc.)

==> Im Vergleich zu Outlook siegt Thunderbird für mich so ziemlich in jeden Bereich und ist zudem im Gegensatz zu diesen auch noch kostenlos!


P.S. Thema lass ich vorerst mal noch offen, da ich wie bereits erwähnt vielleicht doch noch etwas weiterprogrammieren will.


----------



## AlexSpritze (16. Dez 2011)

Ja Thunderbird ist wirklich top für die Zwecke. Es ist auch quellenoffen, allerdings nicht mit Java programmiert.

Da gibt es aber auch noch Unterschiede, ob du dich per POP3 mit einem Mailkonto verbindest, oder mit IMAP. Letzteres wird von den wenigstens kostenlosen Mailanbietern angeboten. POP3 dagegen fast immer, es ist aber auch weniger komfortabel (keine Ordnerstruktur möglich, prinzipiell werden Mails vom Server runtergeladen und dort dann gelöscht, etc.)


----------

