Javamail - Otimização

7 respostas
rodpuc

Tenho o seguinte método que uso para enviar e-mails em meu sistema.
Um dos tipos de e-mail é uma newsletter... bom, o meu sistema ainda não está em produção e resolvi fazer um teste cadastrando míseros 500 usuários e, quando tentei mandar a newsletter levou uma eternidade... Isso me preocupa muito pois o sistema espera ter cerca de 1 milhão de usuários (ou mais) =x

Alguém poderia me dar uma mão em como otimizar isso, ou fornecer alguma altrenativa a essa maneira de enviar a newsletter?

public void sendEmail(EmailTemplate emailTemplate, List<String> recipients) {
        boolean debug = false;

        // Set the host smtp address
        Properties props = new Properties();
        props.put("mail.smtp.host", SMTP_HOST_NAME);
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");

        Authenticator auth = new SMTPAuthenticator();
        Session session = Session.getDefaultInstance(props, auth);

        session.setDebug(debug);

        // create a message
        Message msg = new MimeMessage(session);

        // set the from and to address
        InternetAddress addressFrom = new InternetAddress(emailFromAddress);
        msg.setFrom(addressFrom);
        emailTemplate.aplicarTemplate(msg);

        // Um e-mail para cada usuário
        for (String recipient : recipients) {
            InternetAddress[] addressTo = new InternetAddress[1];
            addressTo[0] = new InternetAddress(recipient);
            msg.setRecipients(Message.RecipientType.TO, addressTo);

            Transport.send(msg);
        }
}

7 Respostas

A

A principio a melhor forma de se fazer isto é criando threads !!!
Assim vc consegue enviar varios emails ao mesmo tempo… !!! neste seu caso Threads e ThreadPoolExecutor

Não sei se vc sabe mexer com thread, mas de uma pesquisada e surgindo duvidas poste que a galera vai te ajudando…

Att

Tchello

Primeiro, seu sistema roda em que tipo de ambiente?
Quais são as tecnologias utilizadas?

rodpuc

roda no tomcat
usa spring, hibernate e struts 2

kzar.razk

Talvez o serviço de SMTP tenha uma solução melhor no caso da mensagem for igual para todos os usuários, um grupo de usuários que receba a mensagem e a encaminhe para todos os usuários do grupo. Seu método não tem tratamento de exceção e existe um risco bem grande de estas ocorrerem. Conheço sistemas de newsletter que tem 300000 usuário e funciona perfeitamente.

rodpuc

Legal! Fiz com threads e parece ter melhorado bastante, porém surgiram agora 2 problemas.
Primeiro deixa eu mostrar como eu fiz, aí vou falar oq acontece de errado.

public class MailSenderThread extends Thread {
    //... omitido

    public MailSenderThread(String recipient, EmailTemplate emailTemplate) {
        super();
        this.recipient = recipient;
        this.emailTemplate = emailTemplate;
        start();
    }

    @Override
    public void run() {
        try {
            boolean debug = false;

            Properties props = new Properties();
            props.put("mail.smtp.host", SMTP_HOST_NAME);
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.starttls.enable", "true");

            Authenticator auth = new SMTPAuthenticator();
            Session session = Session.getDefaultInstance(props, auth);

            session.setDebug(debug);

            // create a message
            Message msg = new MimeMessage(session);

            // set the from and to address
            InternetAddress addressFrom = new InternetAddress(emailFromAddress);
            msg.setFrom(addressFrom);
            this.emailTemplate.aplicarTemplate(msg);

            InternetAddress[] addressTo = new InternetAddress[1];
            addressTo[0] = new InternetAddress(this.recipient);
            msg.setRecipients(Message.RecipientType.TO, addressTo);

            Transport.send(msg);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
    
    //... omitido
E no meu bean do spring
for (String recipient : validRecipients) {
            MailSenderThread thread = new MailSenderThread(recipient, emailTemplate);
}

Aí surgem 2 problemas:
1 - Estou criando threads indiscriminadamente, isso não pode causar um problema de falta de memória em algum momento?

2 - Muitos dos e-mails são enviados com sucesso, mas para muitos outros eu tomo esse erro: Could not connect to SMTP host: mail.[omitido].com.br, port: 25
Acredito que isso se deva a uma limitação no número de conexões simultâneas que o servidor de e-mail aceita.

Para ambos os problemas, a solução seria limitar o número de threads que rodam em paralelo. Gostaria de saber se vcs concordam com o meu "diagnóstico" do problema e como fazer essa limitação de threads.

Valeu!

Tchello

Se for usar essa solução de Threads mesmo use um ThreadPool, um ScheduledThreadPool por exemplo lhe serviria.
Nele você pode limitar o número de threads simultâneas, dai conforme elas foram acabando outras que estão na fila serão executadas.

Abraços.

edit: correção.

M

Muitos (senão todos os) serviços de e-mail limitam a quantidade de e-mails enviados por hora/dia e/ou o número de conexões simultâneas.

Uma solução que alguns provedores oferem é o uso de grupos de e-mail no servidor.

Um exemplo prático: usando Google Apps, pode-se criar um grupo com 10 mil pessoas e enviar apenas 1 e-mail que chegará para todas elas.

Isso reduz em milhares de vezes o tempo gasto no envio de e-mails. Isso pode ser crucial, principalmente em casos como o seu, em que o número de e-mails é absurdamente grande.

Entretanto, nem todos os provedores de e-mail têm uma funcionalidade semelhante. De qualquer forma, fica a dica.

Criado 18 de fevereiro de 2011
Ultima resposta 19 de fev. de 2011
Respostas 7
Participantes 5