Archivo

Entradas Etiquetadas ‘imap’

Borrando correos masivamente usando Javamail

Martes, 30 de Diciembre de 2008

Este articulo es una mejora al código que escribí anteriormente. Jugando un poco con Gmail me di cuenta que los correos aún pueden ser recuperados usando POP3, pese a que fueron borrados con IMAP. Realmente bizarro. Así que modifiqué el programa para que manejara un poco mejor el caso de POP3 o IMAP según las propiedades.

Aquí está el código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package com.kodegeek.blog.mail;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
 
import javax.mail.Session;
import javax.mail.Flags.Flag;
import javax.mail.internet.MimeMessage;
import javax.mail.Message;
 
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Store;
 
import com.sun.mail.imap.IMAPFolder;
 
import java.io.FileInputStream;
 
/**
 * I wrote this program to erase ALL the email on my GMAIL account. I have over 40,000 email so manually doing so was not an option :)
 * Please check the following resources:
 * <ul>
 * <li> http://java.sun.com/products/javamail/javadocs/index.html</li>
 * <li> http://java.sun.com/developer/onlineTraining/JavaMail/contents.html</li>
 * <li> http://java.sun.com/products/javamail/javadocs/com/sun/mail/imap/package-summary.html</li>
 * <li> http://java.sun.com/products/javamail/downloads/index.html</li>
 * </ul>
 * Also define a properties file with the following (adjust it to your configuration):
 * # As defined by the Javadoc
 * <ul>
 * <li> mail.user=name.lastname@gmail.com</li>
 * <li> mail.password=zzz</li>
 * <li> mail.store.host=pop.imap.gmail.com</li>
 * <li> mail.store.protocol=imap</li>
 * <li> mail.imap.port=993</li>
 * <li> mail.imap.socketFactory.port=993</li>
 * <li> mail.imap.socketFactory.class=javax.net.ssl.SSLSocketFactory</li>
 * </ul>
 * More examples:
 * <ul>
 * <li>POP3: -Dmail.user=name.lastname@gmail.com  -Dmail.password=XXXX -Dmail.store.host=pop.gmail.com -Dmail.store.protocol=pop3 -Dmail.store.folder=INBOX -Dmail.pop3.port=995 -Dmail.pop3.socketFactory.port=995 -Dmail.pop3.socketFactory.class=javax.net.ssl.SSLSocketFactory</li>
 * <li>IMAP: -Dmail.user=name.lastname@gmail.com  -Dmail.password=XXXX -Dmail.store.host=imap.gmail.com -Dmail.store.protocol=imap -Dmail.store.folder=INBOX -Dmail.imap.port=993 -Dmail.imap.socketFactory.port=993 -Dmail.imap.socketFactory.class=javax.net.ssl.SSLSocketFactory</li>
 * </ul>
 * License: GPL
 * http://kodegeek.com
 * @author Jose Vicente Nunez Zuleta
 * @version 12/28/2008
 */
public final class MailBulkEraser {
 
