(Resolvido) - JavaMail - Enviar .pdf anexado no email (in-memory) : (Ajuda)

6 respostas
P

Boa tarde pessoal,

Estou precisando de uma ajuda, para enviar um .pdf file anexado no email, porem esse pdf está sendo enviado por uma mensagem JMS ou in-memory, não tem arquivo físico na máquina, quando eu trato com um arquivo físico, ele envia sem problemas.
In-Memory oq acontece é que quando envio o arquivo .pdf e eu recebo um arquivo do tipo MIME application/octet-stream, porem já tentei tratar com DataHandler, ByteArrayDataSource, mas está difícil achar uma solução que de certo até agora.]

Segue código:

MimeMessage msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress(from));
			InternetAddress[] address = { new InternetAddress(to) };
			msg.setRecipients(Message.RecipientType.TO, address);
			msg.setSubject("Assunto teste.");

			// create and fill the first message part
			MimeBodyPart bp1 = new MimeBodyPart();
			bp1.setText("Texto teste.");
			// create the second message part
			MimeBodyPart bp2 = new MimeBodyPart();

			// attach the file to the message
			m_xqLog.logInformation("[ContentType]: "+prt.getContentType());
			//FileDataSource fds = new FileDataSource(prt.getDataHandler()));
			//DataHandler sh = new DataHandler((DataSource) prt.getDataHandler());
			DataSource ds = new FileDataSource("scenario/Testepdf.pdf");
			bp2.setDataHandler( new DataHandler(ds));
			//bp2.setContent(prt.getContent().toString().getBytes(), prt.getContentType());
			//bp2.setDataHandler(new DataHandler(new ByteArrayDataSource(prt.getContent().toString(),"application/pdf")));
			bp2.setFileName("Testepdf.pdf");
			// create the Multipart and add its parts to it
			Multipart mp = new MimeMultipart();
			mp.addBodyPart(bp1);
			mp.addBodyPart(bp2);

			// add the Multipart to the message
			msg.setContent(mp);

			// set the Date: header
			msg.setSentDate(new Date());

			// send the message
			Transport.send(msg);
			System.out.println("Email sent successfully!");

Neste cenário está funcionando certinho, porem estou precisando que o arquivo seje em memória e não físico.

Qualquer ajuda será bem vinda.

Abs,

Paulo Sampei

6 Respostas

B

BufferReader?
poste sua classe completa para podermos te ajudar!
Grata.

P

Obrigado bilu pela resposta, não muda muita coisa na classe, mas segue o código:

protected void SendEmail(XQPart prt, String host, String from, String to){
		// create some properties and get the default Session
		Properties props = System.getProperties();
		props.put("mail.smtp.host", host);

		Session session = Session.getInstance(props, null);

		try {
			// create a message
			MimeMessage msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress(from));
			InternetAddress[] address = { new InternetAddress(to) };
			msg.setRecipients(Message.RecipientType.TO, address);
			msg.setSubject("Assunto teste.");

			// create and fill the first message part
			MimeBodyPart bp1 = new MimeBodyPart();
			bp1.setText("Texto teste.");
			// create the second message part
			MimeBodyPart bp2 = new MimeBodyPart();

			// attach the file to the message
			m_xqLog.logInformation("[ContentType]: "+prt.getContentType());
			//FileDataSource fds = new FileDataSource(prt.getDataHandler()));
			//DataHandler sh = new DataHandler((DataSource) prt.getDataHandler());
			DataSource ds = new FileDataSource("scenario/Testepdf.pdf");
			bp2.setDataHandler( new DataHandler(ds));
			//bp2.setContent(prt.getContent().toString().getBytes(), prt.getContentType());
			//bp2.setDataHandler(new DataHandler(new ByteArrayDataSource(prt.getContent().toString(),"application/pdf")));
			bp2.setFileName("Testepdf.pdf");
			// create the Multipart and add its parts to it
			Multipart mp = new MimeMultipart();
			mp.addBodyPart(bp1);
			mp.addBodyPart(bp2);

			// add the Multipart to the message
			msg.setContent(mp);

			// set the Date: header
			msg.setSentDate(new Date());

			// send the message
			Transport.send(msg);
			System.out.println("Email sent successfully!");

		} catch (MessagingException mex) {
			mex.printStackTrace();
			Exception ex = null;
			if ((ex = mex.getNextException()) != null) {
				ex.printStackTrace();
			}
		}
	}

Então quando eu mudo, para receber o XQPart que sendo a parte de uma mensagem JMS e já 'seto' ela direto com SetContent(prt.getContent, 'application/pdf'), aparece uma exception para mim:

log:

