Apanhando feio da API do Javamail para baixar anexos

7 respostas
L

Bom dia amigos, estou apanhando desde cedo para tentar baixar os anexos que estão em um e-mail que foram encaminhados do Outlook/Thunderbird para uma conta de e-mail que é gerenciada por um aplicativo meu. Este meu aplicativo fica “observando” uma determinada conta de e-mail e a cada X tempo, ele baixa os anexos dos novos e-mails. Estas mensagem que são encaminhadas possuem uma particularidade aonde o e-mail original é “empacotado” num arquivo com extensão eml, anexados ao e-mail e encaminhado para uma conta de e-mail qqr. Se você abrir este arquivo eml no bloco de notas, por exemplo, você irá perceber que os arquivos anexados ao email original agora fazem parte do conteudo do arquivo eml, porém estão codificados, por exemplo:

...

This is a multi-part message in MIME format.
This email requires a MIME compatible email reader.

----=_NextPart_000_d20090818t175506.47c1r898756
Content-Type: multipart/alternative;
	boundary="--=_NextPart_001_d20090818t175506.47c1r898756"

----=_NextPart_001_d20090818t175506.47c1r898756
Content-Type: text/plain;
	charset=us-ascii
Content-Transfer-Encoding: 7bit


----=_NextPart_001_d20090818t175506.47c1r898756--

----=_NextPart_000_d20090818t175506.47c1r898756
Content-Type: application/x-unknown;
 name="35090844016707000161550020000017360484256096.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="35090844016707000161550020000017360484256096.pdf"

JVBERi0xLjMNJeLjz9MNCjEgMCBvYmoNCjw8IA0KL0NyZWF0aW9uRGF0ZSAoRDoyMDA5MDgxODAw
MTI0MikNCi9UaXRsZSAoTm90YSBGaXNjYWwgRWxldHK2bmljYSAtIE6mIDAwMC4wMDEuNzM2IC0g
U9pyaWUgMikNCi9DcmVhdG9yIChVbmltYWtlIFNvZnR3YXJlcyAtIHd3dy51bmltYWtlLmNvbS5i
cikNCi9Qcm9kdWNlciAoVW5pREFORmUgdi4yIFBsdXMgLSB3d3cudW5pZGFuZmUuY29tLmJyKQ0K
L01vZERhdGUgKEQ6MjAwOTA4MTgxNzU1MDMpDQovU3ViamVjdCAoTkNIIEJSQVNJTCBMVERBLikN
Ci9BdXRob3IgKE5DSCBCcmFzaWwgLyBVbmlORmUgLSB3d3cudW5pbWFrZS5jb20uYnIvdW5pbmZl
KQ0KL0tleXdvcmRzIChORi1lLCBOb3RhIEZpc2NhbCBFbGV0crZuaWNhLCBEQU5GRSwgRG9jdW1l
bnRvIEF1eGlsaWFyIGRhIE5vdGEgRmlzY2FsIEVsZXRytm5pY2EsIFVuaU5GZSwgT3BlbiBTb3Vy
Y2UsIFVuaURBTkZlLCBGcmVlLCBQbHVzLCBTRUZBWiwgQnJhc2lsKQ0KPj4gDQplbmRvYmoNCjIg
MCBvYmoNCjw8IA0KL1R5cGUgL0NhdGFsb2cNCi9PdXRsaW5lcyA1IDAgUg0KL1BhZ2VzIDMgMCBS
DQo+PiANCmVuZG9iag0KNiAwIG9iag0KPDwgL0ZpbHRlciAvRmwgL0xlbmd0aCAxMDMgPj4NCnN0
cmVhbQ0KeJwr5OUystSzNDVSMDQy0zMxN1IwNTbSszQxUdC11APyilJ5ucIV8ni5nEJ4ufTdDBUs
FELSeLkMFECwKJ2XyxDMMlSAmWJoATYlJFchWkNXYURDzViFEC9eLldgyAXycgEAhII6yWVuZHN0
cmVhbQ0KZW5kb2JqDQo3IDAgb2JqDQo8PCAvRmlsdGVyIC9GbCAvTGVuZ3RoIDY5ID4+DQpzdHJl
YW0NCnici45VMFBI4eUyUADBIHcgS8/c0EyhnJfLyFLP0tRIwdDQUM/EyETB1NhIz9LEREHXxFDP
0txMoSiVl6uYlwsAk9YMSWVuZHN0cmVhbQ0KZW5kb2JqDQo4IDAgb2JqDQo8PCAvRmlsdGVyIC9G

....

Eu fiz o seguinte tratamento para tentar pegar este conteúdo codificado:

