Baixar anexos do email com JavaMail - [RESOLVIDO]

51 respostas
T

Boa tarde pessoal,

Estou fazendo uma aplicação na qual eu tenho que baixar os e-mails de um certo e-mail e junto com eles
toda as informações.
De:
Assunto:
Conteúdo:
Anexos: (Onde está meu problema).

minha aplicação tirando a parte do anexo está pronta, não consigo achar em lugar nenhum um, um material completo de
como poderei baixar os anexos do meu e-mail. O pessoal começa a postar e quando consegue resolver o problema não posta a solução. =/

Segue meu código:

package testeEmailReceive;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;

import software.mail.EmailAccount;

public class InboxReader {

	public static void main(String args[]) {

		Properties props = System.getProperties();
		props.setProperty("mail.store.protocol", "imaps");


		try {

			Session session = Session.getDefaultInstance(props, null);
			Store store = session.getStore("imaps");

			store.connect("imap.gmail.com", email, password);
			System.out.println(store);

			Folder inbox = store.getFolder("Inbox");
			inbox.open(Folder.READ_ONLY);
			Message messages[] = inbox.getMessages();
			for (Message message : messages) {
				printMessage(message);
			}

		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (MessagingException e) {
			e.printStackTrace();
			System.exit(2);
		}

	}

	/**
	 * "printMessage()" method to print a message.
	 */
	public static void printMessage(Message message) {
		try {
			// Get the header information
			String from = ((InternetAddress) message.getFrom()[0])
					.getPersonal();
			if (from == null)
				from = ((InternetAddress) message.getFrom()[0]).getAddress();

			System.out.println("FROM: " + from);
			String subject = message.getSubject();
			System.out.println("SUBJECT: " + subject);

			// -- Get the message part (i.e. the message itself) --
			Part messagePart = message;
			Object content = messagePart.getContent();

			// -- or its first body part if it is a multipart message --
			if (content instanceof Multipart) {
				messagePart = ((Multipart) content).getBodyPart(0);
				System.out.println("CONTEÚDO: "+messagePart.getContent().toString());
			}

			// -- Get the content type --
			String contentType = messagePart.getContentType();

			// -- If the content is plain text, we can print it --
			System.out.println("CONTENT:" + contentType);
			if (contentType.startsWith("text/plain") || contentType.startsWith("text/html")) {
				InputStream is = messagePart.getInputStream();

				BufferedReader reader = new BufferedReader(
						new InputStreamReader(is));

				String thisLine = reader.readLine();
				while (thisLine != null) {
					thisLine = reader.readLine();
				}
			}
			
			//baixar anexo:
			
			
			
			

			System.out.println("-----------------------------");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}

Desde já agradeço!

51 Respostas

A

Bom amigo, não sei se esta seria a melhor abordagem mas acredito que isto resolva seu problema.
coloca este trecho no lugar no //baixar anexo

else {
   byte[] buf = new byte[4096];

//Aqui você define o caminho que salvará o arquivo.
   String caminhoBase = System.getProperty("user.dir") + "/";
   Multipart multi = (Multipart) content;
  
 for (int i = 0; i < multi.getCount(); i++) {
     String nomeDoArquivo = multi.getBodyPart(i).getFileName();
     if (nomeDoArquivo != null) {
      InputStream is = multi.getBodyPart(i).getInputStream();
      FileOutputStream fos = new FileOutputStream(caminhoBase + nomeDoArquivo);
      int bytesRead;
      while ((bytesRead = is.read(buf)) != -1) {
         fos.write(buf, 0, bytesRead);
      }
     fos.close();
    }
  }
}

Espero ter ajudado. :smiley:
Abraço

T

Valeu Brother , funcionou…

mas você poderia me explicar o que quer dizer esse código?
Qual objeto é meu arquivo, ex: no caso de eu salvar esse arquivo em uma tabela do banco (do mesmo tipo claro)
qual é o Objeto que eu devo manipular…
eu não entendi o código… =/

A

Cara, de forma bem resumida, este código acha todos os arquivos que contenham o contentType diferente de text/plain e text/html e salva os mesmos em disco.
O objeto is do tipo InputStream é quem tem seu anexo, o que ta sendo feito no while ai é simplesmente ler os bytes deste anexo e salvar em um diretório na máquina.
O que vc pode fazer é ao invés salvar os bytes em disco direto, mandá-los para um objeto. Vale reforçar, como disse na mensagem anterior, não sei se esta é a melhor abordagem, fiz esse código a muito tempo atrás a título de aprendizado.

T

Perfeito cara,
Muito obrigado mesmo, serviu para o que eu queria e consegui entender completamente o código agora.

valeu mesmo...

Código Finalizado pra quem ficou com duvidas.

package testeEmailReceive;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;

import software.mail.EmailAccount;

public class InboxReader {

	public static void main(String args[]) {

		Properties props = System.getProperties();
		props.setProperty(&quot;mail.store.protocol&quot;, &quot;imaps&quot;);

		try {

			Session session = Session.getDefaultInstance(props, null);
			Store store = session.getStore(&quot;imaps&quot;);

			store.connect(&quot;imap.gmail.com&quot;, email ,
					password );
			System.out.println(store);

			Folder inbox = store.getFolder(&quot;Inbox&quot;);
			inbox.open(Folder.READ_ONLY);
			Message messages[] = inbox.getMessages();
			for (Message message : messages) {
				printMessage(message);
			}

		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (MessagingException e) {
			e.printStackTrace();
			System.exit(2);
		}

	}

	/**
	 * &quot;printMessage()&quot; method to print a message.
	 */
	public static void printMessage(Message message) {
		try {
			// Get the header information
			String from = ((InternetAddress) message.getFrom()[0])
					.getPersonal();
			if (from == null)
				from = ((InternetAddress) message.getFrom()[0]).getAddress();

			System.out.println(&quot;FROM: &quot; + from);
			String subject = message.getSubject();
			System.out.println(&quot;SUBJECT: &quot; + subject);

			// -- Get the message part (i.e. the message itself) --
			Part messagePart = message;
			Object content = messagePart.getContent();

			// -- or its first body part if it is a multipart message --
			if (content instanceof Multipart) {
				messagePart = ((Multipart) content).getBodyPart(0);
				System.out.println(&quot;CONTEÚDO: &quot;
						+ messagePart.getContent().toString());
			}

			// -- Get the content type --
			String contentType = messagePart.getContentType();

			// -- If the content is plain text, we can print it --
			System.out.println(&quot;CONTENT:&quot; + contentType);
			if (contentType.startsWith(&quot;text/plain&quot;)
					|| contentType.startsWith(&quot;text/html&quot;)) {
				InputStream is = messagePart.getInputStream();

				BufferedReader reader = new BufferedReader(
						new InputStreamReader(is));

				String thisLine = reader.readLine();
				while (thisLine != null) {
					thisLine = reader.readLine();
				}
			}

		else {
				byte[] buf = new byte[4096];

				// Aqui você define o caminho que salvará o arquivo.
				String caminhoBase = System.getProperty(&quot;user.dir&quot;) +&quot;\\src\\testeEmailReceive\\&quot;;
				Multipart multi = (Multipart) content;

				
				
				for (int i = 0; i &lt; multi.getCount(); i++) {
					
					String nomeDoArquivo = multi.getBodyPart(i).getFileName();
					
					if (nomeDoArquivo != null) {
						
                                                //imprimindo o caminho já com o nome do arquivo para ter certeza, e somente se tiver arquivos.
						System.out.println(caminhoBase+nomeDoArquivo);
						
						InputStream is = multi.getBodyPart(i).getInputStream();
						
						FileOutputStream fos = new FileOutputStream(caminhoBase	+ nomeDoArquivo);
						
						int bytesRead;
						while ((bytesRead = is.read(buf)) != -1) {
							fos.write(buf, 0, bytesRead);
						}
						
						fos.close();
					}
				}
			}

			System.out.println(&quot;-----------------------------&quot;);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}
A

Olá amigos, achei muito interessante o assunto de poder salvar o email e muito mais interessante ainda os anexos dele. Queria saber se isso se enquadraria e/ou se tem como fazer isso em uma aplicação web? Se sim, o código seria esse? Outra coisinha também que não entendi. Esse código foi feito para um email específico ou qualquer email funcionária? Desde já meu muito obrigado!

A

Com algumas alterações no código é possível sim fazer funcionar para outros e-mails. Cada provedor de e-mail tem suas configurações específicas de stmp, pop, imap, neste caso está sendo usado GMAIL.
No caso de utilizar em aplicação web minha resposta é a mesma, é possível desde que haja alteração no código.

A

Outra pergunta que esqueci e acho muito importante. Você consegue baixar um email específico ou só consegue trazer todos os emails? Outra… Conseguiria baixar um email da lixeira por exemplo? Achei muito interessante a ideia de manipular o email, e penso em acrescentar isso no workflow da minha empresa, na qual acho muito interessante.

T

pelo o que compreendi utilizando a API JavaMail, nós podemos especificar atraves desse código:

Folder inbox = store.getFolder("Inbox");
	inbox.open(Folder.READ_ONLY);

onde queremos puxar…
mas não sei se é possivel pegar da lixeira, teria que dar uma olhada na especificação da API…

http://javamail.kenai.com/nonav/javadocs/index.html

:wink:

A

Beleza, muito obrigado, vou baixar a lib aqui e testar no gmail mesmo, se eu conseguir fazer funcionar no gmail vou testar com o email da empresa… Se eu obter algum resultado volto a dar notícias, e se eu tiver alguma dúvida também volto a dar notícias kkkk, Abraço, e obrigado novamente! :smiley:

T

demoro cara, posta ae qlqr coisa…

abraçoo!

A

augustovieira, de acordo com a API também é possível procurar e-mail específico de acordo com algum critério.

A

Se é mesmo possível buscar um email específico vai resolver 100% o que eu quero fazer! Show de bola!

A

Fiz o download porém estou perdido, vou ter que importar tudo que vem no zip pro meu projeto? achei que era só uma lib pra colocar no meu projeto.

T

é só pegar o jar do javamail e jogar no classpath…

o resto é arquvo pra ajudar vc…
demos e etc…

A

Esse é o problema, não estou encontrando esse jar nessa infinidade de pastas que veio junto. Sabe qual pasta está ou qual o nome dele? Se melhor cola ele aqui?

T

ta na primeira pasta brother…

o dentro da pasta que você baixou, ele chama MAIL.jar

:wink:

A

Infelizmente procurei nas pastas que fiz download e não tem nenhum jar. Única coisa que tem é um mail.sig

T

você baixou por aqui?

http://www.oracle.com/technetwork/java/javamail/index-138643.html

A

Esse foi o arquivo que baixei: javamail-1.4.5-src.zip. Foi exatamente ai que fiz o download, é esse não é?

A

Se tu puder me encaminhar por email então acho que seria mais fácil: [email removido]

T

Não você baixou o SRC… vc tem que baixar o .ZIP sem o SRC…

http://download.oracle.com/otn-pub/java/javamail/1.4.5/javamail1_4_5.zip

tenta ae…

A

Okk agora deu certo! Porém deu um errinho na hora que fui executar.

javax.mail.MessagingException: Connection refused: connect;
  nested exception is:
	java.net.ConnectException: Connection refused: connect
	at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:670)
	at javax.mail.Service.connect(Service.java:295)
	at javax.mail.Service.connect(Service.java:176)
	at testeEmailReceive.InboxReader.main(InboxReader.java:31)
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.connect0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
	at java.net.Socket.connect(Socket.java:579)
	at java.net.Socket.connect(Socket.java:528)
	at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:319)
	at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:233)
	at com.sun.mail.iap.Protocol.<init>(Protocol.java:113)
	at com.sun.mail.imap.protocol.IMAPProtocol.<init>(IMAPProtocol.java:111)
	at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:637)
	... 3 more

O que é alguém sabe?

T

você ta usando Gmail mesmo ??

trocou o email por seu email ? e password pela sua senha?

Abraço!

A

Exatamente o que eu ia falar, rs. Tá dando conexão negada.
Se for outro servidor de e-mail tem que fazer as configurações de imap dele

T

sim…

hehehe

A

Sim sim , alterei o email para [email removido] e a senha coloquei a senha do email, porém está dando isso! É erro de conexão negada? Pode ser erro de senha ou bloqueio de proxy?

T

você tem email no gmail ?

se sim , coloca ele e a senha dele pra você testar!

e ve se conecta, se conectar ai vc vai atraz de achar um imap para o outro que vc quer!

A

Sim sim, coloquei meu login e senha do gmail, antes de faze no email que quero estou testando no gmail mesmo. Porém como falei anteriormente aconteceu aquele erro. Estou tentando ver aqui, creio que é algo com proxy ou porta que tenho que liberar. Após eu conseguir fazer funcionar o negócio, vou achar o imap do email que quero e desenvolver em cima dele.

T

No meu chegou a dar esse erro,
mas era coisa de senha e usuario!

A

Verifiquei tudo aqui e meu login e senha está certo, tentei com o @gmail.com e tudo mas não deu. Continua dando o mesmo erro. Eu entro com a mesma senha pelo gmail.com e lá loga normal.

A

Bom para tirar qualquer dúvida criei um GMAIL de teste com login [email removido] e senha testeguj1234

public static void main(String args[]) {

		Properties props = System.getProperties();
		props.setProperty("mail.store.protocol", "imaps");

		try {

			Session session = Session.getDefaultInstance(props, null);
			Store store = session.getStore("imaps");

			store.connect("imap.gmail.com", "testeguj",
					"testeguj1234" );
			System.out.println(store);

			Folder inbox = store.getFolder("Inbox");
			inbox.open(Folder.READ_ONLY);
			Message messages[] = inbox.getMessages();
			for (Message message : messages) {
				printMessage(message);
			}

		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (MessagingException e) {
			e.printStackTrace();
			System.exit(2);
		}

	}

e mesmo assim continua o mesmo erro!

javax.mail.MessagingException: Connection refused: connect;
  nested exception is:
	java.net.ConnectException: Connection refused: connect
	at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:670)
	at javax.mail.Service.connect(Service.java:295)
	at javax.mail.Service.connect(Service.java:176)
	at testeEmailReceive.InboxReader.main(InboxReader.java:31)
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.connect0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
	at java.net.Socket.connect(Socket.java:579)
	at java.net.Socket.connect(Socket.java:528)
	at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:319)
	at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:233)
	at com.sun.mail.iap.Protocol.<init>(Protocol.java:113)
	at com.sun.mail.imap.protocol.IMAPProtocol.<init>(IMAPProtocol.java:111)
	at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:637)
	... 3 more

