MokaByte 87 - Luglio/Agosto 2004 
Un gestore di mailing list
III parte
di
Giovanni Bruni

Terza parte della serie dedicata alla gestione delle mailing list in Java.
Questo mese procediamo con l'ultima classe che rimane da esaminare, la MailSender.java

La classe, che è un thread, viene lanciata da JobExtractor quando c'è un Job disponibile nella lista. Dopo aver individuato il Job, la JobExtractor, instanzia la MailSender passando come parametri di inizializzazione in ordine, il time-out, il Job, un riferimento alla SynchronizationMonitor, l'eventuale indirizzo mail di prova.
Il time-out serve a stabilire la pausa tra un invio e il successivo; il job contiene le informazioni da inviare, la SynchronizationMonitor per notificare che il processo ha terminato l'esecuzione ed infine è possibile configurare l'indirizzo mail per una eventuale prova.
Quando si lancia la start() della MailSender, viene creato inizialmente il messaggio da inviare:
vengono settati i campi from, to, subject, message, il path degli attachments e gli attachments stessi. In particolare vengono settati i campi della MimeMessage:

private MimeMessage buildMessage(MailMessageInfo mmi) throws Exception {
Properties props = new Properties();
MailingListInfo mli = MailingListInfo.getSendersInfo();

props.put("mail.smtp.host", mli.smtpHost);
Session session = Session.getDefaultInstance(props, null);

String from = mmi.getFrom();
String subject = mmi.getSubject();
String message = mmi.getMessage();
String attachmentPath = mmi.getAttachmentPath();
String[] attachments = mmi.getAttachments();

// create a message
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
Address[] addr = {new InternetAddress(from)};
msg.setReplyTo(addr);
msg.setSubject(subject);

// create the Multipart and its parts to it
Multipart multipart = new MimeMultipart();

// create and fill the first message part
MimeBodyPart mbp1 = new MimeBodyPart();
mbp1.setText(message);
multipart.addBodyPart(mbp1);

// Gestione attachments
for (int j = 0; j < attachments.length; j++) {
MimeBodyPart mbp = new MimeBodyPart();
File file = new File(attachmentPath, attachments[j]);
if (!file.canRead()) {
logger.fatal("Cannot find file: " + file);
throw new Exception("Cannot find file: " + file);
}
try {
FileDataSource fds = new FileDataSource(file);
mbp.setDataHandler(new DataHandler(fds));
mbp.setFileName(file.getName());
multipart.addBodyPart(mbp);
} catch (Exception e) {
logger.fatal("Error during MIME management: " + file, e);
}
}
// add the Multipart to the message
msg.setContent(multipart);
// set the Date: header
msg.setSentDate(new Date());

return msg;

}

Dopo aver creato il messaggio, in semplice ciclo for si scorrono tutti gli indirizzi mail, si serializzano le strutture principali che mantengono i Job, e si chiama il metodo di invio mail.
Un metodo potrebbe essere il seguente:

public void sendMail(MimeMessage msg, String to, String destTest, String subject) throws Exception {
Address[] address = new Address[1];
if (destTest != null && !"".equals(destTest)) {
msg.setSubject(subject + " (" + to + ")");
address[0] = new InternetAddress(destTest);
msg.setRecipients(Message.RecipientType.TO, address);
} else {
// Siamo in spedizione di un FAX
address[0] = new InternetAddress(to);
}

try {
// send the message
Transport.send(msg, address);
logger.info("email " + to + " messaggio inviato");
} catch (MessagingException mex) {
logger.fatal("Exception: ", mex);
Exception ex = null;
if ((ex = mex.getNextException()) != null) {
logger.fatal("Exception: ", ex);
}
}
}

Se destTest non è null, tutte le mail, saranno inviate ad un unico indirizzo (di prova), ed il soggetto in tal caso viene costruito in questo modo:

soggetto originario + ( + mail a cui doveva essere inviato + )

Dopo aver inviato tutte le mail, occorre avvertire la JobExtractor che può inviare altri Job, per questo viene eseguita una semplice put() della SynchronizationMonitor.

Il progetto è abbastanza semplice dal punto del flusso e nello stesso tempo un po' complesso per quanto riguarda l'implementazione. Quindi particolare attenzione, è da porre nella SynchronizationMonitor la quale ha il compito di gestire le classi concorrenti di ricezione jobs, memorizzazione jobs ed infine invio.

Tale progetto può essere ampliato se pensiamo al fatto di poter amministrare il sistema tramite interfaccia web. Ad esempio, si potrebbe pensare di monitorare i Job ogni x secondi, quindi poter visualizzare quante mail ci sono ancora da inviare per un certo Job e/o quanti Job da processare; e se necessario si potrebbe anche creare un metodo che permette la cancellazione di un Job. Volendo un po' fantasticare (ma è poco distante dalla realtà…) si può anche creare un sistema web che permette di creare i Job, quindi gestione sia di messaggi con allegati che gestione di mailing list.


MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it