	/**
	 * Command line processing
	 * @param args [0] Location of the properties configuration file, If not provided then will use system defaults (defined with -D)
	 * @throws Exception
	 * @since 0.1
	 */
	public static void main(String [] args) throws Exception {
 
		Logger logger = Logger.getLogger(MailBulkEraser.class.getName());
 
		Properties props = System.getProperties();
		if (args.length == 1) {
			props.load(new FileInputStream(args[0]));
		}
		Session session = Session.getInstance(props, null);
		session.setDebug(Boolean.parseBoolean(props.getProperty("debug")));
		Store store = session.getStore(props.getProperty("mail.store.protocol"));
		logger.info(String.format("Connecting to: %s@%s", props.getProperty("mail.user"), props.getProperty("mail.store.host")));
		store.connect(props.getProperty("mail.store.host"), props.getProperty("mail.user"), props.getProperty("mail.password"));
		Folder folder = store.getDefaultFolder();
		logger.info("Got default folder. Erasing emails from ALL the folders");
		Folder [] folders = folder.list();
		long messgCnt = 0;
		for(Folder currFolder: folders) {
 
			try {
 
				if ((currFolder.getType() & Folder.HOLDS_MESSAGES) == 0) {
					continue; // Skip this folder type
				}
				logger.info(String.format("Opening folder: %s, num messages; %d", currFolder.getFullName(), currFolder.getMessageCount()));
				currFolder.open(Folder.READ_WRITE);
				Message [] messages = currFolder.getMessages();
 
				// Mark all the messages for delete
				for (Message message: messages) {
					try {
						if (! currFolder.isOpen()) {
							logger.warning(String.format("Folder %s is closed. Moving to next folder", currFolder.getFullName()));
							break;
						}
						message.setFlag(Flag.DELETED, true);
						MimeMessage currMessage = (MimeMessage) message;
						logger.info(String.format("Deleting mail subject: '%s', folder: '%s', date: '%s'", currMessage.getSubject(), currMessage.getFolder().getFullName(), currMessage.getSentDate()));
						if (currFolder instanceof IMAPFolder) {
							messages = currFolder.expunge(); // Confirm delete for all the messages on the current folder
						}
						messgCnt += 1;
					}  catch (Throwable thrbl) {
						logger.log(Level.WARNING, "There was a problem erasing the message, ignoring", thrbl);
						continue;
					}
				}
 
				logger.info(String.format("Messages erased on folder %s: %d", currFolder.getFullName(), messages.length));
				currFolder.close(true);
 
			} catch (MessagingException messgExp) {
				logger.log(Level.WARNING, "There was a problem, ignoring", messgExp);
			}
 
		}
		logger.info(String.format("Total number of erased messsages: %d", messgCnt));
		store.close();
		System.exit(0);
	}
 
}

Nota de los cambios:

Que lo disfruten :) .

java, kodegeek, opensource , , , , , ,

¿Como borrar 40000 correos en Gmail? Fácil, usando Javamail e IMAP

Domingo, 28 de Diciembre de 2008

Este fin de semana me decidí a poner un poco de orden en mis cuentas de correo; Una de las cosas que me obligó a ello es que mi cuenta paga de Yahoo expiró y aún ando debatiendo si debo pagar $20 por una cuenta de correo que no ofrece nada por encima de Gmail. Al momento de revizar mi cuenta de Gmail me encuentro con que estoy usando por encima de 1 GB en correo con más de 40000 correos.

Si, es increíble la cantidad de basura que se acumula en dos años :)

Definitivamente no estaba dispuesto a perder mi tiempo borrando tal cantidad de correos a mano, en vez de eso me decicí a automatizar la tarea usando Java y el hecho de que Gmail soporta POP / IMAP (Javamail cuenta con accesso a IMAP comp arte de su API). Una vez leido un poco abrí mi Eclipse y el resultado es el código que viene a continuación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package com.kodegeek.blog.mail;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
 
import javax.mail.Session;
import javax.mail.Flags.Flag;
import javax.mail.internet.MimeMessage;
import javax.mail.Message;
 
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Store;
 
import java.io.FileInputStream;
 
/**
 * I wrote this program to erase ALL the email on my GMAIL account. I have over 40,000 email so manually doing so was not an option :)
 * Please check the following resources:
 * <ul>
 * <li> http://java.sun.com/products/javamail/javadocs/index.html</li>
 * <li> http://java.sun.com/developer/onlineTraining/JavaMail/contents.html</li>
 * <li> http://java.sun.com/products/javamail/javadocs/com/sun/mail/imap/package-summary.html</li>
 * <li> http://java.sun.com/products/javamail/downloads/index.html</li>
 * </ul>
 * Also define a properties file with the following (adjust it to your configuration):
 * # As defined by the Javadoc
 * <ul>
 * <li> mail.user=name.lastname@gmail.com</li>
 * <li> mail.password=zzz</li>
 * <li> mail.store.host=pop.imap.gmail.com</li>
 * <li> mail.store.protocol=imap</li>
 * <li> mail.imap.port=993</li>
 * <li> mail.imap.socketFactory.port=993</li>
 * <li> mail.imap.socketFactory.class=javax.net.ssl.SSLSocketFactory</li>
 * </ul>
 * License: GPL
 * http://kodegeek.com
 * @author Jose Vicente Nunez Zuleta
 * @version 12/28/2008
 */
