root/java/Postak/src/cz/frantovo/postak/Postak.java @ 5:bea5d9e11d37

Revision 5:bea5d9e11d37, 8.2 KB (checked in by František Kučera <franta-hg@…>, 14 years ago)

Souborové dialogy si pamatují naposledy použitý adresář.

Line 
1package cz.frantovo.postak;
2
3import java.io.File;
4import java.util.ArrayList;
5import java.util.Collection;
6import java.util.Properties;
7import java.util.logging.Level;
8import java.util.logging.Logger;
9import java.util.regex.Pattern;
10import javax.mail.Address;
11import javax.mail.Authenticator;
12import javax.mail.MessagingException;
13import javax.mail.PasswordAuthentication;
14import javax.mail.Session;
15import javax.mail.Transport;
16import javax.mail.internet.MimeMessage;
17
18/**
19 * Odešle hromadnou zprávu pomocí SMTP.
20 *
21 * @author fiki
22 */
23public class Postak {   
24   
25    private static Logger log = Logger.getLogger(Postak.class.getName());
26    /** Regulární výraz pro správnou e-mailovou adresu */
27    private static String REGULARNI_EMAIL = "^[_a-zA-Z0-9\\.\\-]+@[_a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,4}$";
28   
29    private Nastaveni nastaveni;
30
31    public Postak(Nastaveni nastaveni) {
32        this.nastaveni = nastaveni;
33    }
34
35    public void setNastaveni(Nastaveni nastaveni) {
36        this.nastaveni = nastaveni;
37    }
38
39    /**
40     * Nízkoúrovňová odesílací metoda, která už nekontroluje limit příjemců.
41     * Pokud se nevejdou do limitu SMTP serveru, vyhazuje výjimku.
42     *
43     * TODO: lepší to bude nestaické - nastavení si vyžádat v konstruktoru
44     */
45    private void odesliSMTP(HromadnaZprava zprava) throws MessagingException {
46
47        if (zkontrolujZpravu(zprava) && zkontrolujNastaveni(nastaveni)) {
48
49            /** Inicializace SMTP */
50            Properties smtpVlastnosti = System.getProperties();
51            smtpVlastnosti.put("mail.smtp.host", nastaveni.getPostovniServer());
52            smtpVlastnosti.put("mail.smtp.port", String.valueOf(nastaveni.getPostovniPort()));
53
54            if (nastaveni.getPostovniPort() == 465) {
55                if (new File(nastaveni.getCestaKCertifikatum()).exists()) {
56                    System.setProperty("javax.net.ssl.trustStore", nastaveni.getCestaKCertifikatum());
57                    log.log(Level.INFO, "Používám vlastní důvěryhodné certifikáty: " + nastaveni.getCestaKCertifikatum());
58                }
59                /** TODO: neřídit se číslem portu, ale přidat příznak pro šifrování */
60                smtpVlastnosti.put("mail.smtp.starttls.enable", "true");
61                smtpVlastnosti.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
62                smtpVlastnosti.put("mail.smtp.socketFactory.port", String.valueOf(nastaveni.getPostovniPort()));
63                smtpVlastnosti.put("mail.smtp.socketFactory.fallback", "false");
64            /**
65             * NAHRÁNÍ CERTIFIKÁTU:
66             * 1) stáhneme si certifikát (---BEGIN CERTIFICATE---) a uložíme do vse_ca.cer             
67             * 2) keytool -importcert -file vse_ca.cer -keystore DuveryhodneCertifikaty.keystore -storepass "changeit"
68             * Pokud daný soubor existuje, program ho používá, pokud ne, používá certifikáty uložené v systému (Javovské).
69             */
70            }
71
72            PostakuvHeslovnik heslovnik = new PostakuvHeslovnik();
73            if (nastaveni.getPostovniJmeno() != null && nastaveni.getPostovniJmeno().length() > 0) {
74                heslovnik.setJmenoHeslo(nastaveni.getPostovniJmeno(), nastaveni.getPostovniHeslo());
75                smtpVlastnosti.put("mail.smtp.auth", "true");
76                log.log(Level.FINEST, "Používám pro SMTP jméno a heslo");
77            }
78
79            Session smtpRelace = Session.getInstance(smtpVlastnosti, heslovnik);
80
81            smtpRelace.setDebug(true);
82            smtpRelace.setDebugOut(System.out);
83
84            /** Sestavení zprávy */
85            MimeMessage mimeZprava = new MimeMessage(smtpRelace);
86            mimeZprava.setFrom(zprava.getOdesilatel());
87            if (zprava.getOdpovedetKomu() != null) {
88                Address[] odpovedetKomu = {zprava.getOdpovedetKomu()};
89                mimeZprava.setReplyTo(odpovedetKomu);
90            }
91            naplnPrijemce(mimeZprava, zprava);
92            mimeZprava.setSubject(zprava.getPredmet());
93            mimeZprava.setHeader("User-Agent", "http://frantovo.cz/projekty/SuperPostak/ | https://posta.veverka.ch/posta/");
94            if (zprava.isFormatHTML()) {
95                mimeZprava.setText(zprava.getText(), "UTF-8", "html");
96            } else {
97                mimeZprava.setText(zprava.getText(), "UTF-8");
98            }
99
100            /** Vlastní odeslání */
101            Transport.send(mimeZprava);
102
103        } else {
104            MessagingException e = new MessagingException("Zpráva nebo nastavení jsou nevyhovující");
105            log.log(Level.SEVERE, null, e);
106            throw e;
107        }
108
109    }
110
111    /**
112     * Nastaví zprávě (MimeMessage) všechny příjemce, které najde ve zprávě a nastavení.
113     * Respektuje typy příjemců: komu, kopie, skrytá kopie.   
114     */
115    private static void naplnPrijemce(MimeMessage mimeZprava, HromadnaZprava zprava) throws MessagingException {
116        /**
117         * Příjemci se budou definovat pouze ve zprávě.
118         * Z nastavení se brát nebudou (výchozí příjemci už ve zprávě budou).
119         */
120        ArrayList<InternetAddressKomu> prijemci = zprava.getPrijemci();
121        for (InternetAddressKomu komu : prijemci) {
122            if (zkontrolujAdresu(komu)) {
123                mimeZprava.addRecipient(komu.getTyp(), komu);
124            }
125        }
126    }
127
128    /** Vypíše do logu seznam příjemců */
129    public static void vypisPrijemce(Collection<InternetAddressKomu> prijemci) {
130        for (InternetAddressKomu p : prijemci) {
131            log.log(Level.INFO, p.toString());
132        }
133    }
134
135    /** Veřejná odesílací metoda.
136     * Postará se o rozdělení zpráv na dílčí (které se vejdou do limitu příjemců)
137     */
138    public void odesli(HromadnaZprava zprava) throws MessagingException {
139        Collection<HromadnaZprava> zpravy = zprava.getDilciZpravy(nastaveni.getLimitZprav());
140
141        for (HromadnaZprava dilciZprava : zpravy) {
142            odesliSMTP(dilciZprava);
143        }
144    }
145
146    private static boolean zkontrolujAdresu(InternetAddressKomu a) {
147        if (a.getTyp() == null) {
148            log.log(Level.WARNING, "Neplatná adresa (typ): " + a.getAddress());
149            return false;
150        }
151
152        if (a.getAddress() == null || a.getAddress().length() < 1) {
153            log.log(Level.WARNING, "Neplatná adresa (address): " + a.getPersonal());
154            return false;
155        }
156
157        if (!zkontrolujAdresu(a.getAddress())) {
158            log.log(Level.WARNING, "Adresa nevyhovuje regulárnímu výrazu: " + a.getAddress());
159            return false;
160        }
161
162        return true;
163    }
164
165    /** Zkontroluje e-mailovou adresu pomocí regulárního výrazu. */
166    public static boolean zkontrolujAdresu(String adresa) {
167        return adresa != null && Pattern.matches(REGULARNI_EMAIL, adresa);
168    }
169
170    /** @return  Vrací true, pokud je zpráva v pořádku */
171    private static boolean zkontrolujZpravu(HromadnaZprava z) {
172
173        if (z.getPrijemci() == null) {
174            log.log(Level.WARNING, "getPrijemci() == null");
175            return false;
176        }
177
178        if (z.getPrijemci().size() < 1) {
179            log.log(Level.WARNING, "getPrijemci().size() < 1");
180            return false;
181        }
182
183        if (z.getOdesilatel() == null) {
184            log.log(Level.WARNING, "getOdesilatel() == null");
185            return false;
186        }
187
188        if (z.getPredmet() == null) {
189            log.log(Level.WARNING, "getPredmet() == null");
190            return false;
191        }
192
193        return true;
194    }
195
196    private static boolean zkontrolujNastaveni(Nastaveni n) {
197
198        if (n.getPostovniServer() == null || n.getPostovniServer().length() < 1) {
199            return false;
200        }
201
202        return true;
203    }
204
205    /** Slouží k uložení jména a hesla pro SMTP */
206    private static class PostakuvHeslovnik extends Authenticator {
207
208        private String jmeno = "user";
209        private char[] heslo = "luser".toCharArray();
210
211        @Override
212        public PasswordAuthentication getPasswordAuthentication() {
213            return new PasswordAuthentication(jmeno, String.valueOf(heslo));
214        }
215
216        public void setJmenoHeslo(String jmeno, char[] heslo) {
217            this.jmeno = jmeno;
218            this.heslo = heslo;
219        }
220    }
221}
Note: See TracBrowser for help on using the browser.