quinta-feira, 11 de outubro de 2012

Enviar email usando SMTP - parte II

Vamos agora apresentar uma classe simples para os testes e os resultados da execução


/*
 * classe de teste
 */

package testeenvioemail;

/**
 *
 * @author Henrique
 */

public class TesteEnvioEmail {

    /**
     * @param args não utilizado
     */

    public static void main(String[] args) {
        /*
         * Cria o remetente cadastrando dados do usuário, senha, host etc
         *
         */

        EmailRemetente rmt = new EmailRemetente();
        rmt.setUsuarioNome("Henrique Moura");
        rmt.setUsuarioEmail("COLOQUE AQUI SEU EMAIL");
        rmt.setSenha("A SENHA DO PROVEDOR PARA SEU USUÁRIO");
        rmt.setNomeHost("ENDEREÇO DO SERVIDOR SMTP");
        rmt.setPortaAlternativa(); // no meu caso preciso usar a porta 587
       
         /*
          * cria a mensagem composta por
          * 1) destinatario
          * 2) assunto
          * 3) corpo
         */

        EmailMensagem msg = new EmailMensagem();
        msg.setDestinatario("ENDEREÇO DE EMAIL PARA TESTES", "Henrique");
        msg.setAssunto("Assunto da mensagem - teste");
        msg.setCorpo("teste de mensagem enviada por email... via java");
       
        try {
           
            /*
             * prepara e envia o email
             */

            EnviarEmail email = new EnviarEmail(rmt, msg);
                       
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
   }
}


No Netbeans você deve configurar as bibliotecas para tudo funcionar:



Vamos ver a saída do programa:
run:
DEBUG: JavaMail version 1.4.5
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Sun Microsystems, Inc], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Sun Microsystems, Inc], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Sun Microsystems, Inc]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Sun Microsystems, Inc], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Sun Microsystems, Inc], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Sun Microsystems, Inc], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: setDebug: JavaMail version 1.4.5
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.fournet.inf.br", port 587, isSSL false
220 parodius.seven.com.br ESMTP Postfix
DEBUG SMTP: connected to host "smtp.fournet.inf.br", port: 587

EHLO 192.168.0.113
250-SERVIDOR SELECIONADO
250-PIPELINING
250-SIZE 31457280
250-ETRN
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250 8BITMIME
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "SIZE", arg "31457280"
DEBUG SMTP: Found extension "ETRN", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN"
DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Attempt to authenticate
DEBUG SMTP: check mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
DEBUG SMTP: use8bit false
MAIL FROM:<EMAIL DO REMETENTE>
250 2.1.0 Ok
RCPT TO:<EMAIL DO DESTINATÁRIO>
250 2.1.5 Ok
DEBUG SMTP: Verified Addresses
DEBUG SMTP:   EMAIL DO DESTINATÁRIO
DATA
354 End data with <CR><LF>.<CR><LF>
From: Henrique Moura <
EMAIL DO REMETENTE>
To:
EMAIL DO DESTINATÁRIOMessage-ID: <29930061.0.1350336137396.JavaMail.Henrique@Henrique-PC>
Subject: Assunto da mensagem - teste
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

teste de mensagem... via java
.
250 2.0.0 Ok: queued as 4B73B95D53
QUIT
221 2.0.0 Bye
CONSTRUÍDO COM SUCESSO (tempo total: 4 segundos)

Se você rodar o código conforme está neste post e no anterior, a primeira dúvida que vai surgir na sua cabeça é: como é que está aparecendo este tanto de linhas de debug na tela? É que na verdade eu acrescentei duas linhas dentro da classe EnviarEmail somente para que vocês vissem as mensagens. Estas mensagens ajudar a descobrir algum erro, como por exemplo autenticação, porta errada etc. As linhas que coloquei são:
  • props.put("mail.debug", "true");
  • session.setDebug(true);
A linha em verde acima também só vai aparecer se você estiver rodando no Netbeans. É uma informação da IDE sobre o tempo de montagem e compilação das classes no arquivo JAR.

