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:
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?
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:
Java:
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;
}
}
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?