public final class ImapBulkEraser {
 
	/**
	 * Command line processing
	 * @param args [0] Location of the properties configuration file, If not provided then will use system defaults (defined with -D)
	 * @throws Exception
	 * @since 0.1
	 */
	public static void main(String [] args) throws Exception {
 
		Logger logger = Logger.getLogger(ImapBulkEraser.class.getName());
 
		Properties props = System.getProperties();
		if (args.length == 1) {
			props.load(new FileInputStream(args[0]));
		}
		Session session = Session.getInstance(props, null);
		session.setDebug(Boolean.parseBoolean(props.getProperty("debug")));
		Store store = session.getStore(props.getProperty("mail.store.protocol"));
		logger.info(String.format("Connecting to: %s@%s:%s", props.getProperty("mail.user"), props.getProperty("mail.store.host"), props.getProperty("mail.imap.port")));
		store.connect(props.getProperty("mail.store.host"), props.getProperty("mail.user"), props.getProperty("mail.password"));
		Folder folder = store.getDefaultFolder();
		logger.info("Got default folder. Erasing emails from ALL the folders");
		Folder [] folders = folder.list();
		long messgCnt = 0;
		for(Folder currFolder: folders) {
 
			try {
 
				if ((currFolder.getType() & Folder.HOLDS_MESSAGES) == 0) {
					continue; // Skip this folder type
				}
				logger.info(String.format("Opening folder: %s, num messages; %d", currFolder.getFullName(), currFolder.getMessageCount()));
				currFolder.open(Folder.READ_WRITE);
				Message [] messages = currFolder.getMessages();
 
				// Mark all the messages for delete
				for (Message message: messages) {
					try {
						message.setFlag(Flag.DELETED, true);
						MimeMessage currMessage = (MimeMessage) message;
						logger.info(String.format("Set delete flag for mail subject: '%s', folder: '%s'", currMessage.getSubject(), currMessage.getFolder().getFullName()));
						messages = currFolder.expunge(); // Confirm delete for all the messages on the current folder
						messgCnt += messages.length;
					}  catch (MessagingException messgExp) {
						logger.log(Level.WARNING, "There was a problem erasing the message, ignoring", messgExp);
					}
				}
 
				logger.info(String.format("Messages erased on folder %s: %d", currFolder.getFullName(), messages.length));
				currFolder.close(true);
 
			} catch (MessagingException messgExp) {
				logger.log(Level.WARNING, "There was a problem, ignoring", messgExp);
			}
 
		}
		logger.info(String.format("Total number of erased messsages: %d", messgCnt));
		store.close();
	}
 
}

Correr el código es trivial, asegurese de tener el JAR de Javamail en el $CLASSPATH y haga algo como esto:


java com.kodegeek.blog.mail.ImapBulkEraser -Dmail.user=name.lastname@gmail.com -Dmail.password=XXXX -Dmail.store.host=imap.gmail.com -Dmail.store.protocol=imap -Dmail.store.folder=INBOX -Dmail.imap.port=993 -Dmail.imap.socketFactory.port=993 -Dmail.imap.socketFactory.class=javax.net.ssl.SSLSocketFactory

El programa no es perfecto, ya que de vez en cuando me conseguí con la siguiente error:


NFO: Set delete flag for mail subject: 'Deploying webapps in embedded environment', folder: 'tomcat-user'
Dec 28, 2008 5:40:18 PM com.kodegeek.blog.mail.ImapBulkEraser main
WARNING: There was a problem erasing the message, ignoring
javax.mail.MessagingException: Failed to load IMAP envelope
at com.sun.mail.imap.IMAPMessage.loadEnvelope(IMAPMessage.java:1069)
at com.sun.mail.imap.IMAPMessage.getSubject(IMAPMessage.java:256)
at com.kodegeek.blog.mail.ImapBulkEraser.main(ImapBulkEraser.java:83)
Dec 28, 2008 5:40:18 PM com.kodegeek.blog.mail.ImapBulkEraser main

Sin embargo esos no son todos los correos :)

Como siempre el código fuente de este programa es GPL y se puede bajar desde CVS.

java , , , ,