creio então que não seja erro de login e senha!

T

faltou o @gmail.com

hehehe

T

tem dois e-mails do google !!

CERTO ?

T

Assim amigo!

store.connect("imap.gmail.com", "[email removido]", "testeguj1234" );
A

Mesmo assim moço, acha que eu não iria ter tentado sem o @gmail.com? fiz como tu disse antes e o erro persiste. não estou entendendo o porque

T

cara,

Sei lá…
já olhei umas 5 vezes nossos codigos estão identicos…
aqui está funcionando… to sem ideias, mas to pesquisando aqui…

da uma pesquisada ai também …

A

Tu executa o código pelo Java Application?

A

Fiz a mesma coisa aqui e funcionou normalmente.

T

sim, java application!

dentro do java mesmo…

T

dentro do eclipse mesmo… rsrs

A

Pai do céu!!! O que você tem contra mim? kkkkk essa merda só não funciona aqui!!! Estou tentando descobrir o porque está dando esse erro mas não ta fácil não! Não achei que iria ser tão difícil fazer isso.

O

Se você acessa a Internet no browser através de um proxy, tem que configurar isto no seu código, ou pedir para habilitar a porta no firewall da sua empresa…

T

boa oyama…

é isso mesmo… todos os detalhes que tiver para acessar a web no browser vc terá que configurar no seu codigo, porque ele está
acessando a web também…
:wink:

