CzechIdM – Java – E-mails with attachment

Last week we’ve learned our Identity Manager CzechIdM how to send e-mails with attachments. There are plenty of situations where it could be used: pre-filled form in PDF for print, configuration file for new VPN, certificate or actual version of phone list. I will introduce you this functionality in this article. You will learn how to use it and we will look how to create instance of class MimeMessage, which is used for sending e-mails from Java.

Application Class

Identity Manager CzechIdM has 3 standard layers – data, application and presentation layer. Sending e-mails is of course in application layer – this service is mostly provided to processes, which are written specially for customer. Universal interface of application layer for customer’s processes is Application class. In this class are a lot of useful static methods used by programmers and administrators, from logging to audit log to checking the rights of logged user.

For sending e-mails there are two static methods: sendEmailToIdentity and sendEmailToAddress. Both of them are overloaded, therefore they exist in more versions with different number of arguments. We will discuss only those most general which are using the biggest number of arguments. They’re:

Application.sendEmailToIdentity(String userName, String emailTemplate, Map params, String language, List<EmailAttachment> attachments)
Application.sendEmailToAddress(String address, String emailTemplate, Map params, String language, List<EmailAttachment> attachments

Calling of methods

Argument userName or address defines addressee of the message (by name of identity in CzechIdM or directly by e-mail address), emailTemplate defines template, which is used to assemble message and params is for attributes of message, which will be input into the template. With argument language you can choose language for the situation, when template exists in more language versions. If you input null, the first found template is choosed. Last argument – attachments – is new and is for list of attachments to send.

Instance of class EmailAttachment stands for one attachment. CzechIdM can send attachments in two ways – it can send existing file from disc or dynamically generated array of bytes. Class EmailAttachment represents only encapsulated information about one attachment, as programmer or administrator you can go with 2 constructors:

EmailAttachment(String path, String fileName)
EmailAttachment(byte[] bytes, String mimeType, String fileName)

First is for attachment saved in existing file at disc (path to file is in argument path), second is for sending array of bytes (argument bytes). You can rename attachment with the argument fileName for the addressee. Argument mimeType enable closer specification, how the bytes should be interpreted – picture, text, video…

Example

Following code sends attachment by both methods, as array of bytes and as existing file from disc:

import eu.bcvsolutions.idm.app.Application;
import eu.bcvsolutions.idm.app.email.EmailAttachment;
HashMap params = new HashMap();

    //mapa parametru. Temito parametry bude doplnena e-mailova sablona, #{attr1} v sablone bude nahrazeno retezcem "val1"
    params.put("attr1", "val1");
    params.put("attr2", "val2");
    params.put("attr3", "val3");

    //seznam priloh, ktere v mailu odesleme
    List attachments = new ArrayList();
    //prilohy lze pridat dvema zpusoby - bud primym predanim cesty k souboru a nazvu, pod jakym ma byt predan uzivateli
    EmailAttachment attach1 = new EmailAttachment("/opt/attachments/ahoj.txt", "ahoj.txt");
    //nebo primym predanim pole bytu vcetne mime typu a nazvu souboru
    byte[] bytes = {0x41, 0x48, 0x4F, 0x4A};
    EmailAttachment attach2 = new EmailAttachment(bytes, "text/plain", "ahoj.txt");

    attachments.add(attach1);
    attachments.add(attach2);

    Application.sendEmailToAddress("moje.adresa@test.com", "sablonaTestovaci", params, "cz", attachments);

How it works

The most important part of code is assembling MimeMessage, instance of class, which will be subsequently send. In CzechIdM is this task processed by old method createMimeMessage in class IdMMailerQueueListener. Unusual is using of class Multipart, which enables completing message from more parts, while some of them are mentioned attachments:

private MimeMessage createMimeMessage(Session session, MapMessage mapMessage) throws AddressException, MessagingException, JMSException {
        Charset charset = Charset.forName("UTF-8");

        MimeMessage mimeMessage = new MimeMessage(session);
        mimeMessage.setFrom(new InternetAddress(mapMessage.getString(Constants.EMAIL_FROM)));

        InternetAddress [] recipients = { new InternetAddress(mapMessage.getString(Constants.EMAIL_TO)) };
        mimeMessage.setRecipients(javax.mail.Message.RecipientType.TO, recipients);
        mimeMessage.setSubject(mapMessage.getString(Constants.EMAIL_SUBJECT), charset.name());
        mimeMessage.setSentDate(new java.util.Date());

        Multipart multipart = new MimeMultipart();
        // cast s textem
        MimeBodyPart messageBodyPart = new MimeBodyPart();
        //naplnim cast textem
        messageBodyPart.setText(mapMessage.getString(Constants.EMAIL_CONTENT), charset.name());
        messageBodyPart.setHeader("Content-Type", mapMessage.getString(Constants.EMAIL_CONTENT_TYPE) + "; charset=" + charset.name());
        multipart.addBodyPart(messageBodyPart);

        //zpracovani priloh, ktere jsou z technickych duvodu predany serializovane
        byte[] serializedList = mapMessage.getBytes(Constants.EMAIL_ATTACHMENTS);
        ObjectInputStream ois = null;
        List&lt;EmailAttachment&gt; attachs = new ArrayList&lt;EmailAttachment&gt;();
        if (serializedList != null) {
            try {
                ois = new ObjectInputStream(new ByteArrayInputStream(serializedList));
                attachs = (List&lt;EmailAttachment&gt;) ois.readObject();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
            e.printStackTrace();
            } finally {
                if (ois != null) {
                    try {
                        ois.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        //postupne pridam do zpravy vsechny prilohy, ktere mi byly zadany
        for (EmailAttachment attach : attachs) {
            messageBodyPart = new MimeBodyPart();
            DataSource source = null;
            //podle typu prilohy se rozhodnu, jak budu nacitat data
            switch(attach.getType()) {
            case FILE:
                File attachment = new File(attach.getFilePath());
                if (!attachment.canRead() || attachment.isDirectory() || attachment.isHidden()) {
                    Application.logError("Attachment " + attachment.getAbsolutePath() + " was not sent!", new Object[0]);
                    throw new RuntimeException("Attachment failed: " + attach.getFilePath());
                }
                source = new FileDataSource(attachment);
                break;
            case BYTES:
                source = new ByteArrayDataSource(attach.getBytes(), attach.getMimeType());
                break;
            default:
                throw new RuntimeException("Unknown EmailAttachment Type " + attach.getType());
            }

            messageBodyPart.setDataHandler(new DataHandler(source));
            messageBodyPart.setFileName(attach.getFileName());
            multipart.addBodyPart(messageBodyPart);
        }

        // pridam vsechny casti do zpravy
        mimeMessage.setContent(multipart);

        mimeMessage.saveChanges();
//zprava je pripravena k odeslani
        return mimeMessage;
    }

Conclusion

In this article we taught you how to send e-mail with attachment through CzechIdM. You also have chance to see one of the key procedures of application layer, which is using usual mechanisms of Java.

Leave a Reply