Você agora pode incrementar as classes:
  • colocando autenticação para SSL e TLS;
  • pode colocar anexos;
  • pode colocar múltiplos destinatários;
  • etc.


Sem as linhas de debug ao rodar o programa você vai ter somente:
run:
CONSTRUÍDO COM SUCESSO (tempo total: 4 segundos)

quarta-feira, 10 de outubro de 2012

Enviar email usando SMTP

Tive a necessidade de acrescentar em um software que estou fazendo uma classe para enviar uma mensagem via email. Precisava montar algo que conectasse ao servidor SMTP do cliente e encaminhasse a mensagem uma conta de email previamente cadastrada para este fim.
O J2SE pra variar me deu todas as ferramentas necessárias para isto. Para gerar o email utilizar o pacote JavaMail, mais especificamente o javax.mail.
Vou apresentar abaixo as classes que utilizei para conseguir enviar o mail. Eu criei:
  • um bean EmailRemetente que contem as informações do remetente incluindo os dados do servidor SMTP, porta, usuário para conexão, autenticação etc.
  • um bean EmailMensagem que contem o destinatario da mensagem e a mensagem em si
  • uma classe EnviarMensagem que trata do envio e que instancia as duas classes de remetente e destinatário
  • uma classe de teste para vocês verem como funcionam.
Vamos lá!
As classes foram criadas usando a IDE Netbeans, portanto vocês vão ver algumas coisas que o próprio Netbeans coloca, ok?

EmailRemetente foi feito na forma de um java bean, portanto o construtor não tem parâmetros e as variáveis são acessíveis via getter e setters (encapsulamento). Notem que por default coloco a porta SMTP como 25 mais tem como trocar.

/*
 *
 * Esta classe guarda os dados do rementente incluindo informações de acesso ao servidor
 * Obrigatoriamente para utilizar este bean é necessário após a criação alterar as propriedades
 * de:
 * 1) nome do Host
 * 2) email do usuario
 * 3) senha do usuario
 *
 */

package testeenvioemail;

/**
 *
 * @author Henrique
 */

public class EmailRemetente {

  private String nomeHost;
  private String porta = "25";
  private String usuarioEmail;
  private String usuarioNome;
  private String senha = "";
  private Boolean autenticar = true;

    /**
     * @return nome do Host (endereço ip ou FQDN)
     */

    public String getNomeHost() {
        return nomeHost;
    }

    /**
     * @param nomeHost nome do host SMTP que enviará a mensagem
     */

    public void setNomeHost(String nomeHost) {
        this.nomeHost = nomeHost;
    }

    /**
     * @return a porta do servidor SMTP configurada
     */

    public String getPorta() {
        return porta;
    }

    /**
     * seta a porta para um valor
     *
     * @param porta novo valor, normalmente 25, 465 ou 587
     * Google mail SSL Porta 465 StartTLS Porta 587
     * Outlook.com (ou Hotmail) StartTLS Porta 587
     * Yahoo SSL Porta 465
     *
     */

    public void setPorta(String porta) {
        this.porta = porta;
    }

    /*
     * porta default alternativa usado para new submissions (MSA)
     * muito usada quando em conjunto com StartTLS
     */

    public void setPortaAlternativa() {
        this.porta = "587";
    }
   
    /*
     * porta padrão do SMTP
     */

    public void setPortaDefault() {
        this.porta = "25";
    }
   
    /**
     * @return o email do usuario
     */

    public String getUsuarioEmail() {
        return usuarioEmail;
    }

    /**
     * @param usuario o endereço de email do usuário

     *        (utilizado para conectar ao servidor SMTP 
     *         e para preencher o campo FROM)
     */

    public void setUsuarioEmail(String usuarioEmail) {
        this.usuarioEmail = usuarioEmail;
    }

    /**
     * @return senha
     */

    public String getSenha() {
        return senha;
    }

    /**
     * @param senha pega a senha do usuário 

     *             (usado para autenticar o usuário no servidor)
     */

    public void setSenha(String senha) {
        this.senha = senha;
    }

    /**   
    * @return nome do Usuario
     */

    public String getUsuarioNome() {
        return usuarioNome;
    }