A

Fiz de uma outra forma e deu certo, muito obrigado pela atenção.

A

a título de curiosidade, qual foi sua solução?

A

Utilizei um esquema que tinha feito a um tempo atrás na empresa de consultar conexão com base de email, mas o que tava faltando era fazer a segurança de dados, fiz um esquemas de ssl que grava em um arquivo .jks na minha maquina. Então ele conseguiu fazer a conexão certinha, e outra… consegui conectar no webmail da minha empresa, então matei 2 coelhos com 1 paulada só kkk muito obrigado!!

Obs: não posto o código por ser exclusivo da empresa. :smiley:

T

digo o mesmo aganhara…rsrsrs

qual foi sua solução!

A

Tino_ fico muito feliz de me tornar um JavaBaby trocando idéias contigo kkkkkkkkkkkkk

T

hahahahaa, digo o mesmo amigo…

F

Tentei verificar se a mensagem possui anexo da forma dita:

if (contentType.startsWith("text/plain")  || contentType.startsWith("text/html")) ...

Entretanto o contentType vem “multipart/mixed; boundary=”–=_NextPart_81e443b589cf731b6b3cfc6a1191d4f5"". Essa mensagem não possui anexo!

L

Primeiramente ótimo tópico.
Assim será que tem alguma forma de ler apenas os e-mails que ainda não foram lidos ? se tiver como ?
Obrigado.

Criado 18 de setembro de 2012
Ultima resposta 25 de abr. de 2015
Respostas 51
Participantes 6