diff -r 000000000000 -r e76872ad5226 java/Postak/src/cz/frantovo/postak/Postak.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/Postak/src/cz/frantovo/postak/Postak.java Sun Nov 23 22:19:20 2008 +0100 @@ -0,0 +1,221 @@ +package cz.frantovo.postak; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; +import javax.mail.Address; +import javax.mail.Authenticator; +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.MimeMessage; + +/** + * Odešle hromadnou zprávu pomocí SMTP. + * + * @author fiki + */ +public class Postak { + + private static Logger log = Logger.getLogger(Postak.class.getName()); + /** Regulární výraz pro správnou e-mailovou adresu */ + private static String REGULARNI_EMAIL = "^[_a-zA-Z0-9\\.\\-]+@[_a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,4}$"; + + private Nastaveni nastaveni; + + public Postak(Nastaveni nastaveni) { + this.nastaveni = nastaveni; + } + + public void setNastaveni(Nastaveni nastaveni) { + this.nastaveni = nastaveni; + } + + /** + * Nízkoúrovňová odesílací metoda, která už nekontroluje limit příjemců. + * Pokud se nevejdou do limitu SMTP serveru, vyhazuje výjimku. + * + * TODO: lepší to bude nestaické - nastavení si vyžádat v konstruktoru + */ + private void odesliSMTP(HromadnaZprava zprava) throws MessagingException { + + if (zkontrolujZpravu(zprava) && zkontrolujNastaveni(nastaveni)) { + + /** Inicializace SMTP */ + Properties smtpVlastnosti = System.getProperties(); + smtpVlastnosti.put("mail.smtp.host", nastaveni.getPostovniServer()); + smtpVlastnosti.put("mail.smtp.port", String.valueOf(nastaveni.getPostovniPort())); + + if (nastaveni.getPostovniPort() == 465) { + if (new File(nastaveni.getCestaKCertifikatum()).exists()) { + System.setProperty("javax.net.ssl.trustStore", nastaveni.getCestaKCertifikatum()); + log.log(Level.INFO, "Používám vlastní důvěryhodné certifikáty: " + nastaveni.getCestaKCertifikatum()); + } + /** TODO: neřídit se číslem portu, ale přidat příznak pro šifrování */ + smtpVlastnosti.put("mail.smtp.starttls.enable", "true"); + smtpVlastnosti.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); + smtpVlastnosti.put("mail.smtp.socketFactory.port", String.valueOf(nastaveni.getPostovniPort())); + smtpVlastnosti.put("mail.smtp.socketFactory.fallback", "false"); + /** + * NAHRÁNÍ CERTIFIKÁTU: + * 1) stáhneme si certifikát (---BEGIN CERTIFICATE---) a uložíme do vse_ca.cer + * 2) keytool -importcert -file vse_ca.cer -keystore DuveryhodneCertifikaty.keystore -storepass "changeit" + * Pokud daný soubor existuje, program ho používá, pokud ne, používá certifikáty uložené v systému (Javovské). + */ + } + + PostakuvHeslovnik heslovnik = new PostakuvHeslovnik(); + if (nastaveni.getPostovniJmeno() != null && nastaveni.getPostovniJmeno().length() > 0) { + heslovnik.setJmenoHeslo(nastaveni.getPostovniJmeno(), nastaveni.getPostovniHeslo()); + smtpVlastnosti.put("mail.smtp.auth", "true"); + log.log(Level.FINEST, "Používám pro SMTP jméno a heslo"); + } + + Session smtpRelace = Session.getInstance(smtpVlastnosti, heslovnik); + + smtpRelace.setDebug(true); + smtpRelace.setDebugOut(System.out); + + /** Sestavení zprávy */ + MimeMessage mimeZprava = new MimeMessage(smtpRelace); + mimeZprava.setFrom(zprava.getOdesilatel()); + if (zprava.getOdpovedetKomu() != null) { + Address[] odpovedetKomu = {zprava.getOdpovedetKomu()}; + mimeZprava.setReplyTo(odpovedetKomu); + } + naplnPrijemce(mimeZprava, zprava); + mimeZprava.setSubject(zprava.getPredmet()); + mimeZprava.setHeader("User-Agent", "http://frantovo.cz/projekty/SuperPostak/"); + if (zprava.isFormatHTML()) { + mimeZprava.setText(zprava.getText(), "UTF-8", "html"); + } else { + mimeZprava.setText(zprava.getText(), "UTF-8"); + } + + /** Vlastní odeslání */ + Transport.send(mimeZprava); + + } else { + MessagingException e = new MessagingException("Zpráva nebo nastavení jsou nevyhovující"); + log.log(Level.SEVERE, null, e); + throw e; + } + + } + + /** + * Nastaví zprávě (MimeMessage) všechny příjemce, které najde ve zprávě a nastavení. + * Respektuje typy příjemců: komu, kopie, skrytá kopie. + */ + private static void naplnPrijemce(MimeMessage mimeZprava, HromadnaZprava zprava) throws MessagingException { + /** + * Příjemci se budou definovat pouze ve zprávě. + * Z nastavení se brát nebudou (výchozí příjemci už ve zprávě budou). + */ + ArrayList prijemci = zprava.getPrijemci(); + for (InternetAddressKomu komu : prijemci) { + if (zkontrolujAdresu(komu)) { + mimeZprava.addRecipient(komu.getTyp(), komu); + } + } + } + + /** Vypíše do logu seznam příjemců */ + public static void vypisPrijemce(Collection prijemci) { + for (InternetAddressKomu p : prijemci) { + log.log(Level.INFO, p.toString()); + } + } + + /** Veřejná odesílací metoda. + * Postará se o rozdělení zpráv na dílčí (které se vejdou do limitu příjemců) + */ + public void odesli(HromadnaZprava zprava) throws MessagingException { + Collection zpravy = zprava.getDilciZpravy(nastaveni.getLimitZprav()); + + for (HromadnaZprava dilciZprava : zpravy) { + odesliSMTP(dilciZprava); + } + } + + private static boolean zkontrolujAdresu(InternetAddressKomu a) { + if (a.getTyp() == null) { + log.log(Level.WARNING, "Neplatná adresa (typ): " + a.getAddress()); + return false; + } + + if (a.getAddress() == null || a.getAddress().length() < 1) { + log.log(Level.WARNING, "Neplatná adresa (address): " + a.getPersonal()); + return false; + } + + if (!zkontrolujAdresu(a.getAddress())) { + log.log(Level.WARNING, "Adresa nevyhovuje regulárnímu výrazu: " + a.getAddress()); + return false; + } + + return true; + } + + /** Zkontroluje e-mailovou adresu pomocí regulárního výrazu. */ + public static boolean zkontrolujAdresu(String adresa) { + return adresa != null && Pattern.matches(REGULARNI_EMAIL, adresa); + } + + /** @return Vrací true, pokud je zpráva v pořádku */ + private static boolean zkontrolujZpravu(HromadnaZprava z) { + + if (z.getPrijemci() == null) { + log.log(Level.WARNING, "getPrijemci() == null"); + return false; + } + + if (z.getPrijemci().size() < 1) { + log.log(Level.WARNING, "getPrijemci().size() < 1"); + return false; + } + + if (z.getOdesilatel() == null) { + log.log(Level.WARNING, "getOdesilatel() == null"); + return false; + } + + if (z.getPredmet() == null) { + log.log(Level.WARNING, "getPredmet() == null"); + return false; + } + + return true; + } + + private static boolean zkontrolujNastaveni(Nastaveni n) { + + if (n.getPostovniServer() == null || n.getPostovniServer().length() < 1) { + return false; + } + + return true; + } + + /** Slouží k uložení jména a hesla pro SMTP */ + private static class PostakuvHeslovnik extends Authenticator { + + private String jmeno = "user"; + private char[] heslo = "luser".toCharArray(); + + @Override + public PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(jmeno, String.valueOf(heslo)); + } + + public void setJmenoHeslo(String jmeno, char[] heslo) { + this.jmeno = jmeno; + this.heslo = heslo; + } + } +}