Message: [B@79ffb7f7 /// the service received the pdf file

[09/03/02 12:22:45] ID=dev_ESBTest (info) application/octet-stream ///ContentType of message

javax.mail.SendFailedException: Sending failed; ///Exception

nested exception is:

javax.mail.MessagingException: IOException while sending message;

nested exception is:

*javax.activation.UnsupportedDataTypeException: no object DCH for MIME type application/octet-stream*

at javax.mail.Transport.send0(Transport.java:219)

at javax.mail.Transport.send(Transport.java:81)

javax.mail.MessagingException: IOException while sending message;

nested exception is:

javax.activation.UnsupportedDataTypeException: no object DCH for MIME type application/octet-stream

at com.sun.mail.smtp.SMTPTransport.sendMessage (SMTPTransport.java:353)

at javax.mail.Transport.send0 (Transport.java:164)

at javax.mail.Transport.send(Transport.java:81)

Obrigado pela resposta.

Qualquer coisa vai falando ai..

Abs,

Paulo sampei.

F

Vc quer enviar um email com anexo em memória? sem precisar de um File pro anexo?
Passei por isso tb. Resolvi da seguinte forma:

PS: Analise o codigo e efetue as devidas alterações. Existem objetos aí que sao do meu contexto e framework que utilizo.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import java.io.OutputStream;

import javax.activation.DataSource;

public class InputStreamDataSource implements DataSource {

    private String name;
    private String contentType;
    private ByteArrayOutputStream baos;

    InputStreamDataSource(String name, String contentType, 
                          InputStream inputStream) throws IOException {
        this.name = name;
        this.contentType = contentType;
        baos = new ByteArrayOutputStream();
        int read;
        byte[] buff = new byte[256];
        while ((read = inputStream.read(buff)) != -1) {
            baos.write(buff, 0, read);
        }
    }

    public String getContentType() {
        return contentType;
    }

    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(baos.toByteArray());
    }

    public String getName() {
        return name;
    }

    public OutputStream getOutputStream() throws IOException {
        throw new IOException("RECURSO APENAS DE LEITURA. IMPOSSIVEL ESCREVER");
    }
    
}

Exemplo de utilização:

ClobDomain clobLista = rowLista.getTxLista();
    byte[] lista = clobLista.toString().getBytes("ISO-8859-15");        
    ByteArrayInputStream anexoStream = new ByteArrayInputStream(lista);        
    InputStreamDataSource dataSource = new InputStreamDataSource("lista_" + rowLista.getNrLista() + ".doc", "text/doc", anexoStream);
        
    this.enviarEmail( "##########", "############", this.getEmailRemetente(), this.getEmailDestinatario(), dataSource );




    private void enviarEmail(String assunto, String corpo, String from, 
            String to, InputStreamDataSource anexo) throws Exception {
        
        SystemParameters params = SystemParameters.getInstance();
        
        Properties props = System.getProperties();
        props.put("mail.smtp.host", params.getStrParam(SystemParameters.MAIL_SERVER));
        props.put("mail.smtp.port", params.getStrParam(SystemParameters.MAIL_PORT_SERVER));
        props.put("mail.smtp.auth", "false");
        props.put("mail.debug", "true");
        props.put("mail.smtp.debug", "true");
        props.put("mail.mime.charset", "ISO-8859-1");
        props.put ("mail.smtp.starttls.enable", "true");
        
        Session session = Session.getDefaultInstance(props, null);
        
        //CRIA O EMAIL
        MimeMessage message = new MimeMessage(session);
        
        //TITULO DO EMAIL
        message.setSubject(assunto);
        
        //CONFIGURA DATA DE ENVIO
        message.setSentDate(new Date());
        
        //CONFIGURA O REMETENTE
        message.setFrom(new InternetAddress(from));
        
        //CONFIGURA O DESTINATARIO
        InternetAddress[] address = {new InternetAddress(to)};
        message.setRecipients(Message.RecipientType.TO, address);
        
        //SETA O TEXTO DO EMAIL
        MimeBodyPart body = new MimeBodyPart();
        body.setText(corpo);
        
        MimeBodyPart attachment = new MimeBodyPart();
        attachment.setDataHandler( new DataHandler(anexo) );
        attachment.setFileName(anexo.getName());
        
        //CRIA A MULTIPART
        Multipart mp = new MimeMultipart();
        
        //ADICIONA AS INFORMACOES E CONTEUDO DO EMAIL
        mp.addBodyPart(body);
        
        //ADICIONA O ANEXO
        mp.addBodyPart(attachment);
        
        //SETA O CONTEUDO 
        message.setContent(mp);
        
        //ENVIA
        Transport.send(message);
        
    }
P

Deixa eu tentar passar o cenário. Na verdade esse programa entra como ServiceType em um integração, onde eu crio um processo, sendo dentro deste processos segue passo (Step) que são os Services.
Seguindo os dados (Messages) step-by-step.