    /**
     * @param nomeUsuario texto simples com o nome do usuário
     */

    public void setUsuarioNome(String usuarioNome) {
        this.usuarioNome = usuarioNome;
    }

    /**
     * @return indica se deve fazer procedimento de autenticação
     */

    public Boolean getAutenticar() {
        return autenticar;
    }

    /**
     * @param autenticar
     */

    public void setAutenticar(Boolean autenticar) {
        this.autenticar = autenticar;

    }
}

Aqui fica a mensagem e o destinatário. O ideal seria que o destinatário fosse uma lista e que tivéssemos um método para adicionar e outro para remover destinatários da lista.

/*
 * guarda a mensagem e o remetente
 * TODO: colocar os destinatarios como uma lista
 */

package testeenvioemail;

/**
 *
 * @author Henrique
 */

public class EmailMensagem {
   
    private String emailDestinatario;
    private String nomeDestinatario;
    private String assunto;
    private String corpo;
    private String mimeCorpo = "text/plain";

    /**
     * @return email do Destinatario
     */

    public String getEmailDestinatario() {
        return emailDestinatario;
    }

    /**
     * @param emailDestinatario o email de destino
     * @param nomeDestinatario o nome por exterso do destinatario da mensagem
     */

    public void setDestinatario(String emailDestinatario, String nomeDestinario){
        this.emailDestinatario = emailDestinatario;
        this.nomeDestinatario = nomeDestinatario;
    }

    /**
     * @return the nomeDestinatario
     */

    public String getNomeDestinatario() {
        return nomeDestinatario;
    }

    /**
     * @return the assunto
     */

    public String getAssunto() {
        return assunto;
    }

    /**
     * @param assunto the assunto to set
     */

    public void setAssunto(String assunto) {
        this.assunto = assunto;
    }

    /**
     * @return the corpo
     */

    public String getCorpo() {
        return corpo;
    }

    /**
     * @param corpo the corpo to set
     */

    public void setCorpo(String corpo) {
        this.corpo = corpo;
    }

    /**
     * @return the mimeCorpo
     */

    public String getMimeCorpo() {
        return mimeCorpo;
    }

    /**
     * @param mimeCorpo the mimeCorpo to set
     */

    public void setMimeCorpo(String mimeCorpo) {
        this.mimeCorpo = mimeCorpo;
    }
   
}


E agora a classe que efetivamente envia o email:
/*
 * Para executar este código é preciso colocar o JavaMail (mail.jar) no classpath
 * a biblioteca pode ser obtida no site da oracle
 * no endereço http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-eeplat-419426.html#javamail-1.4.5-oth-JPR
 *
 */

package testeenvioemail;

import java.io.UnsupportedEncodingException;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
/**
 *
 * @author Henrique
 */

public class EnviarEmail {
   
    /*
     * variavel interna utilizada para gravar a mensagem
     */

    private MimeMessage mimeMsg;
   
    public EnviarEmail(final EmailRemetente rmt, EmailMensagem msg) throws MessagingException, UnsupportedEncodingException {

        Properties props = System.getProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.host", rmt.getNomeHost());
        props.put("mail.smtp.port", rmt.getPorta());
        props.put("mail.smtp.user", rmt.getUsuarioEmail());
        if (rmt.getAutenticar()) {
            props.put("mail.smtp.auth", "true");
        } else {
            props.put("mail.smtp.auth", "false");
        }
        //
        Authenticator auth = new Authenticator() {
            @Override
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(rmt.getUsuarioEmail(),

                                                  rmt.getSenha());
            }           
        };

        // obtem a sessão
        Session session = Session.getDefaultInstance(props, auth);
        mimeMsg = new MimeMessage(session);
        mimeMsg.setFrom(new InternetAddress(rmt.getUsuarioEmail(),

                                            rmt.getUsuarioNome()));
        mimeMsg.addRecipient(RecipientType.TO,

                             new InternetAddress(msg.getEmailDestinatario(),
                                                 msg.getNomeDestinatario()));
        mimeMsg.setSubject(msg.getAssunto());
        mimeMsg.setContent(msg.getCorpo(), msg.getMimeCorpo());

