HTML emaily v CzechIdM

Jednou z důležitých funkcí CzechIdM je schopnost předávání informací uživatelům pomocí emailu. Většinou se jedná pouze o notifikace, jejichž cílem je předat informaci. Někdy je ale i notifikační email informací určenou k tisku. K tomu se jednoduchý prostý text příliš nehodí, proto jsme do CzechIdM přidali možnost formátovat emaily pomocí HTML tagů.

Změny v emailových šablonách

Emailová šablona pro CzechIdM je obyčejný XML soubor, který obsahuje otagovaná metadata a samotný text emailu. V textu jsou pak použity speciální tagy, které jsou dynamicky doplněny před odesláním zprávy.

<?xml version="1.0" encoding="UTF-8"?>
<emailTemplate xmlns="urn:jbpm.org:bcv_emailTemplate-1.0" name="UserRoleApprove">
	<language>cs</language>
	<subject>Schválení přidání role uživateli #{userFullName}</subject>
	<text>
	Dobrý den,
	žádáme Vás o schválení přidělení role "#{roleName}" uživateli "#{userName}". 
	Popis role: #{roleDescription}
	</text>
	<hideConfidential>false</hideConfidential>
</emailTemplate>

Emailové šablony se ukládají do databáze, ze které si je CzechIdM v případě potřeby načítá. Z pohledu aplikace se pak jedná o Hibernate entity. Tuto entitu jsme rozšířili o atribut Content-Type, který se při načtení šablony propaguje do mailového subsystému.

@Entity
@Table(name = "email_templates")
public class EmailTemplate extends ViewMainEntity {

	private static final long serialVersionUID = 1L;
	...
	@Column(name = "language", length = 2, nullable = false)
	private String language;

	@Column(name = "content_type", nullable = false)
	private String contentType;

	@Column(name = "hideConfidential", nullable = false)
	private boolean hideConfidential;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}
	...
}

V případě šablony je pak Content-Type přidán jako další tag v rámci XML souboru. Pokud není uveden, CzechIdM předpokládá „text/plain“. Chceme-li mít šablonu jako HTML (a tedy v ní používat HTML tagy), musíme jako typ uvést „text/html“.

<?xml version="1.0" encoding="UTF-8"?>
<emailTemplate xmlns="urn:jbpm.org:bcv_emailTemplate-1.0" name="UserRoleApprove">
	<language>cs</language>
	<subject>Schválení přidání role uživateli #{userFullName}</subject>
	<contentType>text/html</contentType>
	<text>
	Dobrý den,<br/>
	žádáme Vás o schválení přidělení role <strong>#{roleName}</strong> uživateli <strong>#{userName}</strong>.<br/>
	Popis role: #{roleDescription}<br/>
	</text>
	<hideConfidential>false</hideConfidential>
</emailTemplate>

Realizace parseru umožňuje použití jakýchkoli HTML tagů. Pokud jsou uvedeny mezi tagy <text> </text> v šabloně, budou ve výsledné emailové zprávě interpretovány jako HTML značky. Jednoduchou prezentaci výsledku si můžete prohlédnout na obrázku:

html_email

Parser pro nové šablony

Do databáze se nové verze šablon nahrávají pomocí utility IdMUploader. Tato utilita parsuje a validuje soubory šablon a ukládá je do samostatné databázové tabulky. Uploader bylo zapotřebí upravit, protože docházelo ke zmatení XML a HTML značek. Takové chování je správné, protože XML umožňuje definici značek vlastních. V tomto případě ale nebylo zrovna žádané. HTML značky byly tedy parsovány také (jako XML) a z výsledné šablony se ztrácely.

Nejjednodušším řešením se ukázalo použití následujícího triku: Celý soubor šablony byl rozparsován a ve vzniklém DOMu byl nalezen výskyt značky „text“. Celý podstrom této značky byl následně z DOMu převeden zpět na XML. Tím došlo k rekonstrukci textu zprávy včetně HTML tagů. O tento proces se stará následující kód.

private void parseData() {
	Element element = document.getDocumentElement();
	NodeList nodeList = element.getChildNodes();
	for (int i = 0; i < nodeList.getLength(); i++) {
		Node node = nodeList.item(i);
		if ("text".equals(node.getNodeName())) {
			setText(returnTextNodeChildrenAsString(node));
		}
	...
	}
...
}

private String returnTextNodeChildrenAsString(Node node) {
	ByteArrayOutputStream out = new ByteArrayOutputStream()
              try {
		Transformer transformer = TransformerFactory.newInstance().newTransformer();
		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
		Source source = new DOMSource(node);
		Result target = new StreamResult(out);
		transformer.transform(source, target);
	} catch (TransformerException e) {
		e.printStackTrace();
	}
	String res = out.toString();
	return res.replaceAll("<text .*>", "").replaceAll("</text>", "");
}

Závěr

V článku jsme popsali způsob, jakým CzechIdM tvoří emailové zprávy z XML šablon a ukázali jednoduché přidání jejich nové vlastnosti. Text šablon je nyní možné formátovat klasickým HTML. Pokud Vás článek zaujal a chtěli byste se dozvědět o mailovém subsystému v CzechIdM více, neváhejte mne kontaktovat na petr.fiser@bcvsolutions.eu.