Exemplo: NomeProcesso: Enviar Email
Passo1: Pegar informação do banco (ServiceName:DBService):
Passo2: Transformo informação para um padrão conforme requerimento(ServiceName:Tranform)
Passo3: Se umas das informações não atenderem o requisito então volto a mensagem (IF/ELSE)(ServiceName:CBR)
Passo4: Se atendeu gero um pdf com a informação (ServiceName:GeneratePdf)
Passo5: pego o pdf e anexo a mensagem enviando um email (ServiceName:AttachFileOnEmail)
etc…

Então o .pdf não está em máquina, por isso que falo que está em memória… mas enfim vou dar uma olhada nessa sua solução, já havia sobrescrito essa classe antes, mas sem sucesso, mas vou seguir o seu modelo…

de qualquer forma muito obrigado, e já falo se consegui ou não…

qualquer dúvida a disposição.

Paulo Sampei.

F

Funciona sim.

Na verdade, rodou um tempo essa rotina aqui enviando um .pdf, por razoes do cliente virou .doc.
Mas eu tinha o mesmo problema que vc: nao existiria File, arquivo em disco, precisava enviar o anexo (pdf) em memoria, e dessa maneira resolveu bem.

P

Bom dia a todos.
fabim e comunidade Guj, parabéns, consegui resolver esse problema de enviar um email com anexo em pdf e conforme falei anteriormente, passarei a solução, afim de outros que obtiverem o mesmo problema procurem a solução fácil e rápida, parabens a todos que ajudaram....

Solução:

Code 1: Call 2 method passing requirement parameter:

Obs: Always ContentType = application/octet-stream

ByteArrayInputStream attachStream = new ByteArrayInputStream((byte[]) prt.getContent());
							//call constructor class:InputStreamDataSource
							InputStreamDataSource isds = new InputStreamDataSource("Testepdf.pdf", prt.getContentType(),attachStream);
							//call method sendMail(InputStreamDataSource,host,from,to)
							sendMail(isds, s_Host, s_SendFrom, s_SendTo);

Code 2: Class InputStreamDataSource

// statement DataSource
	private class InputStreamDataSource implements DataSource {
		
		private String name;
		private String contentType;
		private ByteArrayOutputStream baos;

		InputStreamDataSource(String name, String contentType,
				InputStream inputStream) throws IOException {
			int read;			
			this.name = name;
			this.contentType = contentType;
			
			baos = new ByteArrayOutputStream();
			
			byte[] buff = new byte[256];			
			while ((read = inputStream.read(buff)) != -1) {
				baos.write(buff, 0, read);
			}
		}

		public String getContentType() {
			// TODO Auto-generated method stub
			return contentType;
		}

		public InputStream getInputStream() throws IOException {
			// TODO Auto-generated method stub
			return new ByteArrayInputStream(baos.toByteArray());
		}

		public String getName() {
			// TODO Auto-generated method stub
			return name;
		}

		public OutputStream getOutputStream() throws IOException {
			// TODO Auto-generated method stub
			throw new IOException("Cannot write to this read-only resource");
		}
	}

Code 3: mehod sendMail(InputStreamDataSource, host, from, to)

protected void sendMail(InputStreamDataSource attach, String host,
			String from, String to) {
		// create some properties and get the default Session
		Properties props = System.getProperties();
		props.put("mail.smtp.host", host);

		Session session = Session.getInstance(props, null);

		try {
			// create a message
			MimeMessage msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress(from));
			InternetAddress[] address = { new InternetAddress(to) };
			msg.setRecipients(Message.RecipientType.TO, address);
			msg.setSubject("Assunto teste.");

			// create and fill the first message part
			MimeBodyPart bp1 = new MimeBodyPart();
			bp1.setText("Texto teste.");

			// create the second message part
			MimeBodyPart bp2 = new MimeBodyPart();
                        // attach the file to the message
			bp2.setDataHandler(new DataHandler(attach));
                        // getNameFile
			bp2.setFileName(attach.getName());

			// create the Multipart and add its parts to it
			Multipart mp = new MimeMultipart();
			mp.addBodyPart(bp1);
			mp.addBodyPart(bp2);

			// add the Multipart to the message
			msg.setContent(mp);

			// set the Date: header
			msg.setSentDate(new Date());

			// send the message
			Transport.send(msg);
			System.out.println("Email sent successfully!");

		} catch (MessagingException mex) {
			mex.printStackTrace();
			Exception ex = null;
			if ((ex = mex.getNextException()) != null) {
				ex.printStackTrace();
			}
		}
	}

Segue a solução, obrigado comunidade, fabim e biluquinha , pela atenção.

abs,

Paulo Sampei.

Criado 5 de maio de 2009
Ultima resposta 6 de mai. de 2009
Respostas 6
Participantes 3