Bom pessoal, precisei fazer uma pequena aplicação para receber e-mails e anexos no caso XMLs, só que vi somente artigos e tutoriais que apenas ensinavam como enviar o e-mail, o site do JavaMail, também não está tão legal, algumas coisas como salvar os anexos em pastas não estava tão bom, então resolvi pegar o código que fiz em casa e hoje está adaptado para rodar aqui no trabalho e vou postá-lo:
Ajuda no GUJ que obtive enquanto fazia: http://www.guj.com.br/posts/list/15/142839.java#771656Download do código no github aqui.
A solução, ficou assim:
Classe de Constantes:
public class Constantes { public static final String PASTA_XML = pasta onde o XML será salvo em seu computador;
public static final String IMAP = "imap";
public static final String HOST = Seu host;
public static final int PORTA = Sua porta;
public static final String ARQUIVO_MSG = Arquivo de mensagens do seu e-mail;
public static final String LOGIN = Seu login;
public static final String SENHA = Sua senha;
public static final String PASTA_PRINCIPAL = "Inbox";
public static final String PASTA_BACKUP = pasta caso você copie os e-mails da principal como fiz;
}
Classe ReadEmails
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import javax.mail.AuthenticationFailedException;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.FolderClosedException;
import javax.mail.FolderNotFoundException;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.ReadOnlyFolderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.StoreClosedException;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
/**
* @author Eduardo Bregaida
*
*/
public class ReadEmails {
private Store store = null;
private Folder folder = null;
private Message message = null;
private Message[] messages = null;
private Object msgObj = null;
private String sender = null;
@SuppressWarnings("unused")
private String subject = null;
private Multipart multipart = null;
private Part part = null;
private String contentType = null;
public ReadEmails() throws MessagingException {
processMail();
}
/**
* Processa o e-mail
*
*/
public void processMail() throws MessagingException {
try {
store = conexaoServidorEMail();
folder = getPastaCaixaEntrada(store);
messages = folder.getMessages();
for (int messageNumber = 0; messageNumber < messages.length; messageNumber++) {
message = messages[messageNumber];
msgObj = message.getContent();
// Determine o tipo de email
if (msgObj instanceof Multipart) {
subject = message.getSubject();
multipart = (Multipart) message.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
part = multipart.getBodyPart(i);
// pegando um tipo do conteúdo
contentType = part.getContentType();
String fileName2 = part.getFileName();
if(fileName2 != null) {
System.out.println(messageNumber + " " + fileName2 + " | " + message.getSubject());
}
fileName2 = null;
// Tela do conteúdo
if (contentType.startsWith("text/plain")) {
} else {
String fileName = part.getFileName();
@SuppressWarnings("unused")
Message[] mensagensXML = separaMensagensXML(i, fileName);
}
}
} else {
sender = ((InternetAddress) message.getFrom()[0]).getPersonal();
if (sender == null) {
sender = ((InternetAddress) message.getFrom()[0]).getAddress();
}
// Get the subject information
subject = message.getSubject();
}
}
// Fecha a pasta
folder.close(true);
// Histório de mensagens
store.close();
System.out.println("Terminado");
} catch (AuthenticationFailedException e) {
store.close();
e.printStackTrace();
} catch (FolderClosedException e) {
store.close();
e.printStackTrace();
} catch (FolderNotFoundException e) {
store.close();
e.printStackTrace();
} catch (NoSuchProviderException e) {
store.close();
e.printStackTrace();
} catch (ReadOnlyFolderException e) {
store.close();
e.printStackTrace();
} catch (StoreClosedException e) {
store.close();
e.printStackTrace();
} catch (Exception e) {
store.close();
e.printStackTrace();
}
}
/**
* @param i
* @param fileName
* @return
* @throws MessagingException
* @throws IOException
*/
private Message[] separaMensagensXML(int i, String fileName) throws MessagingException, IOException {
Message[] mensagensXML = folder.getMessages();;
if (fileName != null) {
int tamanhoString = fileName.length() - 3;
for (int a = 0; a < messages.length; a++) {
if (fileName.substring(tamanhoString).equals("xml")) {
mensagensXML[a] = message;
}
}
}
// Recebendo o nome do arquivo
@SuppressWarnings("unused")
String fileName2 = validarXML(part, store, folder, mensagensXML, i);
return mensagensXML;
}
/**
* @param messages
* @param i
* @throws MessagingException
*/
private void excluirMensagemInbox(Message[] messages, int i) throws MessagingException {
@SuppressWarnings("unused")
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
messages[i].setFlag(Flags.Flag.DELETED, true);
}
/**
* Envia os arquivos da pasta princiál para a pasta reserva
*
* @param store
* @param folder
* @param messages
* @throws MessagingException
*/
private boolean enviaArquivoPastaAuxiliar(Store store, Folder folder, Message[] messages, int i) throws MessagingException {
return false;
Folder folderAux;
folderAux = getPastaAuxiliar(store);
folder.copyMessages(messages, folderAux);
folderAux.close(true);
excluirMensagemInbox(messages, i);
}
/**
* Recebe o anexo e valida se é um XML, se sim ele salva o arquivo em uma
* pasta
*
* @param part
* @return
* @throws MessagingException
* @throws IOException
*/
private String validarXML(Part part, Store store, Folder folder, Message[] messages, int i) throws MessagingException, IOException {
String fileName = part.getFileName();
if (fileName != null) {
int tamanhoString = fileName.length() - 3;
if (!fileName.substring(tamanhoString).equals("xml")) {
return fileName;
} else {
String disposition = part.getDisposition();
if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT) || (disposition.equals(Part.INLINE))))) {
salvarArquivo(part);
enviaArquivoPastaAuxiliar(store, folder, messages, i);
}
}
}
return fileName;
}
/**
* Salva o arquivo em uma pasta
*
* @param part
* @throws MessagingException
* @throws IOException
*/
private void salvarArquivo(Part part) throws IOException, MessagingException {
FileOutputStream fileOutputStream = new FileOutputStream(Constantes.PASTA_XML + part.getFileName());
Object obj = part.getContent();
if (obj instanceof InputStream) {
InputStream is = (InputStream) obj;
int ch = -1;
while ((ch = is.read()) != -1) {
fileOutputStream.write(ch);
}
}
}
/**
* Acessa a Caixa de Entrada (Inbox)
*
* @param store
* @return
* @throws MessagingException
*/
private Folder getPastaCaixaEntrada(Store store) throws MessagingException {
Folder folder;
folder = store.getFolder(Constantes.PASTA_PRINCIPAL);
folder.open(Folder.READ_WRITE);
return folder;
}
/**
* Acessa a Pasta Auxiliar
*
* @param store
* @return
* @throws MessagingException
*/
private Folder getPastaAuxiliar(Store store) throws MessagingException {
Folder folder;
folder = store.getFolder(Constantes.PASTA_BACKUP);
folder.open(Folder.READ_WRITE);
return folder;
}
/**
* Autenticação e conexão com o Servidor de e-mail
*
* @return
* @throws NoSuchProviderException
* @throws MessagingException
*/
private Store conexaoServidorEMail() throws NoSuchProviderException, MessagingException {
Session session;
Store store;
Properties prop = new Properties();
session = Session.getInstance(prop);
URLName url = new URLName(Constantes.IMAP, Constantes.HOST, Constantes.PORTA, Constantes.ARQUIVO_MSG, Constantes.LOGIN, Constantes.SENHA);
store = session.getStore(url);
store.connect();
return store;
}
}
Classe Principal (Main):
import javax.mail.MessagingException;
/**
* @author Eduardo Bregaida
*
*/
public class PrincipalNfe {
public static void main(String[] args) {
@SuppressWarnings("unused")
ReadEmails readMail =null;
try {
readMail = new ReadEmails();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
import javax.mail.MessagingException;
/**
* @author Eduardo Bregaida
*
*/
public class PrincipalNfe {
public static void main(String[] args) {
@SuppressWarnings("unused")
ReadEmails readMail =null;
try {
readMail = new ReadEmails();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
Manifest:
Manifest-Version: 1.1
Main-Class: PrincipalNfe
Class-Path: lib-dep/activation.jar
lib-dep/dsn.jar
lib-dep/imap.jar
lib-dep/mail.jar
lib-dep/mailapi.jar
lib-dep/pop3.jar
lib-dep/smtp.jar
47 comentários:
Parabéns pela equipe do Java Anywhere, e principalmente ao eduardo.
Recebi ajuda do amigo, e automatizei a rotina de recebimento de DANFE (xml) com está função.
Muito Obrigado!
Obrigado pelo comentário Jeferson, fico feliz por ter ajudado, estamos aqui para passar sempre o nosso conhecimento para quem precisar.
Abraços
Parabens pelo codigo,porem estou com dificuldade para realizar a conexao..
Edlaine, obrigado, disponibilizei o fonte do exemplo dentro do meu GithHub, fique a vontade para baixar e tentar odificá-lo para seu projeto.
Muito bommm...Obrigadoo
Entao Eduardo estou com problema na pasta de backup no caso poderia ser qualquer pasta que eu queria fazer uma copia do arquvo "uma pasta que eu tenha no meu email"?
A pasta de backup é a pasta que você irá copiar os emails que serão excluídos da inbox, pode ser qualquer nome, basta criar uma pasta no seu email =)
Eduardo estou com um problema coloco o nome da pasta de backup porem nao esta dando certo, por acaso tem uma maneira diferente para colocar o nome?.Tenho que colocar o caminho?p
Pode me explicar?
Olá Edlaine, a pasta Backup ela deve ficar no nível da pasta Inbox, ela serve para quando o email é lido, ele vá para essa pasta e a mensagem original da inbox seja excluída.
Espero ter ajudado.
Eduardo,
Muito obrigado por compartilhar seu conhecimento! Você está ajudando muito a comunidade
Abraços
Felipe
Obrigado Felipe, fico feliz em ter ajudado.
Eduardo muito legal esse projeto, mas como ficaria se fosse usado o POP3 ao invés do IMAP, funciona tb?
Obrigado.
Tentei com uma conta do Gmail, mesmo ativando o IMAP ele não funcionou, chega a conectar mas não lê a caixa e trava.
Helcio, tudo bem? eu não cheguei a fazer conectando ao POP3, no Gmail você não é o primeiro que reclama desse problema, esse projeto eu fiz conectando num Lotus Notes, mas você pegou o código aqui do blog ou do GitHub? Lá está mais atualizado.
No post do GUJ o alexandrenilton fez acessando o GMail utilizando a solução que havia postado, dê uma olhadinha o link está no começo do tópico.
Bom dia Eduardo obrigado pela resposta. Eu realmenet preciso que seja IMAP como vc fez. Minha conta no gmail está ativada essa opção. Olhando o post do alexandrenilton fiz algumas modificações mas não obtive exito.
eu alterei as contantes dessa forma:
public static final String PASTA_XML = "C:/pasta/aplicacao/aqui_ser‡_salvo/";
public static final String IMAP = "imap";
public static final String HOST = "imap.gmail.com";
public static final int PORTA = 993;
public static final String ARQUIVO_MSG = "Inbox";
public static final String LOGIN = "user@gmail.com";
public static final String SENHA = "senha";
public static final String PASTA_PRINCIPAL = "Inbox";
public static final String PASTA_BACKUP = "backup";
Só que no monitor e no log fica aguardando :
INFO 15.08.2012 11:34:20 main br.com.email.dados.main.PrincipalNfe - #################### INICIANDO O PROCESSAMENTO DOS E-MAILS ##################
INFO 15.08.2012 11:34:20 main br.com.email.dados.email.ManipularEmail - Conectando ao servidor de e-mail
Pelo que entendi ele não está conectando, faz o seguinte, envia o fonte que vou plugar com meu gmail e debugar pra ver o que está acontecendo. eduardo.bregaida@gmail.com
[]ss
Opa, obrigado Eduardo. Então eu só mudei as constantes conforme a mensagem acima. O restante está igual ao seu projeto eu baixei o zip do GitHub. Se conseguir alguma luz vai me ajudar muito.
Ok, a noite vou olhar, qualquer novidade te aviso por aqui.
Helcio, demorou mas consegui, tenta assim:
//Gmail
public static final String PASTA_XML = "c:/SuaPasta";
public static final String IMAP = "imaps";
public static final String HOST = "imap.gmail.com";
public static final int PORTA = 993;
public static final String ARQUIVO_MSG = "Inbox";
public static final String LOGIN = "seuEmail@gmail.com";
public static final String SENHA = "suaSenha";
public static final String PASTA_PRINCIPAL = "Inbox";
public static final String PASTA_BACKUP = "backup";
Boa Eduardo aqui funcionou também, basicamente era o public static final String IMAP = "imaps"; eu havia colocado imap sem o 's'. Obrigado pela ajuda e parabéns pela iniciativa.
Eu tbm não sabia, testei outras formas e li alguns artigos para descobrir isso, mas o bom é que funcionou, boa sorte aí no seu projeto.
[]s
Eduardo,
Estou usando um código semelhante e estou tento problemas para receber arquivos de NFE em anexo enviados pelo SAP. Aparementente o SAP GRC não envia multipart corretamente, ou seja, não tem aquela separação de boundary na mensagem, com isso o javax.mail não identifica como anexo. Já teve problema semelhante a este? Sabe como fazer o programa entender que o que vem depois dos cabeçalhos é um anexo?
parabéns Eduardo modulo show de bola quero ver se eu consigo ajustar um layout para o modulo e fazer com que ele envie via ftp os arquivos da nota
Ernesto, infelizmente nunca tive esse problema, até mesmo porque na empresa que usava não havia SAP.
Divonei, blz, coloquei aqui depois as duvidas e resoluções que você achou.
[]sss
Boa noite Eduardo nao consigo rodar fala pra consultar este site
See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Galera tentei fazer a conexão mas obtive o seguinte erro:
#################### INICIANDO O PROCESSAMENTO DOS E-MAILS ##################
#################### FIM DO PROCESSAMENTO DOS E-MAILS ##################
javax.mail.MessagingException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:571)
at javax.mail.Service.connect(Service.java:288)
at javax.mail.Service.connect(Service.java:169)
at javax.mail.Service.connect(Service.java:118)
at br.com.email.dados.email.ManipularEmail.conectar(ManipularEmail.java:47)
at br.com.email.dados.acao.ReadEmails.(ReadEmails.java:51)
at br.com.email.dados.main.PrincipalNfe.main(PrincipalNfe.java:24)
Entendi o erro mas não entendi o pq? Como gero esse certificado?
Qual email vc está tentando conectar? Gmail?
Bom dia Eduardo,
Primeiramente parabéns pelo post, muito bacana.
Estou iniciando um projeto, também para gerenciamento de arquivos XML (no meu caso, arquivos de nf-e) e estava com dúvida sobre esta pasta auxiliar, esta pasta fica no webmail?
Obrigado mais uma vez por compartilhar.
Att.
João Paulo
Mal a demora JP, pasta de Backup sim, dentro do email, pasta XML é a que será salva no seu PC.
Essa aplicação é exatamente para a NFE =)
Olá, excelente post, me ajudou muito... mas só consegui conectar no gmail, tentei yahoo e ig e não tive sucesso. Sabe me dizer o que muda?
Olá Eduardo.
Dias atrás pesquisei muito na web, pois precisava bem isto o que você fez. Ficou excepcional. Porém, faz pouco tempo que estou aprendendo Java. Seu sistema rodou 100%. Mas gostaria de saber se posso imprimir os resultados num JTextArea por exemplo. Pois ele imprime no depurador. No caso eu queria que fosse mostrando num JTextArea. Saberia me dar algum exemplo?
Aquele abraço e parabéns pela postagem. Excelente
Sanches, eu não tentei por esses outros tipos de email mas com certeza dá, basta configurar o POP3 ou IMAP e outros parâmetros dos mesmos.
Carlos vamos lá:
Você quer imprimir os System.out? Dá sim, você pode criar algo como:
String imprime = "Movendo e-mail para pasta backup!";
JTextArea meuTextArea = new JTextArea();
meuTextArea.setText(imprime);
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JTextArea.html
Olá Eduardo.
Seu post me ajudou muito, só não consegui fazer um filtro pra pegar os e-mails que vem com determinado assunto. (Estou usando para fazer uma integração da página de contatos do cliente para o CRM). Alguma idéia de como posso fazer isso?
opa tentou com o getSubject criar um método para validar o assunto que tá chegando?
geronimo.apache.org/maven/specs/geronimo-javamail_1.4_spec/1.6/apidocs/javax/mail/Message.html
Boa Tarde,
Estou tentando salvar arquivos .txt é aparece o seguinte erro:
java.io.FileNotFoundException: D:\Teste Sistema\=?UTF-8?B?U0lQX1NQT0xPRy50eHQ=?= (The filename, directory name, or volume label syntax is incorrect)
Alguém pode me ajudar?
Att,
Então colocar caminho posicional é complicado, pois muda de ambiente para ambiente, ele pode não pegar no contexto, tente mudar para um caminho relativo:
http://respostas.guj.com.br/100-como-pegar-o-caminho-relativo-de-um-arquivo-e-transformar-em-absoluto
[]ssss
Oi Juliana, tudo bem?
Então eu criei a classe primeiro pra não espalhar um monte de constante na classe de ReadEmails, apenas por estética e limpeza, toda aquela parte de configuração fica chumbada num lugar separado para qualquer constante do sistema, em termos práticos não muda nada, apenas diminui um pouco a sujeira na classe mais importante :) só estética mesmo.
Oi Eduardo.. Primeiramente, obrigada pelo código! Ajudou Muito! ^.^
Os arquivos xml não estão sendo enviados para a pasta.. :c Você tem alguma ideia do que pode estar acontecendo?
Muito obrigada pela atenção e pela resposta anterior, Eduardo!
Precisando só chamar
Então..só mais uma coisa.. o código funcionou mas os arquivos não estão aparecendo na pasta T.T vc tem alguma ideia do por quê? A validação tá funcionando..mas parece que a parte de salvar não.. Eu mandei salvar em uma pasta dentro do projeto
Está gerando alguma Exception?
Vc tem algum contato Juliana?
Parabens Eduardo
Obrigado pelo comentário, fico feliz em saber que um artigo escrito quase 9 anos atrás ainda está ajudando :)
Postar um comentário