for (int messageNumber = 0; messageNumber < messages.length; messageNumber++) {
	Message message = messages[messageNumber];
	
	Object msgObj = message.getContent();
	if (msgObj instanceof Multipart) {
		Multipart multipart = (Multipart) message.getContent();
		
		for (int i = 0; i < multipart.getCount(); i++) {
			Part part = multipart.getBodyPart(i);
			
			// ...
			//Algumas checagens, inclusive uma para verificar se o anexo é do tipo EML.  entrará no bloco abaixo se for deste tipo de arquivo
			
			Message msg = (Message) part.getContent();
			Object msgContent = msg.getContent();

			if (msgContent instanceof Multipart) {
				MimeMultipart mmp = (MimeMultipart) msg.getContent();
				
				for (int i = 0; i < mmp.getCount(); i++) {
					MimeBodyPart mbp = (MimeBodyPart) mmp.getBodyPart(i);
					
					FileOutputStream fileOutputStream = new FileOutputStream(mbp.getFileName());
					InputStream stream = mbp.getInputStream();
					int ch = -1;
					while ((ch = stream.read()) != -1) {
						fileOutputStream.write(ch);
					}
				}
			}
		}
	}
}

Quando o aplicativo passa pela linha InputStream stream = mbp.getInputStream(); dá a seguinte exception:

java.io.IOException: No content
	at javax.mail.internet.MimePartDataSource.getInputStream(MimePartDataSource.java:109)
	at javax.activation.DataHandler.getInputStream(DataHandler.java:238)
	at javax.mail.internet.MimeBodyPart.getInputStream(MimeBodyPart.java:558)
	at action.ReadEmailAction.trataArquivoEML(ReadEmailAction.java:315)
	at action.ReadEmailAction.processMail(ReadEmailAction.java:101)
	at action.ProcessaEmailAction.run(ProcessaEmailAction.java:133)
	at thread.ProcessaEmailThread.run(ProcessaEmailThread.java:32)

Já virei a internet e não consigo encontrar a solução… Acredito que seja algo simples e que eu esteja comendo bola.

Aonde será que eu estou errando?

Obrigado!

7 Respostas

C

Bom dia libajunior,

Este seu aplicativo é um servidor proxy de e-mail?

Como esta conta está configurada no cliente de e-mail (Outlook/Thunderbird)?

Utiliza conexão SSL?

É um servidor IMAP ou POP?

Abraço!

L

Bom dia…

A conta que estou monitorando está no gmail (google apps) e estou utilizando imap. Esta conta está no próprio gmail (webmail) porém existem e-mail que foram encaminhado para esta conta das duas ferramentas (Outlook e Thunderbird). Os parâmetros (properties) que utilizo na conexão com esta conta, além dos normais, são:

mail.imap.socketFactory.class=javax.net.ssl.SSLSocketFactory
mail.imap.partialfetch=false
C

Até onde sei, para você conseguir “descriptografar” a mensagem enviada pelo Outlook/Thunderbird você precisará da chave pública utilizada para a conexão SSL.

No meu TCC, desenvolvi um servidor proxy de e-mail com filtragem dos e-mails recebidos. Este filtro é configurado na própria aplicação antes de abrir o servidor.

Pelo que vejo, a única diferença entre a minha aplicação e a sua, é que meu servidor “ouvia” uma porta de recebimento de e-mail (IMAP) e a sua uma porta de envio (SMTP) de e-mail.

Se é realmente isto, faça o teste com um servidor IMAP onde não utilize conexão SSL, desta forma os dados trafegarão limpos (sem criptografia). Talvez você consiga montar corretamente o anexo.

Abraço!

L

Obrigado pela ajuda… Acho que eu não fui claro na primeira mensagem. Nãio estou utilizando SMTP e sim IMAP. Minha aplicação apenas lê o conteúdo de um e-mail e faz o download do anexo. Ela funciona normalmente, não vem nenhum conteúdo criptografado. A única coisa que ocorre é quando existe um email que foi encaminhado pelo Outlook/Thunderbird, pois nestes casos o email original é anexado ao email encaminhado com uma extensão eml.

O arquivo eml, não é um arquivo compactado como um ZIP. Ele possui em seu conteudo as partes do e-mail original. Então aqueles códigos parecem ser códigos cifrados,ao meu entender (posso estar errado), é o conteúdo do arquivo não cifrado e sim codificado. Posso estar enganado, mas não creio que utilizando uma chave publica vai resolver.

Como falei, posso estar enganado.

Este aplicativo que você desenvolveu… Qual o comportamento dele qdo chegava um email que foi encaminhado de outra conta?

C

Não entendi a pergunta "Qual o comportamento dele qdo chegava um email que foi encaminhado de outra conta?".

O meu aplicativo é um servidor proxy, então ele funciona com qualquer cliente de e-mail (Thunderbird/Outlook).

Basta o cliente de e-mail configurar a sua conta para conectar no meu servidor proxy e não diretamente no servidor de e-mail (imap.terra.com.br por exemplo). Então o cliente de e-mail se conecta no meu servidor proxy e o meu servidor proxy se conecta no servidor de e-mail (THUNDERBID <-> MEU SERVIDOR PROXY <-> SERVIDOR DE E-MAIL).

Qualquer dúvida poste aqui que esclareço.

Abraço!

L

Entendi… Tinha pensado que teu app era um cliente que lia e-mail…

C

Não não…

Apenas filtro os e-mails solicitados por um cliente de e-mail.

Abraço!

Criado 5 de julho de 2012
Ultima resposta 6 de jul. de 2012
Respostas 7
Participantes 2