#4 multipart/alternative zprávy: XHTML + prostý text (generuje se pomocí XSLT) v1.1
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 23 Apr 2012 00:24:31 +0200
changeset 179cb46ca7e26c
parent 16 290074b53aca
child 18 4f42075aada1
#4 multipart/alternative zprávy: XHTML + prostý text (generuje se pomocí XSLT)
java/Postak/src/cz/frantovo/postak/HromadnaZprava.java
java/Postak/src/cz/frantovo/postak/Postak.java
java/Postak/src/cz/frantovo/postak/odchozíEmailText.xsl
java/SuperPostak/src/cz/frantovo/superPostak/SuperPostak.form
java/SuperPostak/src/cz/frantovo/superPostak/SuperPostak.java
     1.1 --- a/java/Postak/src/cz/frantovo/postak/HromadnaZprava.java	Fri Mar 30 15:35:26 2012 +0200
     1.2 +++ b/java/Postak/src/cz/frantovo/postak/HromadnaZprava.java	Mon Apr 23 00:24:31 2012 +0200
     1.3 @@ -9,130 +9,138 @@
     1.4  /**
     1.5   * Hromadná zpráva. Umí se rozdělit i na více dílčích zpráv,
     1.6   * které se vejdou do limitu příjemců SMTP serveru.
     1.7 + *
     1.8   * @author fiki
     1.9   */
    1.10  public class HromadnaZprava implements Cloneable {
    1.11  
    1.12 -    private static final Logger log = Logger.getLogger(HromadnaZprava.class.getName());
    1.13 -    /** Předmět zprávy */
    1.14 -    private String predmet;
    1.15 -    /** Adresa a případně jméno odesílatele */
    1.16 -    private InternetAddress odesilatel;
    1.17 -    /** Zda má být zpráva odeslána jako HTML nebo prostý text */
    1.18 -    private boolean formatHTML = false;
    1.19 -    /** Tělo zprávy - prostý text */
    1.20 -    private String text;
    1.21 -    /** Všichni příjemci této zprávy */
    1.22 -    private ArrayList<InternetAddressKomu> prijemci = new ArrayList<InternetAddressKomu>();
    1.23 -    /** Hlavička Reply-to */
    1.24 -    private InternetAddress odpovedetKomu;
    1.25 +	public enum FORMÁT {
    1.26  
    1.27 -    public String getPredmet() {
    1.28 -        return predmet;
    1.29 -    }
    1.30 +		XHTML,
    1.31 +		PROSTÝ_TEXT,
    1.32 +		OBOJE
    1.33 +	}
    1.34 +	private static final Logger log = Logger.getLogger(HromadnaZprava.class.getName());
    1.35 +	/** Předmět zprávy */
    1.36 +	private String predmet;
    1.37 +	/** Adresa a případně jméno odesílatele */
    1.38 +	private InternetAddress odesilatel;
    1.39 +	/** Zda má být zpráva odeslána jako HTML nebo prostý text */
    1.40 +	private FORMÁT formát = FORMÁT.PROSTÝ_TEXT;
    1.41 +	/** Tělo zprávy - prostý text */
    1.42 +	private String text;
    1.43 +	/** Všichni příjemci této zprávy */
    1.44 +	private ArrayList<InternetAddressKomu> prijemci = new ArrayList<InternetAddressKomu>();
    1.45 +	/** Hlavička Reply-to */
    1.46 +	private InternetAddress odpovedetKomu;
    1.47  
    1.48 -    public void setPredmet(String predmet) {
    1.49 -        this.predmet = predmet;
    1.50 -    }
    1.51 +	public String getPredmet() {
    1.52 +		return predmet;
    1.53 +	}
    1.54  
    1.55 -    public InternetAddress getOdesilatel() {
    1.56 -        return odesilatel;
    1.57 -    }
    1.58 +	public void setPredmet(String predmet) {
    1.59 +		this.predmet = predmet;
    1.60 +	}
    1.61  
    1.62 -    public void setOdesilatel(InternetAddress odesilatel) {
    1.63 -        this.odesilatel = odesilatel;
    1.64 -    }
    1.65 +	public InternetAddress getOdesilatel() {
    1.66 +		return odesilatel;
    1.67 +	}
    1.68  
    1.69 -    public String getText() {
    1.70 -        return text;
    1.71 -    }
    1.72 +	public void setOdesilatel(InternetAddress odesilatel) {
    1.73 +		this.odesilatel = odesilatel;
    1.74 +	}
    1.75  
    1.76 -    public void setText(String text) {
    1.77 -        this.text = text;
    1.78 -    }
    1.79 +	public String getText() {
    1.80 +		return text;
    1.81 +	}
    1.82  
    1.83 -    public ArrayList<InternetAddressKomu> getPrijemci() {
    1.84 -        return prijemci;
    1.85 -    }
    1.86 +	public void setText(String text) {
    1.87 +		this.text = text;
    1.88 +	}
    1.89  
    1.90 -    /** 
    1.91 -     * @param prijemci pokud je null, nastaví prázdná kolekce.
    1.92 -     */
    1.93 -    public void setPrijemci(ArrayList<InternetAddressKomu> prijemci) {
    1.94 -        this.prijemci = new ArrayList<InternetAddressKomu>();
    1.95 -        pridejPrijemce(prijemci);
    1.96 -    }
    1.97 +	public ArrayList<InternetAddressKomu> getPrijemci() {
    1.98 +		return prijemci;
    1.99 +	}
   1.100  
   1.101 -    public void pridejPrijemce(Collection<InternetAddressKomu> prijemci) {
   1.102 -        if (prijemci == null) {
   1.103 -            log.log(Level.FINER, "Prázdná množina příjemců – nic nepřidáme");
   1.104 -        } else {
   1.105 -            this.prijemci.addAll(prijemci);
   1.106 -        }
   1.107 -    }
   1.108 +	/**
   1.109 +	 * @param prijemci pokud je null, nastaví prázdná kolekce.
   1.110 +	 */
   1.111 +	public void setPrijemci(ArrayList<InternetAddressKomu> prijemci) {
   1.112 +		this.prijemci = new ArrayList<InternetAddressKomu>();
   1.113 +		pridejPrijemce(prijemci);
   1.114 +	}
   1.115  
   1.116 -    /**
   1.117 -     * Pokud má zpráva více přijemců, než je limit povolený SMTP serverem,
   1.118 -     * rozdělí se zpráva na více dílčích zpráv.
   1.119 -     * @param limit maximální počet příjemců jedné zprávy (omezení SMTP serveru)
   1.120 -     */
   1.121 -    public Collection<HromadnaZprava> getDilciZpravy(int limit) {
   1.122 -        Collection<HromadnaZprava> zpravy = new ArrayList<HromadnaZprava>();
   1.123 +	public void pridejPrijemce(Collection<InternetAddressKomu> prijemci) {
   1.124 +		if (prijemci == null) {
   1.125 +			log.log(Level.FINER, "Prázdná množina příjemců – nic nepřidáme");
   1.126 +		} else {
   1.127 +			this.prijemci.addAll(prijemci);
   1.128 +		}
   1.129 +	}
   1.130  
   1.131 -        if (limit < getPrijemci().size()) {
   1.132 -            /** Zprávu je potřeba rozdělit */
   1.133 -            try {
   1.134 -                HromadnaZprava dilciZprava = (HromadnaZprava) clone();
   1.135 -                dilciZprava.setPrijemci(null);
   1.136 +	/**
   1.137 +	 * Pokud má zpráva více přijemců, než je limit povolený SMTP serverem,
   1.138 +	 * rozdělí se zpráva na více dílčích zpráv.
   1.139 +	 *
   1.140 +	 * @param limit maximální počet příjemců jedné zprávy (omezení SMTP serveru)
   1.141 +	 */
   1.142 +	public Collection<HromadnaZprava> getDilciZpravy(int limit) {
   1.143 +		Collection<HromadnaZprava> zpravy = new ArrayList<HromadnaZprava>();
   1.144  
   1.145 -                ArrayList<InternetAddressKomu> vsichniPrijemci = getPrijemci();
   1.146 -                for (InternetAddressKomu prijemce : vsichniPrijemci) {
   1.147 -                    dilciZprava.getPrijemci().add(prijemce);
   1.148 +		if (limit < getPrijemci().size()) {
   1.149 +			/** Zprávu je potřeba rozdělit */
   1.150 +			try {
   1.151 +				HromadnaZprava dilciZprava = (HromadnaZprava) clone();
   1.152 +				dilciZprava.setPrijemci(null);
   1.153  
   1.154 -                    if (dilciZprava.getPrijemci().size() == limit) {
   1.155 -                        zpravy.add(dilciZprava);
   1.156 -                        dilciZprava = (HromadnaZprava) clone();
   1.157 -                        dilciZprava.setPrijemci(null);
   1.158 -                    }
   1.159 -                }
   1.160 +				ArrayList<InternetAddressKomu> vsichniPrijemci = getPrijemci();
   1.161 +				for (InternetAddressKomu prijemce : vsichniPrijemci) {
   1.162 +					dilciZprava.getPrijemci().add(prijemce);
   1.163  
   1.164 -                if (dilciZprava.getPrijemci().size() > 0) {
   1.165 -                    /**
   1.166 -                     * Počet příjemců není násobkem limitu,
   1.167 -                     * takže nakonci ještě někteří zbyli.
   1.168 -                     * Z nich budou příjemci pro poslední dílčí zprávu.
   1.169 -                     */
   1.170 -                    zpravy.add(dilciZprava);
   1.171 -                }
   1.172 +					if (dilciZprava.getPrijemci().size() == limit) {
   1.173 +						zpravy.add(dilciZprava);
   1.174 +						dilciZprava = (HromadnaZprava) clone();
   1.175 +						dilciZprava.setPrijemci(null);
   1.176 +					}
   1.177 +				}
   1.178  
   1.179 +				if (dilciZprava.getPrijemci().size() > 0) {
   1.180 +					/**
   1.181 +					 * Počet příjemců není násobkem limitu,
   1.182 +					 * takže nakonci ještě někteří zbyli.
   1.183 +					 * Z nich budou příjemci pro poslední dílčí zprávu.
   1.184 +					 */
   1.185 +					zpravy.add(dilciZprava);
   1.186 +				}
   1.187  
   1.188 -            } catch (CloneNotSupportedException ex) {
   1.189 -                /** Tohle by nikdy nemělo nastat */
   1.190 -                log.log(Level.SEVERE, "Hromandou zprávu se nepodařilo naklonovat - divné.", ex);
   1.191 -                zpravy.add(this);
   1.192 -            }
   1.193 -        } else {
   1.194 -            /** Zprávu má málo příjemců - můžeme ji odeslat najednou */
   1.195 -            zpravy.add(this);
   1.196 -        }
   1.197  
   1.198 -        return zpravy;
   1.199 -    }
   1.200 +			} catch (CloneNotSupportedException ex) {
   1.201 +				/** Tohle by nikdy nemělo nastat */
   1.202 +				log.log(Level.SEVERE, "Hromandou zprávu se nepodařilo naklonovat - divné.", ex);
   1.203 +				zpravy.add(this);
   1.204 +			}
   1.205 +		} else {
   1.206 +			/** Zprávu má málo příjemců - můžeme ji odeslat najednou */
   1.207 +			zpravy.add(this);
   1.208 +		}
   1.209  
   1.210 -    public boolean isFormatHTML() {
   1.211 -        return formatHTML;
   1.212 -    }
   1.213 +		return zpravy;
   1.214 +	}
   1.215  
   1.216 -    public void setFormatHTML(boolean formatHTML) {
   1.217 -        this.formatHTML = formatHTML;
   1.218 -    }
   1.219 +	public FORMÁT getFormát() {
   1.220 +		return formát;
   1.221 +	}
   1.222  
   1.223 -    public InternetAddress getOdpovedetKomu() {
   1.224 -        return odpovedetKomu;
   1.225 -    }
   1.226 +	public void setFormatHTML(FORMÁT formát) {
   1.227 +		this.formát = formát;
   1.228 +	}
   1.229  
   1.230 -    /** Pokud je null, hlavička Reply-to se v e-mailu vůbec nenastaví. */
   1.231 -    public void setOdpovedetKomu(InternetAddress odpovedetKomu) {
   1.232 -        this.odpovedetKomu = odpovedetKomu;
   1.233 -    }
   1.234 +	public InternetAddress getOdpovedetKomu() {
   1.235 +		return odpovedetKomu;
   1.236 +	}
   1.237 +
   1.238 +	/** Pokud je null, hlavička Reply-to se v e-mailu vůbec nenastaví. */
   1.239 +	public void setOdpovedetKomu(InternetAddress odpovedetKomu) {
   1.240 +		this.odpovedetKomu = odpovedetKomu;
   1.241 +	}
   1.242  }
     2.1 --- a/java/Postak/src/cz/frantovo/postak/Postak.java	Fri Mar 30 15:35:26 2012 +0200
     2.2 +++ b/java/Postak/src/cz/frantovo/postak/Postak.java	Mon Apr 23 00:24:31 2012 +0200
     2.3 @@ -1,6 +1,8 @@
     2.4  package cz.frantovo.postak;
     2.5  
     2.6  import java.io.File;
     2.7 +import java.io.StringReader;
     2.8 +import java.io.StringWriter;
     2.9  import java.util.ArrayList;
    2.10  import java.util.Collection;
    2.11  import java.util.Properties;
    2.12 @@ -13,210 +15,251 @@
    2.13  import javax.mail.PasswordAuthentication;
    2.14  import javax.mail.Session;
    2.15  import javax.mail.Transport;
    2.16 +import javax.mail.internet.MimeBodyPart;
    2.17  import javax.mail.internet.MimeMessage;
    2.18 +import javax.mail.internet.MimeMultipart;
    2.19 +import javax.xml.transform.Transformer;
    2.20 +import javax.xml.transform.TransformerFactory;
    2.21 +import javax.xml.transform.stream.StreamResult;
    2.22 +import javax.xml.transform.stream.StreamSource;
    2.23  
    2.24  /**
    2.25   * Odešle hromadnou zprávu pomocí SMTP.
    2.26 - * 
    2.27 + *
    2.28   * @author fiki
    2.29   */
    2.30 -public class Postak {   
    2.31 -    
    2.32 -    private static final Logger log = Logger.getLogger(Postak.class.getName());
    2.33 -    /** Regulární výraz pro správnou e-mailovou adresu */
    2.34 -    private static String REGULARNI_EMAIL = "^[_a-zA-Z0-9\\.\\-]+@[_a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,4}$";
    2.35 -    
    2.36 -    private Nastaveni nastaveni;
    2.37 +public class Postak {
    2.38  
    2.39 -    public Postak(Nastaveni nastaveni) {
    2.40 -        this.nastaveni = nastaveni;
    2.41 -    }
    2.42 +	private static final String KÓDOVÁNÍ = "UTF-8";
    2.43 +	private static final Logger log = Logger.getLogger(Postak.class.getName());
    2.44 +	/** Regulární výraz pro správnou e-mailovou adresu */
    2.45 +	private static String REGULARNI_EMAIL = "^[_a-zA-Z0-9\\.\\-]+@[_a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,4}$";
    2.46 +	private Nastaveni nastaveni;
    2.47 +	private TransformerFactory transformerFactory;
    2.48  
    2.49 -    public void setNastaveni(Nastaveni nastaveni) {
    2.50 -        this.nastaveni = nastaveni;
    2.51 -    }
    2.52 +	public Postak(Nastaveni nastaveni) {
    2.53 +		this.nastaveni = nastaveni;
    2.54 +		transformerFactory = TransformerFactory.newInstance();
    2.55 +	}
    2.56  
    2.57 -    /** 
    2.58 -     * Nízkoúrovňová odesílací metoda, která už nekontroluje limit příjemců.
    2.59 -     * Pokud se nevejdou do limitu SMTP serveru, vyhazuje výjimku.
    2.60 -     * 
    2.61 -     * TODO: lepší to bude nestaické - nastavení si vyžádat v konstruktoru
    2.62 -     */
    2.63 -    private void odesliSMTP(HromadnaZprava zprava) throws MessagingException {
    2.64 +	public void setNastaveni(Nastaveni nastaveni) {
    2.65 +		this.nastaveni = nastaveni;
    2.66 +	}
    2.67  
    2.68 -        if (zkontrolujZpravu(zprava) && zkontrolujNastaveni(nastaveni)) {
    2.69 +	/**
    2.70 +	 * Nízkoúrovňová odesílací metoda, která už nekontroluje limit příjemců.
    2.71 +	 * Pokud se nevejdou do limitu SMTP serveru, vyhazuje výjimku.
    2.72 +	 *
    2.73 +	 * TODO: lepší to bude nestaické - nastavení si vyžádat v konstruktoru
    2.74 +	 */
    2.75 +	private void odesliSMTP(HromadnaZprava zprava) throws MessagingException {
    2.76  
    2.77 -            /** Inicializace SMTP */
    2.78 -            Properties smtpVlastnosti = System.getProperties();
    2.79 -            smtpVlastnosti.put("mail.smtp.host", nastaveni.getPostovniServer());
    2.80 -            smtpVlastnosti.put("mail.smtp.port", String.valueOf(nastaveni.getPostovniPort()));
    2.81 +		if (zkontrolujZpravu(zprava) && zkontrolujNastaveni(nastaveni)) {
    2.82  
    2.83 -            if (nastaveni.getPostovniPort() == 465) {
    2.84 -                if (new File(nastaveni.getCestaKCertifikatum()).exists()) {
    2.85 -                    System.setProperty("javax.net.ssl.trustStore", nastaveni.getCestaKCertifikatum());
    2.86 -                    log.log(Level.INFO, "Používám vlastní důvěryhodné certifikáty: {0}", nastaveni.getCestaKCertifikatum());
    2.87 -                }
    2.88 -                /** TODO: neřídit se číslem portu, ale přidat příznak pro šifrování */
    2.89 -                smtpVlastnosti.put("mail.smtp.starttls.enable", "true");
    2.90 -                smtpVlastnosti.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    2.91 -                smtpVlastnosti.put("mail.smtp.socketFactory.port", String.valueOf(nastaveni.getPostovniPort()));
    2.92 -                smtpVlastnosti.put("mail.smtp.socketFactory.fallback", "false");
    2.93 -            /**
    2.94 -             * NAHRÁNÍ CERTIFIKÁTU:
    2.95 -             * 1) stáhneme si certifikát (---BEGIN CERTIFICATE---) a uložíme do vse_ca.cer             
    2.96 -             * 2) keytool -importcert -file vse_ca.cer -keystore DuveryhodneCertifikaty.keystore -storepass "changeit"
    2.97 -             * Pokud daný soubor existuje, program ho používá, pokud ne, používá certifikáty uložené v systému (Javovské).
    2.98 -             */
    2.99 -            }
   2.100 +			/** Inicializace SMTP */
   2.101 +			Properties smtpVlastnosti = System.getProperties();
   2.102 +			smtpVlastnosti.put("mail.smtp.host", nastaveni.getPostovniServer());
   2.103 +			smtpVlastnosti.put("mail.smtp.port", String.valueOf(nastaveni.getPostovniPort()));
   2.104  
   2.105 -            PostakuvHeslovnik heslovnik = new PostakuvHeslovnik();
   2.106 -            if (nastaveni.getPostovniJmeno() != null && nastaveni.getPostovniJmeno().length() > 0) {
   2.107 -                heslovnik.setJmenoHeslo(nastaveni.getPostovniJmeno(), nastaveni.getPostovniHeslo());
   2.108 -                smtpVlastnosti.put("mail.smtp.auth", "true");
   2.109 -                log.log(Level.FINEST, "Používám pro SMTP jméno a heslo");
   2.110 -            }
   2.111 +			if (nastaveni.getPostovniPort() == 465) {
   2.112 +				if (new File(nastaveni.getCestaKCertifikatum()).exists()) {
   2.113 +					System.setProperty("javax.net.ssl.trustStore", nastaveni.getCestaKCertifikatum());
   2.114 +					log.log(Level.INFO, "Používám vlastní důvěryhodné certifikáty: {0}", nastaveni.getCestaKCertifikatum());
   2.115 +				}
   2.116 +				/** TODO: neřídit se číslem portu, ale přidat příznak pro šifrování */
   2.117 +				smtpVlastnosti.put("mail.smtp.starttls.enable", "true");
   2.118 +				smtpVlastnosti.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
   2.119 +				smtpVlastnosti.put("mail.smtp.socketFactory.port", String.valueOf(nastaveni.getPostovniPort()));
   2.120 +				smtpVlastnosti.put("mail.smtp.socketFactory.fallback", "false");
   2.121 +				/**
   2.122 +				 * NAHRÁNÍ CERTIFIKÁTU:
   2.123 +				 * 1) stáhneme si certifikát (---BEGIN CERTIFICATE---) a uložíme do vse_ca.cer
   2.124 +				 * 2) keytool -importcert -file vse_ca.cer -keystore DuveryhodneCertifikaty.keystore
   2.125 +				 * -storepass "changeit"
   2.126 +				 * Pokud daný soubor existuje, program ho používá, pokud ne, používá certifikáty
   2.127 +				 * uložené v systému (Javovské).
   2.128 +				 */
   2.129 +			}
   2.130  
   2.131 -            Session smtpRelace = Session.getInstance(smtpVlastnosti, heslovnik);
   2.132 +			PostakuvHeslovnik heslovnik = new PostakuvHeslovnik();
   2.133 +			if (nastaveni.getPostovniJmeno() != null && nastaveni.getPostovniJmeno().length() > 0) {
   2.134 +				heslovnik.setJmenoHeslo(nastaveni.getPostovniJmeno(), nastaveni.getPostovniHeslo());
   2.135 +				smtpVlastnosti.put("mail.smtp.auth", "true");
   2.136 +				log.log(Level.FINEST, "Používám pro SMTP jméno a heslo");
   2.137 +			}
   2.138  
   2.139 -            smtpRelace.setDebug(true);
   2.140 -            smtpRelace.setDebugOut(System.out);
   2.141 +			Session smtpRelace = Session.getInstance(smtpVlastnosti, heslovnik);
   2.142  
   2.143 -            /** Sestavení zprávy */
   2.144 -            MimeMessage mimeZprava = new MimeMessage(smtpRelace);
   2.145 -            mimeZprava.setFrom(zprava.getOdesilatel());
   2.146 -            if (zprava.getOdpovedetKomu() != null) {
   2.147 -                Address[] odpovedetKomu = {zprava.getOdpovedetKomu()};
   2.148 -                mimeZprava.setReplyTo(odpovedetKomu);
   2.149 -            }
   2.150 -            naplnPrijemce(mimeZprava, zprava);
   2.151 -            mimeZprava.setSubject(zprava.getPredmet());
   2.152 -            mimeZprava.setHeader("User-Agent", "https://frantovo.cz/projekty/SuperPostak/");
   2.153 -            mimeZprava.setHeader("Precedence", "bulk");
   2.154 -            if (zprava.isFormatHTML()) {
   2.155 -                mimeZprava.setText(zprava.getText(), "UTF-8", "html");
   2.156 -            } else {
   2.157 -                mimeZprava.setText(zprava.getText(), "UTF-8");
   2.158 -            }
   2.159 +			smtpRelace.setDebug(true);
   2.160 +			smtpRelace.setDebugOut(System.out);
   2.161  
   2.162 -            /** Vlastní odeslání */
   2.163 -            Transport.send(mimeZprava);
   2.164 +			/** Sestavení zprávy */
   2.165 +			MimeMessage mimeZprava = new MimeMessage(smtpRelace);
   2.166 +			mimeZprava.setFrom(zprava.getOdesilatel());
   2.167 +			if (zprava.getOdpovedetKomu() != null) {
   2.168 +				Address[] odpovedetKomu = {zprava.getOdpovedetKomu()};
   2.169 +				mimeZprava.setReplyTo(odpovedetKomu);
   2.170 +			}
   2.171 +			naplnPrijemce(mimeZprava, zprava);
   2.172 +			mimeZprava.setSubject(zprava.getPredmet());
   2.173 +			mimeZprava.setHeader("User-Agent", "https://frantovo.cz/projekty/SuperPostak/");
   2.174 +			mimeZprava.setHeader("Precedence", "bulk");
   2.175  
   2.176 -        } else {
   2.177 -            MessagingException e = new MessagingException("Zpráva nebo nastavení jsou nevyhovující");
   2.178 -            log.log(Level.SEVERE, null, e);
   2.179 -            throw e;
   2.180 -        }
   2.181 +			switch (zprava.getFormát()) {
   2.182 +				case PROSTÝ_TEXT:
   2.183 +					mimeZprava.setText(zprava.getText(), KÓDOVÁNÍ);
   2.184 +					break;
   2.185 +				case XHTML:
   2.186 +					mimeZprava.setText(zprava.getText(), KÓDOVÁNÍ, "html");
   2.187 +					break;
   2.188 +				case OBOJE:
   2.189 +					MimeMultipart multipart = new MimeMultipart("alternative");
   2.190 +					mimeZprava.setContent(multipart);
   2.191  
   2.192 -    }
   2.193 +					MimeBodyPart textováČást = new MimeBodyPart();
   2.194 +					MimeBodyPart xhtmlČást = new MimeBodyPart();
   2.195  
   2.196 -    /**
   2.197 -     * Nastaví zprávě (MimeMessage) všechny příjemce, které najde ve zprávě a nastavení.
   2.198 -     * Respektuje typy příjemců: komu, kopie, skrytá kopie.    
   2.199 -     */
   2.200 -    private static void naplnPrijemce(MimeMessage mimeZprava, HromadnaZprava zprava) throws MessagingException {
   2.201 -        /** 
   2.202 -         * Příjemci se budou definovat pouze ve zprávě.
   2.203 -         * Z nastavení se brát nebudou (výchozí příjemci už ve zprávě budou).
   2.204 -         */
   2.205 -        ArrayList<InternetAddressKomu> prijemci = zprava.getPrijemci();
   2.206 -        for (InternetAddressKomu komu : prijemci) {
   2.207 -            if (zkontrolujAdresu(komu)) {
   2.208 -                mimeZprava.addRecipient(komu.getTyp(), komu);
   2.209 -            }
   2.210 -        }
   2.211 -    }
   2.212 +					textováČást.setText(xhtmlNaProstýText(zprava.getText()), KÓDOVÁNÍ);
   2.213 +					xhtmlČást.setContent(zprava.getText(), "text/html; charset=" + KÓDOVÁNÍ);
   2.214  
   2.215 -    /** Vypíše do logu seznam příjemců */
   2.216 -    public static void vypisPrijemce(Collection<InternetAddressKomu> prijemci) {
   2.217 -        for (InternetAddressKomu p : prijemci) {
   2.218 -            log.log(Level.INFO, p.toString());
   2.219 -        }
   2.220 -    }
   2.221 +					multipart.addBodyPart(textováČást);
   2.222 +					multipart.addBodyPart(xhtmlČást);
   2.223 +					break;
   2.224 +			}
   2.225  
   2.226 -    /** Veřejná odesílací metoda.
   2.227 -     * Postará se o rozdělení zpráv na dílčí (které se vejdou do limitu příjemců)
   2.228 -     */
   2.229 -    public void odesli(HromadnaZprava zprava) throws MessagingException {
   2.230 -        Collection<HromadnaZprava> zpravy = zprava.getDilciZpravy(nastaveni.getLimitZprav());
   2.231 +			/** Vlastní odeslání */
   2.232 +			Transport.send(mimeZprava);
   2.233  
   2.234 -        for (HromadnaZprava dilciZprava : zpravy) {
   2.235 -            odesliSMTP(dilciZprava);
   2.236 -        }
   2.237 -    }
   2.238 +		} else {
   2.239 +			MessagingException e = new MessagingException("Zpráva nebo nastavení jsou nevyhovující");
   2.240 +			log.log(Level.SEVERE, null, e);
   2.241 +			throw e;
   2.242 +		}
   2.243  
   2.244 -    private static boolean zkontrolujAdresu(InternetAddressKomu a) {
   2.245 -        if (a.getTyp() == null) {
   2.246 -            log.log(Level.WARNING, "Neplatná adresa (typ): {0}", a.getAddress());
   2.247 -            return false;
   2.248 -        }
   2.249 +	}
   2.250  
   2.251 -        if (a.getAddress() == null || a.getAddress().length() < 1) {
   2.252 -            log.log(Level.WARNING, "Neplatná adresa (address): {0}", a.getPersonal());
   2.253 -            return false;
   2.254 -        }
   2.255 +	private String xhtmlNaProstýText(String xhtml) throws MessagingException {
   2.256 +		try {
   2.257 +			Transformer textTransformer = transformerFactory.newTransformer(new StreamSource(getClass().getClassLoader().getResourceAsStream("cz/frantovo/postak/odchozíEmailText.xsl")));
   2.258  
   2.259 -        if (!zkontrolujAdresu(a.getAddress())) {
   2.260 -            log.log(Level.WARNING, "Adresa nevyhovuje regulárnímu výrazu: {0}", a.getAddress());
   2.261 -            return false;
   2.262 -        }
   2.263 +			StringReader input = new StringReader(xhtml);
   2.264 +			StringWriter output = new StringWriter(xhtml.length());
   2.265 +			textTransformer.transform(new StreamSource(input), new StreamResult(output));
   2.266  
   2.267 -        return true;
   2.268 -    }
   2.269 +			return output.toString();
   2.270 +		} catch (Exception e) {
   2.271 +			throw new MessagingException("Chyba při XSL transformaci zprávy na prostý text.", e);
   2.272 +		}
   2.273 +	}
   2.274  
   2.275 -    /** Zkontroluje e-mailovou adresu pomocí regulárního výrazu. */
   2.276 -    public static boolean zkontrolujAdresu(String adresa) {
   2.277 -        return adresa != null && Pattern.matches(REGULARNI_EMAIL, adresa);
   2.278 -    }
   2.279 +	/**
   2.280 +	 * Nastaví zprávě (MimeMessage) všechny příjemce, které najde ve zprávě a nastavení.
   2.281 +	 * Respektuje typy příjemců: komu, kopie, skrytá kopie.
   2.282 +	 */
   2.283 +	private static void naplnPrijemce(MimeMessage mimeZprava, HromadnaZprava zprava) throws MessagingException {
   2.284 +		/**
   2.285 +		 * Příjemci se budou definovat pouze ve zprávě.
   2.286 +		 * Z nastavení se brát nebudou (výchozí příjemci už ve zprávě budou).
   2.287 +		 */
   2.288 +		ArrayList<InternetAddressKomu> prijemci = zprava.getPrijemci();
   2.289 +		for (InternetAddressKomu komu : prijemci) {
   2.290 +			if (zkontrolujAdresu(komu)) {
   2.291 +				mimeZprava.addRecipient(komu.getTyp(), komu);
   2.292 +			}
   2.293 +		}
   2.294 +	}
   2.295  
   2.296 -    /** @return  Vrací true, pokud je zpráva v pořádku */
   2.297 -    private static boolean zkontrolujZpravu(HromadnaZprava z) {
   2.298 +	/** Vypíše do logu seznam příjemců */
   2.299 +	public static void vypisPrijemce(Collection<InternetAddressKomu> prijemci) {
   2.300 +		for (InternetAddressKomu p : prijemci) {
   2.301 +			log.log(Level.INFO, p.toString());
   2.302 +		}
   2.303 +	}
   2.304  
   2.305 -        if (z.getPrijemci() == null) {
   2.306 -            log.log(Level.WARNING, "getPrijemci() == null");
   2.307 -            return false;
   2.308 -        }
   2.309 +	/** Veřejná odesílací metoda.
   2.310 +	 * Postará se o rozdělení zpráv na dílčí (které se vejdou do limitu příjemců)
   2.311 +	 */
   2.312 +	public void odesli(HromadnaZprava zprava) throws MessagingException {
   2.313 +		Collection<HromadnaZprava> zpravy = zprava.getDilciZpravy(nastaveni.getLimitZprav());
   2.314  
   2.315 -        if (z.getPrijemci().size() < 1) {
   2.316 -            log.log(Level.WARNING, "getPrijemci().size() < 1");
   2.317 -            return false;
   2.318 -        }
   2.319 +		for (HromadnaZprava dilciZprava : zpravy) {
   2.320 +			odesliSMTP(dilciZprava);
   2.321 +		}
   2.322 +	}
   2.323  
   2.324 -        if (z.getOdesilatel() == null) {
   2.325 -            log.log(Level.WARNING, "getOdesilatel() == null");
   2.326 -            return false;
   2.327 -        }
   2.328 +	private static boolean zkontrolujAdresu(InternetAddressKomu a) {
   2.329 +		if (a.getTyp() == null) {
   2.330 +			log.log(Level.WARNING, "Neplatná adresa (typ): {0}", a.getAddress());
   2.331 +			return false;
   2.332 +		}
   2.333  
   2.334 -        if (z.getPredmet() == null) {
   2.335 -            log.log(Level.WARNING, "getPredmet() == null");
   2.336 -            return false;
   2.337 -        }
   2.338 +		if (a.getAddress() == null || a.getAddress().length() < 1) {
   2.339 +			log.log(Level.WARNING, "Neplatná adresa (address): {0}", a.getPersonal());
   2.340 +			return false;
   2.341 +		}
   2.342  
   2.343 -        return true;
   2.344 -    }
   2.345 +		if (!zkontrolujAdresu(a.getAddress())) {
   2.346 +			log.log(Level.WARNING, "Adresa nevyhovuje regulárnímu výrazu: {0}", a.getAddress());
   2.347 +			return false;
   2.348 +		}
   2.349  
   2.350 -    private static boolean zkontrolujNastaveni(Nastaveni n) {
   2.351 +		return true;
   2.352 +	}
   2.353  
   2.354 -        if (n.getPostovniServer() == null || n.getPostovniServer().length() < 1) {
   2.355 -            return false;
   2.356 -        }
   2.357 +	/** Zkontroluje e-mailovou adresu pomocí regulárního výrazu. */
   2.358 +	public static boolean zkontrolujAdresu(String adresa) {
   2.359 +		return adresa != null && Pattern.matches(REGULARNI_EMAIL, adresa);
   2.360 +	}
   2.361  
   2.362 -        return true;
   2.363 -    }
   2.364 +	/** @return Vrací true, pokud je zpráva v pořádku */
   2.365 +	private static boolean zkontrolujZpravu(HromadnaZprava z) {
   2.366  
   2.367 -    /** Slouží k uložení jména a hesla pro SMTP */
   2.368 -    private static class PostakuvHeslovnik extends Authenticator {
   2.369 +		if (z.getPrijemci() == null) {
   2.370 +			log.log(Level.WARNING, "getPrijemci() == null");
   2.371 +			return false;
   2.372 +		}
   2.373  
   2.374 -        private String jmeno = "user";
   2.375 -        private char[] heslo = "luser".toCharArray();
   2.376 +		if (z.getPrijemci().size() < 1) {
   2.377 +			log.log(Level.WARNING, "getPrijemci().size() < 1");
   2.378 +			return false;
   2.379 +		}
   2.380  
   2.381 -        @Override
   2.382 -        public PasswordAuthentication getPasswordAuthentication() {
   2.383 -            return new PasswordAuthentication(jmeno, String.valueOf(heslo));
   2.384 -        }
   2.385 +		if (z.getOdesilatel() == null) {
   2.386 +			log.log(Level.WARNING, "getOdesilatel() == null");
   2.387 +			return false;
   2.388 +		}
   2.389  
   2.390 -        public void setJmenoHeslo(String jmeno, char[] heslo) {
   2.391 -            this.jmeno = jmeno;
   2.392 -            this.heslo = heslo;
   2.393 -        }
   2.394 -    }
   2.395 +		if (z.getPredmet() == null) {
   2.396 +			log.log(Level.WARNING, "getPredmet() == null");
   2.397 +			return false;
   2.398 +		}
   2.399 +
   2.400 +		return true;
   2.401 +	}
   2.402 +
   2.403 +	private static boolean zkontrolujNastaveni(Nastaveni n) {
   2.404 +
   2.405 +		if (n.getPostovniServer() == null || n.getPostovniServer().length() < 1) {
   2.406 +			return false;
   2.407 +		}
   2.408 +
   2.409 +		return true;
   2.410 +	}
   2.411 +
   2.412 +	/** Slouží k uložení jména a hesla pro SMTP */
   2.413 +	private static class PostakuvHeslovnik extends Authenticator {
   2.414 +
   2.415 +		private String jmeno = "user";
   2.416 +		private char[] heslo = "luser".toCharArray();
   2.417 +
   2.418 +		@Override
   2.419 +		public PasswordAuthentication getPasswordAuthentication() {
   2.420 +			return new PasswordAuthentication(jmeno, String.valueOf(heslo));
   2.421 +		}
   2.422 +
   2.423 +		public void setJmenoHeslo(String jmeno, char[] heslo) {
   2.424 +			this.jmeno = jmeno;
   2.425 +			this.heslo = heslo;
   2.426 +		}
   2.427 +	}
   2.428  }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/java/Postak/src/cz/frantovo/postak/odchozíEmailText.xsl	Mon Apr 23 00:24:31 2012 +0200
     3.3 @@ -0,0 +1,274 @@
     3.4 +<?xml version="1.0" encoding="UTF-8"?>
     3.5 +<!--
     3.6 +	Převzato z projektu hellDesk.
     3.7 +-->
     3.8 +<xsl:stylesheet version="1.0"
     3.9 +				xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    3.10 +				xmlns:fn="http://www.w3.org/2005/xpath-functions"
    3.11 +				xmlns:str="http://xsltsl.org/string"
    3.12 +				xmlns:h="http://www.w3.org/1999/xhtml">
    3.13 +	<xsl:output method="text" encoding="UTF-8"/>
    3.14 +	<xsl:strip-space elements="*"/>
    3.15 +
    3.16 +	<xsl:output method="text" encoding="UTF-8"/>
    3.17 +	<xsl:strip-space elements="*"/>
    3.18 +
    3.19 +	<xsl:variable name="urlBase" select="/h:html/h:head/h:base/@href"/>
    3.20 +
    3.21 +
    3.22 +	<!-- Celý dokument -->
    3.23 +	<xsl:template match="/">
    3.24 +		<xsl:apply-templates select="h:html/h:body"/>
    3.25 +	</xsl:template>
    3.26 +
    3.27 +
    3.28 +	<xsl:template match="h:h1">
    3.29 +		<xsl:value-of select="text()"/>
    3.30 +		<xsl:text>&#10;</xsl:text>
    3.31 +		<xsl:call-template name="str:generate-string">
    3.32 +			<xsl:with-param name="text" select="'='"/>
    3.33 +			<xsl:with-param name="count" select="string-length(.)"/>
    3.34 +		</xsl:call-template>
    3.35 +		<xsl:text>&#10;</xsl:text>
    3.36 +		<xsl:text>&#10;</xsl:text>
    3.37 +	</xsl:template>
    3.38 +
    3.39 +
    3.40 +	<xsl:template match="h:h2">
    3.41 +		<xsl:value-of select="text()"/>
    3.42 +		<xsl:text>&#10;</xsl:text>
    3.43 +		<xsl:call-template name="str:generate-string">
    3.44 +			<xsl:with-param name="text" select="'-'"/>
    3.45 +			<xsl:with-param name="count" select="string-length(.)"/>
    3.46 +		</xsl:call-template>
    3.47 +		<xsl:text>&#10;</xsl:text>
    3.48 +		<xsl:text>&#10;</xsl:text>
    3.49 +	</xsl:template>
    3.50 +
    3.51 +
    3.52 +	<xsl:template match="h:h3">
    3.53 +		<xsl:text>### </xsl:text>
    3.54 +		<xsl:value-of select="text()"/>
    3.55 +		<xsl:text>&#10;</xsl:text>
    3.56 +		<xsl:text>&#10;</xsl:text>
    3.57 +	</xsl:template>
    3.58 +
    3.59 +
    3.60 +	<xsl:template match="h:h4">
    3.61 +		<xsl:text>#### </xsl:text>
    3.62 +		<xsl:value-of select="text()"/>
    3.63 +		<xsl:text>&#10;</xsl:text>
    3.64 +		<xsl:text>&#10;</xsl:text>
    3.65 +	</xsl:template>
    3.66 +
    3.67 +
    3.68 +	<xsl:template match="h:h5">
    3.69 +		<xsl:text>##### </xsl:text>
    3.70 +		<xsl:value-of select="text()"/>
    3.71 +		<xsl:text>&#10;</xsl:text>
    3.72 +		<xsl:text>&#10;</xsl:text>
    3.73 +	</xsl:template>
    3.74 +
    3.75 +
    3.76 +	<xsl:template match="h:h6">
    3.77 +		<xsl:text>###### </xsl:text>
    3.78 +		<xsl:value-of select="text()"/>
    3.79 +		<xsl:text>&#10;</xsl:text>
    3.80 +		<xsl:text>&#10;</xsl:text>
    3.81 +	</xsl:template>
    3.82 +
    3.83 +
    3.84 +	<xsl:template match="h:p">
    3.85 +		<xsl:apply-templates/>
    3.86 +		<xsl:text>&#10;</xsl:text>
    3.87 +		<xsl:text>&#10;</xsl:text>
    3.88 +	</xsl:template>
    3.89 +
    3.90 +	
    3.91 +	<xsl:template match="h:blockquote/h:p">
    3.92 +		<xsl:text>&gt; </xsl:text>
    3.93 +		<xsl:apply-templates/>
    3.94 +		<xsl:text>&#10;</xsl:text>
    3.95 +		<xsl:text>&#10;</xsl:text>
    3.96 +	</xsl:template>
    3.97 +
    3.98 +
    3.99 +	<xsl:template match="h:cite[not(starts-with(., '„') or starts-with(., '‚'))]">
   3.100 +		<xsl:text>„</xsl:text>
   3.101 +		<xsl:apply-templates/>
   3.102 +		<xsl:text>“</xsl:text>
   3.103 +	</xsl:template>	
   3.104 +
   3.105 +
   3.106 +	<xsl:template match="h:a">
   3.107 +		<xsl:if test="not(text() = @href)">
   3.108 +			<xsl:text>'</xsl:text>
   3.109 +			<xsl:apply-templates select="node()"/>
   3.110 +			<xsl:text>' </xsl:text>
   3.111 +		</xsl:if>
   3.112 +		<xsl:text>&lt;</xsl:text>
   3.113 +		<xsl:choose>
   3.114 +			<xsl:when test="starts-with(@href, 'http:') or starts-with(@href, 'https:') or starts-with(@href, 'ftp:')">
   3.115 +				<xsl:value-of select="@href"/>
   3.116 +			</xsl:when>
   3.117 +			<xsl:when test="starts-with(@href, 'mailto:')">
   3.118 +				<xsl:value-of select="substring-after(@href, 'mailto:')"/>
   3.119 +			</xsl:when>
   3.120 +			<xsl:otherwise>
   3.121 +				<xsl:choose>
   3.122 +					<!-- TODO: $urlBase by nemělo končit lomítkem -->
   3.123 +					<xsl:when test="starts-with(@href, '/')">
   3.124 +						<xsl:value-of select="concat($urlBase, @href)"/>
   3.125 +					</xsl:when>
   3.126 +					<xsl:otherwise>
   3.127 +						<xsl:value-of select="concat($urlBase, '/', @href)"/>
   3.128 +					</xsl:otherwise>
   3.129 +				</xsl:choose>
   3.130 +			</xsl:otherwise>
   3.131 +		</xsl:choose>
   3.132 +		<xsl:text>&gt;</xsl:text>
   3.133 +		<xsl:if test="normalize-space(@title)">
   3.134 +			<xsl:text> (</xsl:text>
   3.135 +			<xsl:value-of select="@title"/>
   3.136 +			<xsl:text>)</xsl:text>
   3.137 +		</xsl:if>
   3.138 +	</xsl:template>
   3.139 +
   3.140 +
   3.141 +	<xsl:template match="h:img">
   3.142 +		<xsl:text>Obrázek: </xsl:text>
   3.143 +		<xsl:value-of select="@src"/>
   3.144 +		<!-- TODO: relativní odkazy -->
   3.145 +	</xsl:template>
   3.146 +
   3.147 +
   3.148 +	<xsl:template match="h:strong|h:b">
   3.149 +		<xsl:text>**</xsl:text>
   3.150 +		<xsl:apply-templates/>
   3.151 +		<xsl:text>**</xsl:text>
   3.152 +	</xsl:template>
   3.153 +
   3.154 +
   3.155 +	<xsl:template match="h:em|h:i">
   3.156 +		<xsl:text>*</xsl:text>
   3.157 +		<xsl:apply-templates/>
   3.158 +		<xsl:text>*</xsl:text>
   3.159 +	</xsl:template>
   3.160 +
   3.161 +
   3.162 +	<xsl:template match="h:abbr[@title]">
   3.163 +		<xsl:apply-templates/>
   3.164 +		<xsl:text> (</xsl:text>
   3.165 +		<xsl:value-of select="@title"/>
   3.166 +		<xsl:text>)</xsl:text>
   3.167 +	</xsl:template>
   3.168 +
   3.169 +
   3.170 +	<xsl:template match="h:pre">
   3.171 +		<xsl:text>--------------------------------</xsl:text>
   3.172 +		<xsl:text>&#10;</xsl:text>
   3.173 +		<xsl:apply-templates/>
   3.174 +		<xsl:text>&#10;</xsl:text>
   3.175 +		<xsl:text>--------------------------------</xsl:text>
   3.176 +		<xsl:text>&#10;</xsl:text>
   3.177 +		<xsl:text>&#10;</xsl:text>
   3.178 +	</xsl:template>
   3.179 +
   3.180 +
   3.181 +	<xsl:template match="h:code">
   3.182 +		<xsl:text>`</xsl:text>
   3.183 +		<xsl:apply-templates/>
   3.184 +		<xsl:text>`</xsl:text>
   3.185 +	</xsl:template>
   3.186 +
   3.187 +
   3.188 +	<xsl:template match="h:hr">
   3.189 +		<xsl:text>----------------------------------------------------------------</xsl:text>
   3.190 +		<xsl:text>&#10;</xsl:text>
   3.191 +		<xsl:text>&#10;</xsl:text>
   3.192 +	</xsl:template>
   3.193 +
   3.194 +
   3.195 +	<xsl:template match="h:br">
   3.196 +		<xsl:text>&#10;</xsl:text>
   3.197 +	</xsl:template>	
   3.198 +
   3.199 +
   3.200 +	<xsl:template match="h:ol|h:ul">
   3.201 +		<xsl:variable name="úroveň" select="count(ancestor::h:li)"/>
   3.202 +		<xsl:variable name="odsazení">
   3.203 +			<!-- položky na nejvyšší úrovni odsazené jednou mezerou -->
   3.204 +			<xsl:value-of select="' '"/>
   3.205 +			<xsl:call-template name="str:generate-string">
   3.206 +				<xsl:with-param name="text" select="'  '"/>
   3.207 +				<!-- položky na druhé a vyšší úrovni odsazené vždy dvěma dalšími mezerami -->
   3.208 +				<xsl:with-param name="count" select="$úroveň - 1"/>
   3.209 +			</xsl:call-template>
   3.210 +		</xsl:variable>
   3.211 +
   3.212 +		<xsl:if test="$úroveň &gt; 0">
   3.213 +			<xsl:text>&#10;</xsl:text>
   3.214 +		</xsl:if>
   3.215 +
   3.216 +		<xsl:for-each select="h:li">
   3.217 +			<xsl:if test="parent::h:ol">
   3.218 +				<xsl:value-of select="concat($odsazení, position(), ') ')"/>
   3.219 +			</xsl:if>
   3.220 +			<xsl:if test="parent::h:ul">
   3.221 +				<xsl:value-of select="concat($odsazení, '- ')"/>
   3.222 +			</xsl:if>
   3.223 +			<xsl:apply-templates/>
   3.224 +			<xsl:if test="$úroveň = 0 or not(position() = last())">
   3.225 +				<xsl:text>&#10;</xsl:text>
   3.226 +			</xsl:if>
   3.227 +		</xsl:for-each>
   3.228 +		
   3.229 +		<xsl:if test="$úroveň = 0">
   3.230 +			<xsl:text>&#10;</xsl:text>
   3.231 +		</xsl:if>
   3.232 +	</xsl:template>
   3.233 +
   3.234 +
   3.235 +	<xsl:template match="text()[not(parent::h:pre)]">
   3.236 +		<xsl:if test="(starts-with(., ' ') or starts-with(., '&#10;')) and preceding-sibling::node() and not(preceding-sibling::h:br)">
   3.237 +			<xsl:text> </xsl:text>
   3.238 +		</xsl:if>
   3.239 +		<xsl:value-of select="normalize-space(.)"/>
   3.240 +		<xsl:variable name="posledníZnak" select="substring(., string-length(.))"/>
   3.241 +		<!-- TODO: tabulátor? -->
   3.242 +		<xsl:if test="($posledníZnak = ' ' or $posledníZnak = '&#10;') and following-sibling::node()">
   3.243 +			<xsl:text> </xsl:text>
   3.244 +		</xsl:if>
   3.245 +	</xsl:template>
   3.246 +	
   3.247 +	
   3.248 +	<xsl:template match="h:div[@class = 'patička']">
   3.249 +		<xsl:text>-- </xsl:text>
   3.250 +		<xsl:text>&#10;</xsl:text>
   3.251 +		<xsl:apply-templates/>
   3.252 +	</xsl:template>
   3.253 +	
   3.254 +
   3.255 +	<!--
   3.256 +		Převzato z:
   3.257 +		http://xsltsl.sourceforge.net/string.html#template.str:generate-string
   3.258 +	-->
   3.259 +	<xsl:template name="str:generate-string">
   3.260 +		<xsl:param name="text"/>
   3.261 +		<xsl:param name="count"/>
   3.262 +
   3.263 +		<xsl:choose>
   3.264 +			<xsl:when test="string-length($text) = 0 or $count &lt;= 0"/>
   3.265 +			<xsl:otherwise>
   3.266 +				<xsl:value-of select="$text"/>
   3.267 +				<xsl:call-template name="str:generate-string">
   3.268 +					<xsl:with-param name="text" select="$text"/>
   3.269 +					<xsl:with-param name="count" select="$count - 1"/>
   3.270 +				</xsl:call-template>
   3.271 +			</xsl:otherwise>
   3.272 +		</xsl:choose>
   3.273 +	</xsl:template>
   3.274 +
   3.275 +
   3.276 +</xsl:stylesheet>
   3.277 +
     4.1 --- a/java/SuperPostak/src/cz/frantovo/superPostak/SuperPostak.form	Fri Mar 30 15:35:26 2012 +0200
     4.2 +++ b/java/SuperPostak/src/cz/frantovo/superPostak/SuperPostak.form	Mon Apr 23 00:24:31 2012 +0200
     4.3 @@ -510,8 +510,8 @@
     4.4            <Group type="103" groupAlignment="0" attributes="0">
     4.5                <Group type="102" alignment="1" attributes="0">
     4.6                    <EmptySpace max="-2" attributes="0"/>
     4.7 -                  <Group type="103" groupAlignment="1" attributes="0">
     4.8 -                      <Component id="jScrollPane1" alignment="0" pref="438" max="32767" attributes="0"/>
     4.9 +                  <Group type="103" groupAlignment="0" attributes="0">
    4.10 +                      <Component id="jScrollPane1" alignment="0" pref="461" max="32767" attributes="0"/>
    4.11                        <Group type="102" alignment="1" attributes="0">
    4.12                            <Group type="103" groupAlignment="1" attributes="0">
    4.13                                <Group type="102" attributes="0">
    4.14 @@ -527,16 +527,20 @@
    4.15                                </Group>
    4.16                            </Group>
    4.17                            <Group type="103" groupAlignment="0" attributes="0">
    4.18 -                              <Component id="vstupJmenoOdesilatele" alignment="0" pref="328" max="32767" attributes="0"/>
    4.19 -                              <Component id="vstupAdresaOdesilatele" alignment="0" pref="328" max="32767" attributes="0"/>
    4.20 -                              <Component id="vstupPredmet" alignment="0" pref="328" max="32767" attributes="0"/>
    4.21 +                              <Component id="vstupJmenoOdesilatele" alignment="0" max="32767" attributes="0"/>
    4.22 +                              <Component id="vstupAdresaOdesilatele" alignment="0" max="32767" attributes="0"/>
    4.23 +                              <Component id="vstupPredmet" alignment="0" max="32767" attributes="0"/>
    4.24                            </Group>
    4.25                        </Group>
    4.26                        <Group type="102" alignment="0" attributes="0">
    4.27                            <Component id="jLabel15" min="-2" max="-2" attributes="0"/>
    4.28 -                          <EmptySpace min="-2" pref="33" max="-2" attributes="0"/>
    4.29 -                          <Component id="vstupFormatHTML" pref="81" max="32767" attributes="0"/>
    4.30 -                          <EmptySpace min="-2" pref="247" max="-2" attributes="0"/>
    4.31 +                          <EmptySpace max="-2" attributes="0"/>
    4.32 +                          <Component id="formátProstý" min="-2" max="-2" attributes="0"/>
    4.33 +                          <EmptySpace max="-2" attributes="0"/>
    4.34 +                          <Component id="formátXHTML" min="-2" max="-2" attributes="0"/>
    4.35 +                          <EmptySpace max="-2" attributes="0"/>
    4.36 +                          <Component id="formátOboje" min="-2" max="-2" attributes="0"/>
    4.37 +                          <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
    4.38                        </Group>
    4.39                    </Group>
    4.40                    <EmptySpace max="-2" attributes="0"/>
    4.41 @@ -566,7 +570,9 @@
    4.42                    <EmptySpace max="-2" attributes="0"/>
    4.43                    <Group type="103" groupAlignment="3" attributes="0">
    4.44                        <Component id="jLabel15" alignment="3" min="-2" max="-2" attributes="0"/>
    4.45 -                      <Component id="vstupFormatHTML" alignment="3" min="-2" max="-2" attributes="0"/>
    4.46 +                      <Component id="formátProstý" alignment="3" min="-2" max="-2" attributes="0"/>
    4.47 +                      <Component id="formátXHTML" alignment="3" min="-2" max="-2" attributes="0"/>
    4.48 +                      <Component id="formátOboje" alignment="3" min="-2" max="-2" attributes="0"/>
    4.49                    </Group>
    4.50                    <EmptySpace max="-2" attributes="0"/>
    4.51                </Group>
    4.52 @@ -616,13 +622,6 @@
    4.53              <Property name="text" type="java.lang.String" value="Form&#xe1;t zpr&#xe1;vy"/>
    4.54            </Properties>
    4.55          </Component>
    4.56 -        <Component class="javax.swing.JCheckBox" name="vstupFormatHTML">
    4.57 -          <Properties>
    4.58 -            <Property name="mnemonic" type="int" value="104"/>
    4.59 -            <Property name="text" type="java.lang.String" value="HTML"/>
    4.60 -            <Property name="toolTipText" type="java.lang.String" value="P&#x159;i neza&#x161;krtnut&#xed; se ode&#x161;le jako prost&#xfd; text"/>
    4.61 -          </Properties>
    4.62 -        </Component>
    4.63          <Component class="org.jdesktop.swingx.JXHyperlink" name="odpovedetKomuOdkaz">
    4.64            <Properties>
    4.65              <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
    4.66 @@ -642,6 +641,37 @@
    4.67              <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="odpovedetKomuOdkazActionPerformed"/>
    4.68            </Events>
    4.69          </Component>
    4.70 +        <Component class="javax.swing.JRadioButton" name="form&#xe1;tProst&#xfd;">
    4.71 +          <Properties>
    4.72 +            <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    4.73 +              <ComponentRef name="form&#xe1;tSkupina"/>
    4.74 +            </Property>
    4.75 +            <Property name="selected" type="boolean" value="true"/>
    4.76 +            <Property name="text" type="java.lang.String" value="Prost&#xfd; text"/>
    4.77 +          </Properties>
    4.78 +        </Component>
    4.79 +        <Component class="javax.swing.JRadioButton" name="form&#xe1;tXHTML">
    4.80 +          <Properties>
    4.81 +            <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    4.82 +              <ComponentRef name="form&#xe1;tSkupina"/>
    4.83 +            </Property>
    4.84 +            <Property name="text" type="java.lang.String" value="(X)HTML"/>
    4.85 +          </Properties>
    4.86 +          <Events>
    4.87 +            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="form&#xe1;tXHTMLActionPerformed"/>
    4.88 +          </Events>
    4.89 +        </Component>
    4.90 +        <Component class="javax.swing.JRadioButton" name="form&#xe1;tOboje">
    4.91 +          <Properties>
    4.92 +            <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    4.93 +              <ComponentRef name="form&#xe1;tSkupina"/>
    4.94 +            </Property>
    4.95 +            <Property name="text" type="java.lang.String" value="Oboje"/>
    4.96 +          </Properties>
    4.97 +          <Events>
    4.98 +            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="form&#xe1;tObojeActionPerformed"/>
    4.99 +          </Events>
   4.100 +        </Component>
   4.101        </SubComponents>
   4.102      </Container>
   4.103      <Container class="javax.swing.JDialog" name="odpovedetKomuDialog">
   4.104 @@ -726,6 +756,8 @@
   4.105          </Component>
   4.106        </SubComponents>
   4.107      </Container>
   4.108 +    <Component class="javax.swing.ButtonGroup" name="form&#xe1;tSkupina">
   4.109 +    </Component>
   4.110    </NonVisualComponents>
   4.111    <Properties>
   4.112      <Property name="title" type="java.lang.String" value="SuperPo&#x161;&#x165;&#xe1;k"/>
     5.1 --- a/java/SuperPostak/src/cz/frantovo/superPostak/SuperPostak.java	Fri Mar 30 15:35:26 2012 +0200
     5.2 +++ b/java/SuperPostak/src/cz/frantovo/superPostak/SuperPostak.java	Mon Apr 23 00:24:31 2012 +0200
     5.3 @@ -9,6 +9,8 @@
     5.4  import java.awt.Cursor;
     5.5  import java.awt.Dialog.ModalityType;
     5.6  import java.awt.KeyboardFocusManager;
     5.7 +import java.awt.event.ActionListener;
     5.8 +import java.awt.event.ItemListener;
     5.9  import java.beans.XMLDecoder;
    5.10  import java.beans.XMLEncoder;
    5.11  import java.io.BufferedInputStream;
    5.12 @@ -28,19 +30,15 @@
    5.13  import java.util.zip.GZIPOutputStream;
    5.14  import javax.mail.MessagingException;
    5.15  import javax.mail.internet.InternetAddress;
    5.16 -import javax.swing.JComponent;
    5.17 -import javax.swing.JDialog;
    5.18 -import javax.swing.JOptionPane;
    5.19 -import javax.swing.JTextArea;
    5.20 -import javax.swing.UIManager;
    5.21 -import javax.swing.UnsupportedLookAndFeelException;
    5.22 +import javax.swing.*;
    5.23 +import javax.swing.event.ChangeListener;
    5.24  import org.jdesktop.swingx.JXErrorPane;
    5.25  import org.jdesktop.swingx.JXTaskPaneContainer;
    5.26  import org.jdesktop.swingx.error.ErrorInfo;
    5.27  
    5.28  /**
    5.29   *
    5.30 - * @author  fiki
    5.31 + * @author fiki
    5.32   */
    5.33  public class SuperPostak extends javax.swing.JFrame {
    5.34  
    5.35 @@ -56,6 +54,7 @@
    5.36  
    5.37  	/**
    5.38  	 * Creates new form SuperPostak
    5.39 +	 *
    5.40  	 * @param ladit předvyplní testovací hodnoty - zprávu
    5.41  	 * @param exit při zavření okna ukončí program
    5.42  	 */
    5.43 @@ -350,8 +349,10 @@
    5.44          jScrollPane1 = new javax.swing.JScrollPane();
    5.45          vstupZprava = new javax.swing.JTextArea();
    5.46          jLabel15 = new javax.swing.JLabel();
    5.47 -        vstupFormatHTML = new javax.swing.JCheckBox();
    5.48          odpovedetKomuOdkaz = new org.jdesktop.swingx.JXHyperlink();
    5.49 +        formátProstý = new javax.swing.JRadioButton();
    5.50 +        formátXHTML = new javax.swing.JRadioButton();
    5.51 +        formátOboje = new javax.swing.JRadioButton();
    5.52          odpovedetKomuDialog = new javax.swing.JDialog();
    5.53          jLabel18 = new javax.swing.JLabel();
    5.54          jLabel19 = new javax.swing.JLabel();
    5.55 @@ -359,6 +360,7 @@
    5.56          odpovedetKomuJmeno = new javax.swing.JTextField();
    5.57          odpovedetKomuAdresa = new javax.swing.JTextField();
    5.58          odpovedetKomuHotovo = new javax.swing.JButton();
    5.59 +        formátSkupina = new javax.swing.ButtonGroup();
    5.60          jXHeader1 = new org.jdesktop.swingx.JXHeader();
    5.61          taskPanel = new org.jdesktop.swingx.JXTaskPaneContainer();
    5.62          jXTaskPane1 = new org.jdesktop.swingx.JXTaskPane();
    5.63 @@ -700,10 +702,6 @@
    5.64  
    5.65          jLabel15.setText("Formát zprávy");
    5.66  
    5.67 -        vstupFormatHTML.setMnemonic('h');
    5.68 -        vstupFormatHTML.setText("HTML");
    5.69 -        vstupFormatHTML.setToolTipText("Při nezaškrtnutí se odešle jako prostý text");
    5.70 -
    5.71          odpovedetKomuOdkaz.setForeground(javax.swing.UIManager.getDefaults().getColor("windowText"));
    5.72          odpovedetKomuOdkaz.setMnemonic('e');
    5.73          odpovedetKomuOdkaz.setText("Adresa odesílatele");
    5.74 @@ -716,15 +714,35 @@
    5.75              }
    5.76          });
    5.77  
    5.78 +        formátSkupina.add(formátProstý);
    5.79 +        formátProstý.setSelected(true);
    5.80 +        formátProstý.setText("Prostý text");
    5.81 +
    5.82 +        formátSkupina.add(formátXHTML);
    5.83 +        formátXHTML.setText("(X)HTML");
    5.84 +        formátXHTML.addActionListener(new java.awt.event.ActionListener() {
    5.85 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
    5.86 +                formátXHTMLActionPerformed(evt);
    5.87 +            }
    5.88 +        });
    5.89 +
    5.90 +        formátSkupina.add(formátOboje);
    5.91 +        formátOboje.setText("Oboje");
    5.92 +        formátOboje.addActionListener(new java.awt.event.ActionListener() {
    5.93 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
    5.94 +                formátObojeActionPerformed(evt);
    5.95 +            }
    5.96 +        });
    5.97 +
    5.98          javax.swing.GroupLayout panelZpravaLayout = new javax.swing.GroupLayout(panelZprava);
    5.99          panelZprava.setLayout(panelZpravaLayout);
   5.100          panelZpravaLayout.setHorizontalGroup(
   5.101              panelZpravaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   5.102              .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelZpravaLayout.createSequentialGroup()
   5.103                  .addContainerGap()
   5.104 -                .addGroup(panelZpravaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
   5.105 -                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE)
   5.106 -                    .addGroup(panelZpravaLayout.createSequentialGroup()
   5.107 +                .addGroup(panelZpravaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   5.108 +                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 461, Short.MAX_VALUE)
   5.109 +                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelZpravaLayout.createSequentialGroup()
   5.110                          .addGroup(panelZpravaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
   5.111                              .addGroup(panelZpravaLayout.createSequentialGroup()
   5.112                                  .addGroup(panelZpravaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   5.113 @@ -735,14 +753,18 @@
   5.114                                  .addComponent(odpovedetKomuOdkaz, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
   5.115                                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)))
   5.116                          .addGroup(panelZpravaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   5.117 -                            .addComponent(vstupJmenoOdesilatele, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
   5.118 -                            .addComponent(vstupAdresaOdesilatele, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
   5.119 -                            .addComponent(vstupPredmet, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)))
   5.120 -                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, panelZpravaLayout.createSequentialGroup()
   5.121 +                            .addComponent(vstupJmenoOdesilatele)
   5.122 +                            .addComponent(vstupAdresaOdesilatele)
   5.123 +                            .addComponent(vstupPredmet)))
   5.124 +                    .addGroup(panelZpravaLayout.createSequentialGroup()
   5.125                          .addComponent(jLabel15)
   5.126 -                        .addGap(33, 33, 33)
   5.127 -                        .addComponent(vstupFormatHTML, javax.swing.GroupLayout.DEFAULT_SIZE, 81, Short.MAX_VALUE)
   5.128 -                        .addGap(247, 247, 247)))
   5.129 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   5.130 +                        .addComponent(formátProstý)
   5.131 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   5.132 +                        .addComponent(formátXHTML)
   5.133 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   5.134 +                        .addComponent(formátOboje)
   5.135 +                        .addGap(0, 0, Short.MAX_VALUE)))
   5.136                  .addContainerGap())
   5.137          );
   5.138          panelZpravaLayout.setVerticalGroup(
   5.139 @@ -765,7 +787,9 @@
   5.140                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   5.141                  .addGroup(panelZpravaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
   5.142                      .addComponent(jLabel15)
   5.143 -                    .addComponent(vstupFormatHTML))
   5.144 +                    .addComponent(formátProstý)
   5.145 +                    .addComponent(formátXHTML)
   5.146 +                    .addComponent(formátOboje))
   5.147                  .addContainerGap())
   5.148          );
   5.149  
   5.150 @@ -816,7 +840,7 @@
   5.151                      .addComponent(jLabel19)
   5.152                      .addComponent(odpovedetKomuAdresa, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
   5.153                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   5.154 -                .addComponent(jLabel17)
   5.155 +                .addComponent(jLabel17, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
   5.156                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
   5.157                  .addComponent(odpovedetKomuHotovo)
   5.158                  .addContainerGap())
   5.159 @@ -966,7 +990,17 @@
   5.160  		zprava.setOdesilatel(new InternetAddress(vstupAdresaOdesilatele.getText(), vstupJmenoOdesilatele.getText()));
   5.161  		zprava.setPredmet(vstupPredmet.getText());
   5.162  		zprava.setText(vstupZprava.getText());
   5.163 -		zprava.setFormatHTML(vstupFormatHTML.isSelected());
   5.164 +
   5.165 +		if (formátProstý.isSelected()) {
   5.166 +			zprava.setFormatHTML(HromadnaZprava.FORMÁT.PROSTÝ_TEXT);
   5.167 +		} else if (formátXHTML.isSelected()) {
   5.168 +			zprava.setFormatHTML(HromadnaZprava.FORMÁT.XHTML);
   5.169 +		} else if (formátOboje.isSelected()) {
   5.170 +			zprava.setFormatHTML(HromadnaZprava.FORMÁT.OBOJE);
   5.171 +		} else {
   5.172 +			log.severe("Není zvolen formát zprávy → nastavuji: prostý text.");
   5.173 +			zprava.setFormatHTML(HromadnaZprava.FORMÁT.PROSTÝ_TEXT);
   5.174 +		}
   5.175  
   5.176  		if (Postak.zkontrolujAdresu(odpovedetKomuAdresa.getText())) {
   5.177  			InternetAddress komu = new InternetAddress();
   5.178 @@ -1102,6 +1136,28 @@
   5.179  		}
   5.180  }//GEN-LAST:event_odpovedetKomuHotovoActionPerformed
   5.181  
   5.182 +	private void formátXHTMLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_formátXHTMLActionPerformed
   5.183 +		nastavVýchozíXHTML();
   5.184 +	}//GEN-LAST:event_formátXHTMLActionPerformed
   5.185 +
   5.186 +	private void formátObojeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_formátObojeActionPerformed
   5.187 +		nastavVýchozíXHTML();
   5.188 +	}//GEN-LAST:event_formátObojeActionPerformed
   5.189 +
   5.190 +	/**
   5.191 +	 * Pokud ještě není vyplněn žádný text, vložíme šablonu.
   5.192 +	 */
   5.193 +	private void nastavVýchozíXHTML() {
   5.194 +		if (vstupZprava.getText().isEmpty()) {
   5.195 +			vstupZprava.setText("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
   5.196 +					+ "<body>\n\n"
   5.197 +					+ "<p></p>\n"
   5.198 +					+ "<div class=\"patička\"></div>\n\n"
   5.199 +					+ "</body>\n"
   5.200 +					+ "</html>");
   5.201 +		}
   5.202 +	}
   5.203 +
   5.204  	/** Provede uživatelem zadaný SQL dotaz a vrátí získané příjemce */
   5.205  	private Collection<InternetAddressKomu> getPrijemciSQL() throws SQLException, UnsupportedEncodingException {
   5.206  		if ("".equals(vstupSQL.getText())) {
   5.207 @@ -1183,6 +1239,10 @@
   5.208  		});
   5.209  	}
   5.210      // Variables declaration - do not modify//GEN-BEGIN:variables
   5.211 +    private javax.swing.JRadioButton formátOboje;
   5.212 +    private javax.swing.JRadioButton formátProstý;
   5.213 +    private javax.swing.ButtonGroup formátSkupina;
   5.214 +    private javax.swing.JRadioButton formátXHTML;
   5.215      private javax.swing.JLabel jLabel1;
   5.216      private javax.swing.JLabel jLabel10;
   5.217      private javax.swing.JLabel jLabel11;
   5.218 @@ -1239,7 +1299,6 @@
   5.219      private javax.swing.JPasswordField vstupDBheslo;
   5.220      private javax.swing.JTextField vstupDBjmeno;
   5.221      private javax.swing.JTextField vstupDatabaze;
   5.222 -    private javax.swing.JCheckBox vstupFormatHTML;
   5.223      private javax.swing.JTextField vstupJmenoOdesilatele;
   5.224      private javax.swing.JTextField vstupPredmet;
   5.225      private javax.swing.JPasswordField vstupSMTPheslo;