Doplňování jména a adresy odesílatele na základě hodnot „odpovědět komu“ (přidáme noreply).
1 package cz.frantovo.postak;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Properties;
7 import java.util.logging.Level;
8 import java.util.logging.Logger;
9 import java.util.regex.Pattern;
10 import javax.mail.Address;
11 import javax.mail.Authenticator;
12 import javax.mail.MessagingException;
13 import javax.mail.PasswordAuthentication;
14 import javax.mail.Session;
15 import javax.mail.Transport;
16 import javax.mail.internet.MimeMessage;
19 * Odešle hromadnou zprávu pomocí SMTP.
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}$";
29 private Nastaveni nastaveni;
31 public Postak(Nastaveni nastaveni) {
32 this.nastaveni = nastaveni;
35 public void setNastaveni(Nastaveni nastaveni) {
36 this.nastaveni = nastaveni;
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.
43 * TODO: lepší to bude nestaické - nastavení si vyžádat v konstruktoru
45 private void odesliSMTP(HromadnaZprava zprava) throws MessagingException {
47 if (zkontrolujZpravu(zprava) && zkontrolujNastaveni(nastaveni)) {
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()));
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());
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");
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é).
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");
79 Session smtpRelace = Session.getInstance(smtpVlastnosti, heslovnik);
81 smtpRelace.setDebug(true);
82 smtpRelace.setDebugOut(System.out);
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);
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");
98 mimeZprava.setText(zprava.getText(), "UTF-8");
101 /** Vlastní odeslání */
102 Transport.send(mimeZprava);
105 MessagingException e = new MessagingException("Zpráva nebo nastavení jsou nevyhovující");
106 log.log(Level.SEVERE, null, e);
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.
116 private static void naplnPrijemce(MimeMessage mimeZprava, HromadnaZprava zprava) throws MessagingException {
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).
121 ArrayList<InternetAddressKomu> prijemci = zprava.getPrijemci();
122 for (InternetAddressKomu komu : prijemci) {
123 if (zkontrolujAdresu(komu)) {
124 mimeZprava.addRecipient(komu.getTyp(), komu);
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());
136 /** Veřejná odesílací metoda.
137 * Postará se o rozdělení zpráv na dílčí (které se vejdou do limitu příjemců)
139 public void odesli(HromadnaZprava zprava) throws MessagingException {
140 Collection<HromadnaZprava> zpravy = zprava.getDilciZpravy(nastaveni.getLimitZprav());
142 for (HromadnaZprava dilciZprava : zpravy) {
143 odesliSMTP(dilciZprava);
147 private static boolean zkontrolujAdresu(InternetAddressKomu a) {
148 if (a.getTyp() == null) {
149 log.log(Level.WARNING, "Neplatná adresa (typ): {0}", a.getAddress());
153 if (a.getAddress() == null || a.getAddress().length() < 1) {
154 log.log(Level.WARNING, "Neplatná adresa (address): {0}", a.getPersonal());
158 if (!zkontrolujAdresu(a.getAddress())) {
159 log.log(Level.WARNING, "Adresa nevyhovuje regulárnímu výrazu: {0}", a.getAddress());
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);
171 /** @return Vrací true, pokud je zpráva v pořádku */
172 private static boolean zkontrolujZpravu(HromadnaZprava z) {
174 if (z.getPrijemci() == null) {
175 log.log(Level.WARNING, "getPrijemci() == null");
179 if (z.getPrijemci().size() < 1) {
180 log.log(Level.WARNING, "getPrijemci().size() < 1");
184 if (z.getOdesilatel() == null) {
185 log.log(Level.WARNING, "getOdesilatel() == null");
189 if (z.getPredmet() == null) {
190 log.log(Level.WARNING, "getPredmet() == null");
197 private static boolean zkontrolujNastaveni(Nastaveni n) {
199 if (n.getPostovniServer() == null || n.getPostovniServer().length() < 1) {
206 /** Slouží k uložení jména a hesla pro SMTP */
207 private static class PostakuvHeslovnik extends Authenticator {
209 private String jmeno = "user";
210 private char[] heslo = "luser".toCharArray();
213 public PasswordAuthentication getPasswordAuthentication() {
214 return new PasswordAuthentication(jmeno, String.valueOf(heslo));
217 public void setJmenoHeslo(String jmeno, char[] heslo) {