        Transport.send(mimeMsg); // enviar a mensagem       
    }
   
}


Alguns pontos importantes:
  • veja que o parâmetro rmt está como final. Isto acontece porque utilizamos dentro da definição da classe Autheticator.
  • Authenticator é uma classe abstrata e temos que implementar getPasswordAuthentication.
  • Em properties definimos o protocolo de comunicação "mail.transport.protocol" : isto não é obrigatório. Nos meus testes, vi que não fazia diferença nos resultados. Note que o protocolo está explícito nas demais entradas de props. Por exemplo "mail.smtp.host"
  • Session representa a sessão de email, armazenando propriedades e padrões usados pela API de email. Uma única default session pode ser compartilhada entre diversas aplicações no desktop, mas se você quiser pode criar uma sessão exclusiva. Eu optei por usar a sessão default.
  • Transport modela na API o transporte da mensagem. Utilizamos o método send para enviar a mensagem MIME que criamos antes.
  • MimeMessage é uma subclasse de Message. Para implementação poderíamos utilizar SMTPMessage que é uma classe de MimeMessage, mas no momento não precisamos das características adicionais apresentadas por SMTPMessage. Precisamos criar na mensagem as informações de:
    • From: de quem vem a mensagem (rmt)
    • To: para quem vai a mensagem (msg).
    • Subject: o assunto
    • Content: o texto que queremos enviar
  • Existe um método addRecipients que permite criar várias destinatários de uma só vez. addRecipient pode também ser chamado várias vezes para acrescentar os destinatários um a um.
  • ao invés de setContent poderíamos utilizar setText se o MIME type for "text".



No próximo post mostro para vocês o teste destas classes.

segunda-feira, 1 de outubro de 2012

Java + Netbeans + Android

Oi Pessoal,

Vamos ver hoje como fazer para configurar o seu netbeans 7.2 para funcionar como uma IDE para desenvolvimento de aplicações para Android.

O primeiro passo é baixar e instalar o SDK do Android para o seu computador. Vá no site http://developer.android.com/sdk/index.html e pegue o instalador para a sua plataforma. No meu caso é Windows.

Segundo as notas do site, o download não é um ambiente SDK completo. Ele inclui somente as ferramentas SDK principais. Rode o instalador que irá verificar a existência do JDK e fazer a instalação.




Terminada a instalação o Android SDK Manager verificará e permitirá que você faça o download das demais ferramentas, plataformas e componentes.



É recomendável que você instale:
  • SDK Tools
  • SDK Platform Tools
  • SDK Platform
  • System Image
  • Android Support
  • SDK Samples
  • Android Support Library



Você deve inserir manualmente na variável de ambiente PATH o caminho para tools/ e platform/tools.



Vamos criar agora a máquina virtual android para podermos testar os nossos programas.


 Vamos rodar para ver se está tudo ok.




 
Ok... Até aqui tudo está funcionado.

Se você utiliza Eclipse, a instalação continua fácil, bastando instalar o ADT Plugin para o Eclipse. Mas se você como eu, utiliza Netbeans, existem mais alguns passos a serem feitos.

Abra agora o Netbeans, selecione o menu Ferramentas | Plugin e na tela que se abre opte por Definições. Acione o botão de Adicionar e coloque o endereço do projeto Android Plugin for Netbeans (veja mais detalhes em http://kenai.com/projects/nbandroid).



 Na aba de Plugins disponíveis, podemos encontrar a entrada que foi inserida agora. Selecione esta entrada e mande instalar. Será feito o download.



O Netbeans informa que alguns plugins não são confiáveis, pois não estão devidamente assinados. Você tem que clicar no botão Continuar para autorizar a instalação.




Agora que o Android plugin para o NetBeans foi instalado, você precisará fazer apenas mais um passo para configurá-lo. Criar um novo projeto no Netbeans para verificar:
  • Vá em novo projeto
  • Selecione um novo projeto android


No próximo post vamos terminar a configuração e criar um HelloAndroid (falta de imaginação ... eu sei).