JavaMail - Anexar arquivo pdf (como vetor de bytes)

Boa tarde pessoas!

Bom, fiz algumas pesquisas mas não obtive êxito ainda.

Eis o que acontece: tenho um bean que usa a API javaMail pra… enviar emails (d’oh!) vez ou outra com alguns arquivos anexos de relatórios gerados pelo jasper.

O que acontece é que gero um relatório em arquivo pdf e o jasper me retorna em um vetor de bytes que quero anexar no email.
Posso muito bem (e funciona) salvar esse arquivo em disco (transformando-o em pdf) e então anexa-lo,
Mas estou tentando pular esse passo, anexar direto o vetor de bytes como pdf pra evitar gargalos e outra simplicações.

O que acontece é que fazendo assim ele da um problema de Encode64 e não envia o email.
Pesquisei e encontrei uma biblioteca da Apache (commons-codec) que faz esse Encoding64 no vetor de bytes, retornando outro vetor de bytes convertido.

Assim o anexo foi criado e o email enviado corretamente, MASS, porém, entretanto, ao abrir o anexo recebo uma mensagem do sistema semelhante a: “a extensão do arquivo diz que ele é pdf, mas o conteúdo diz que é do tipo texto” e não abre =(
Aqui vai o código que gera o email:

public void enviarEmail() throws Exception {

        try {

            Session session = null;

            Context ctx = new InitialContext();
            Object obj = ctx.lookup("java:/Mail");
            session = (Session) obj;

            MimeMessage m = new MimeMessage(session);
            m.setFrom(new InternetAddress("censurado"));
            Address[] to = new InternetAddress[] {new InternetAddress("censurdo")};
            m.setRecipients(Message.RecipientType.TO, to);
            m.setSubject("[Teste] TITULO");
            m.setSentDate(new java.util.Date());
            m.setText("TESTANDO EMAIL");

            Multipart corpo = new MimeMultipart();

            InternetHeaders headers = new InternetHeaders();
            headers.addHeader("Content-Type", "application/pdf"); //diz o mime type, é isso que ele ta se confundindo depois de codificar pra base64

            byte[] encoded = Base64.encodeBase64(relatorio()); //codifica para base64 pra montar o email

            //essas tres proximas linhas é pra teste, ele salvou em disco e deu o msm bug de achar que eh arquivo texto, tudo culpa do base 64 =/
            OutputStream os = new FileOutputStream("/usr/local/jboss/teste1.pdf");
            os.write(encoded);
            os.close();

           MimeBodyPart partPhoto = new MimeBodyPart(headers,encoded);
            partPhoto.setDisposition(javax.mail.Part.ATTACHMENT);
            partPhoto.setFileName("anexo2.pdf");

            corpo.addBodyPart(partPhoto);

             m.setContent(corpo);
            
            Transport.send(m);

        } catch (Exception ex) {
            throw new Exception(ex.getMessage() + FONTE + "enviarEmail()");
        }

    }

E ai galera, alguma dica?!

Abraços!

ARRESORVIDO!

A quem possa interessar, a solução:

            MimeBodyPart partPhoto = new MimeBodyPart();
            partPhoto.setDataHandler(new DataHandler(new ByteArrayDataSource(relatorio(), "aplication/pdf")));
            partPhoto.setFileName("PDF.pdf");

Simples não?
Então, a classe ByteArrayDataSource é do pacote geronimo-javamail do apache Axiom.

Espero ao menos ter ajudado as pessoas que enfrentam e as que futuramente enfrentarão esse problema.

Abraços!

A propósito, essa classe ByteArrayDataSource está presente no último release do javaMail.
Mas o pacote activation não tem e se faz necessário baixa-lo.

Abraços.

Fala Tchello, conforme ja te perguntei por MP, onde eu seto informações de segurança como usuario e senha eo endereçodo smtp e porta!?
Abraços

Opa, e ai bokerao!

Então cara, no meu caso essas informações estão setadas na minha arvore JNDI do meu jboss (mais precisamente num arquivo mail-services.xml no diretorio de deploy) e as obtenho nesse trecho:

Context ctx = new InitialContext(); Object obj = ctx.lookup("java:/Mail"); session = (Session) obj;

MAASS você pode criar seu session sem usar isso com o seguinte codigo:

        MeuAutenticador auth = new MeuAutenticador(SEU USUARIO AUTENTICADOR, SENHA); //aqui deve ser uma classe sua que extenda javax.mail.Authenticator
        props.setProperty("mail.smtp.user", USUARIO DE AUTENTICA CAO SMTP);
        props.setProperty("mail.smtp.host", SEU SMTP);
        props.setProperty("mail.smtp.localhost", SEU HOST);
        props.setProperty("mail.smtp.auth", "true"); //se quer que seja autenticado
        props.setProperty("mail.user", SEU USER);
        Session sessao = Session.getInstance(props,auth);
        MimeMessage m = new MimeMessage(sessao);

Ai pronto, você obteve seu mimeMessage.
Agora se você estiver usando um servidor de aplicações a forma acima é muito mais fácil eheheh.
Espero tê-lo ajudado!

Abraços.

No momento to testando aqui no Tomcat localmente mesmo, vou tentar e kalker coisa encho o saco de novo.
Valeu, abraços!

Fala Tchello, montei agora legal usando a classe extendendo o Authenticator, ele roda sem problemas, não dá erro, na console mostra que gerou o PDF.pdf, mas nada, num chega email nenhum!

Vou postar o código, ve se tem algo errado por favor!

Classe Teste.java que contem todo aquele código postado por você inicialmente!

import java.util.Properties;

import javax.activation.DataHandler;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.InternetHeaders;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;

public class Teste {
	public void enviarEmail(byte[] bytes) throws Exception {
		String de = "rcabral@xxx.com.br";
		String para = "deusemar@xxx.com.br";
		String assunto = "Teste";
		String texto = "nononono";
        try {
            Properties props = new Properties();
            props.setProperty("mail.smtp.user", "user_do_email");
            props.setProperty("mail.smtp.host", "meu_smtp");
            props.setProperty("mail.smtp.auth", "true");
            Autenticacao auth = new Autenticacao("user_do_email","minha_senha_email");
            Session sessao = Session.getInstance(props,auth);
            MimeMessage m = new MimeMessage(sessao);
           
            m.setFrom(new InternetAddress(de));
            Address[] to = new InternetAddress[] {new InternetAddress(para)};
            m.setRecipients(Message.RecipientType.TO, to);
            m.setSubject(assunto);
            m.setSentDate(new java.util.Date());
            m.setText(texto);

            Multipart corpo = new MimeMultipart();
            InternetHeaders headers = new InternetHeaders();
            headers.addHeader("Content-Type", "application/pdf");
            MimeBodyPart partPhoto = new MimeBodyPart();
            partPhoto.setDataHandler(new DataHandler(new ByteArrayDataSource(bytes, "aplication/pdf")));
            partPhoto.setFileName("PDF.pdf");            

            corpo.addBodyPart(partPhoto);
            m.setContent(corpo);
            Transport.send(m);
        } catch (Exception ex) {
            throw new Exception(ex.getMessage());
        }
    }
}

Classe Autenticacao.java que contem a parte de autenticacao do SMTP:

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

public class Autenticacao extends Authenticator {
	private String username;  
	private String password;
	
	public Autenticacao(){}
	
	public Autenticacao(String usuario, String senha){
		this.username = usuario;
		this.password = senha;
	}
	
	public PasswordAuthentication getPasswordAuthentication() {
		return new PasswordAuthentication(username, password);
	}
}

Lógico que troquei os valores de alguns parametros, senão vcs iam acessar todas as porcarias do meu email… rs
Além disso na classe teste eu passo um array de bytes que é o relatório gerado pelo JasperReports!

Dá uma olhada por favor!

Abraços

Ixi cara, ta dificil… faz o seguinte, testa com essas linhas dessa forma, sem usar autenticação:

...
props.setProperty("mail.smtp.auth", "false");  
...
 Session sessao = Session.getInstance(props); 

Posta ae o resultado.

Abraços.

Passa normal, erro ZERO, mas não chega email nenhum.

Será que é o servidor de email!?!?

Só um detalhe, nossa rede tem proxy também, será que pode ser isso?!

[quote=bokerao]Passa normal, erro ZERO, mas não chega email nenhum.

Será que é o servidor de email!?!?[/quote]
Possível cara…
Você contratou um smtp ou tem o seu particular?

É um da Secretaria de Fazenda do Pará!
Conversei com um dos administradores de rede e segundo ele necessita liberação, assim que ele o fizer eu vou testar, por enquanto valeu mesmo Tchello, o código tá show de bola!

Fala Tchello
Consegui resolver a bronca e agora ele está enviando o email sem problemas.
Porém agora o problema é outro, estou usando o mesmo código que postei ali em cima.
Mas quando o email vem, o corpo dele mostra todo o conteúdo do PDF nums códigos doidos (que é o array de bytes) e não anexado como deveria ser, o começo do corpo do email é bem assim:

------=_Part_0_8689654.1260455014989
Content-Type: text/plain; name=PDF.pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=PDF.pdf

JVBERi0xLjQKJeLjz9MKNCAwIG9iaiA8PC9UeXBlL1hPYmplY3QvQ29sb3JTcGFjZVsvSW5kZXhl
ZC9EZXZpY2VSR0IgMjU1KAAAAP///8cjJckqK8otMMwyM887PLMiXCjPLjTUTFHba3Dlio3poKXq
uLv97e57VVn0ys/Jo6nBnqO2jpW7lJzSp7H309ucf4fpwMuWa3nYtL+3pKrguMbux9XKqbX73emN

Sabe me dizer o que pode tá rolando, além dos imports do javax.mail fiz os seguintes:

import javax.mail.util.ByteArrayDataSource;
import javax.activation.DataHandler;

Espero resposta
Abraços

Fala Tchello.

Cara, consegui resolver, minha pasta lib tava uma bagunça gigante de JARs.

Basicamente tirei tudo que se referia a email e deixei só o mail.jar do JavaMail 1.4.3. funcionou maravilhosamente bem, nem precisei do activation.jar. Será que ele já está nessa versãodo JavaMail??

Abraços e valeu mesmo…
Bokerão