root/java/Postak/src/cz/frantovo/postak/Postak.java @ 14:3a12bd9312b1

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

Zprávy budeme posílat s hlavičkou Precedence: bulk

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 final 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: {0}", 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", "https://frantovo.cz/projekty/SuperPostak/");
94            mimeZprava.setHeader("Precedence", "bulk");
95            if (zprava.isFormatHTML()) {
96                mimeZprava.setText(zprava.getText(), "UTF-8", "html");
97            } else {
98                mimeZprava.setText(zprava.getText(), "UTF-8");
99            }
100
101            /** Vlastní odeslání */
102            Transport.send(mimeZprava);
103
104        } else {
105            MessagingException e = new MessagingException("Zpráva nebo nastavení jsou nevyhovující");
106            log.log(Level.SEVERE, null, e);
107            throw e;
108        }
109
110    }
111
112    /**
113     * Nastaví zprávě (MimeMessage) všechny příjemce, které najde ve zprávě a nastavení.
114     * Respektuje typy příjemců: komu, kopie, skrytá kopie.   
115     */
116    private static void naplnPrijemce(MimeMessage mimeZprava, HromadnaZprava zprava) throws MessagingException {
117        /**
118         * Příjemci se budou definovat pouze ve zprávě.
119         * Z nastavení se brát nebudou (výchozí příjemci už ve zprávě budou).
120         */
121        ArrayList<InternetAddressKomu> prijemci = zprava.getPrijemci();
122        for (InternetAddressKomu komu : prijemci) {
123            if (zkontrolujAdresu(komu)) {
124                mimeZprava.addRecipient(komu.getTyp(), komu);
125            }
126        }
127    }
128
129    /** Vypíše do logu seznam příjemců */
130    public static void vypisPrijemce(Collection<InternetAddressKomu> prijemci) {
131        for (InternetAddressKomu p : prijemci) {
132            log.log(Level.INFO, p.toString());
133        }
134    }
135
136    /** Veřejná odesílací metoda.
137     * Postará se o rozdělení zpráv na dílčí (které se vejdou do limitu příjemců)
138     */
139    public void odesli(HromadnaZprava zprava) throws MessagingException {
140        Collection<HromadnaZprava> zpravy = zprava.getDilciZpravy(nastaveni.getLimitZprav());
141
142        for (HromadnaZprava dilciZprava : zpravy) {
143            odesliSMTP(dilciZprava);
144        }
145    }
146
147    private static boolean zkontrolujAdresu(InternetAddressKomu a) {
148        if (a.getTyp() == null) {
149            log.log(Level.WARNING, "Neplatná adresa (typ): {0}", a.getAddress());
150            return false;
151        }
152
153        if (a.getAddress() == null || a.getAddress().length() < 1) {
154            log.log(Level.WARNING, "Neplatná adresa (address): {0}", a.getPersonal());
155            return false;
156        }
157
158        if (!zkontrolujAdresu(a.getAddress())) {
159            log.log(Level.WARNING, "Adresa nevyhovuje regulárnímu výrazu: {0}", a.getAddress());
160            return false;
161        }
162
163        return true;
164    }
165
166    /** Zkontroluje e-mailovou adresu pomocí regulárního výrazu. */
167    public static boolean zkontrolujAdresu(String adresa) {
168        return adresa != null && Pattern.matches(REGULARNI_EMAIL, adresa);
169    }
170
171    /** @return  Vrací true, pokud je zpráva v pořádku */
172    private static boolean zkontrolujZpravu(HromadnaZprava z) {
173
174        if (z.getPrijemci() == null) {
175            log.log(Level.WARNING, "getPrijemci() == null");
176            return false;
177        }
178
179        if (z.getPrijemci().size() < 1) {
180            log.log(Level.WARNING, "getPrijemci().size() < 1");
181            return false;
182        }
183
184        if (z.getOdesilatel() == null) {
185            log.log(Level.WARNING, "getOdesilatel() == null");
186            return false;
187        }
188
189        if (z.getPredmet() == null) {
190            log.log(Level.WARNING, "getPredmet() == null");
191            return false;
192        }
193
194        return true;
195    }
196
197    private static boolean zkontrolujNastaveni(Nastaveni n) {
198
199        if (n.getPostovniServer() == null || n.getPostovniServer().length() < 1) {
200            return false;
201        }
202
203        return true;
204    }
205
206    /** Slouží k uložení jména a hesla pro SMTP */
207    private static class PostakuvHeslovnik extends Authenticator {
208
209        private String jmeno = "user";
210        private char[] heslo = "luser".toCharArray();
211
212        @Override
213        public PasswordAuthentication getPasswordAuthentication() {
214            return new PasswordAuthentication(jmeno, String.valueOf(heslo));
215        }
216
217        public void setJmenoHeslo(String jmeno, char[] heslo) {
218            this.jmeno = jmeno;
219            this.heslo = heslo;
220        }
221    }
222}
Note: See TracBrowser for help on using the browser.