As of version 2.7.0.1 DidiSoft OpenPGP Library for Java provides a separate JAR file located under [product ZIP]\Library\Mail\pgplib-mail-<version>.jar and offering PGP/MIME email functionality.
In this tutorial we will illustrate how to utilize the classes located in the above JAR file in order to exchange PGP/MIME email messages with other systems that support this format (e.g. Symantec Messaging Gateway, Z1 SecureMail Gateway, Enigmail, etc.).
Online Javadoc is available here
Table of contents
1. Setup
2. Sending encrypted email
3. Receiving encrypted email
4. Signed email
5. Signed and encrypted email
Setup
You have to include the JAR files listed below in the class path of your Java application:
[product ZIP archive]\Library\Mail\pgplib-mail-x.x.x.jar
[product ZIP archive]\Library\Mail\javax.mail.jar – you can skip this file if it’s already in your classpath
2. Sending encrypted email
The main class offering PGP/MIME functionality is com.didisoft.pgp.mail.PGPMailUtils. It provides encrypting methods similar to the ones provided by PGPLib and works with keys located in files, provided as inline strings or located in a KeyStore.
The example below shows how to produce a javax.mail.internet.MimeMessage OpenPGP encrypted with a public key located in a file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; import com.didisoft.pgp.mail.PGPMailUtils; public class SendEncryptedMail { public static void main(String[] args) { // Recipient's email String to = "recipient@company.com"; // Sender email String from = "sender@didisoft.com"; Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", "mail.didisoft.com"); properties.setProperty("mail.smtp.port", "25"); properties.setProperty("mail.user", "sender@didisoft.com"); properties.setProperty("mail.password", "mail password"); // Get the default Session object. Session session = Session.getDefaultInstance(properties); try{ // Create a default MimeMessage object. MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // Set Subject: header field message.setSubject("This is the Subject Line!"); // Now set the actual message message.setText("This is actual message"); // PGP encrypt here the message PGPMailLib mailUtil = new PGPMailLib(); String publicKeyFileName = "c:\\Keys\\public_key.asc"; MimeMessage pgpMessage = mailUtil.encryptMessage(session, message, publicKeyFileName); // Send message Transport.send(pgpMessage); System.out.println("Sent message successfully...."); }catch (Exception ex) { ex.printStackTrace(); } } } |
1. Receiving encrypted mail
The receiving of PGP/MIME encrypted message consists of actually decrypting it and handling the extracted message like an ordinary received mail:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | import java.io.IOException; import java.util.Properties; import javax.activation.DataHandler; import javax.mail.*; import javax.mail.internet.*; import com.sun.mail.pop3.POP3Store; import com.didisoft.pgp.mail.*; public class ReceiveEncryptedMail { private boolean textIsHtml = false; /** Handling MIME parts */ private String getText(Part p) throws MessagingException, IOException { if (p.isMimeType("text/*")) { String s = (String) p.getContent(); textIsHtml = p.isMimeType("text/html"); return s; } if (p.isMimeType("multipart/alternative")) { // prefer html text over plain text Multipart mp = (Multipart) p.getContent(); String text = null; for (int i = 0; i < mp.getCount(); i++) { Part bp = mp.getBodyPart(i); if (bp.isMimeType("text/plain")) { if (text == null) text = getText(bp); continue; } else if (bp.isMimeType("text/html")) { String s = getText(bp); if (s != null) return s; } else { return getText(bp); } } return text; } else if (p.isMimeType("multipart/*")) { Multipart mp = (Multipart) p.getContent(); for (int i = 0; i < mp.getCount(); i++) { String s = getText(mp.getBodyPart(i)); if (s != null) return s; } } return null; } public void receiveEmail(String pop3Host, String user, String password) { try { Properties properties = new Properties(); properties.put("mail.pop3.host", pop3Host); Session emailSession = Session.getDefaultInstance(properties); //2) create the POP3 store object and connect with the pop server POP3Store emailStore = (POP3Store) emailSession.getStore("pop3"); emailStore.connect(user, password); //3) create the folder object and open it Folder emailFolder = emailStore.getFolder("INBOX"); emailFolder.open(Folder.READ_ONLY); //4) retrieve the messages from the folder in an array and print it Message[] messages = emailFolder.getMessages(); for (int i = 0; i < messages.length; i++) { Message message = messages[i]; System.out.println("Email Number " + (i + 1)); System.out.println("Subject: " + message.getSubject()); System.out.println("From: " + message.getFrom()[0]); PGPMailLib mailUtil = new PGPMailLib(); if (mailUtil.isOpenPGPEncrypted(message)) { try { MimeMessage decrypted = mailUtil.decryptMessage(emailSession, (MimeMessage)message, "c:\\PGPKeys\\private_key.asc", "changeit"); Object decryptedRawContent = decrypted.getContent(); if (decryptedRawContent instanceof Multipart) { Multipart multipart = (Multipart) decryptedRawContent; BodyPart bodyPart = multipart.getBodyPart(0); String messageText = getText(bodyPart); System.out.print("Decrypted message: "); System.out.println(messageText); if (mailUtil.hasAttachments(decrypted)) { for (int j = 1; j < multipart.getCount(); j++) { BodyPart attachment = multipart.getBodyPart(j); DataHandler handler = attachment.getDataHandler(); System.out.println("Attachment file name is : " + handler.getName()); // save here the file ... ((MimeBodyPart)attachment).saveFile(...) } } } else { // pgp inline mail with no attachments, just print the decrypted text then String content = decryptedRawContent.toString(); System.out.println(content); } } catch (Exception e) { System.out.println(e.getMessage()); } } else if (mailUtil.isOpenPGPSigned(message)) { // pgp signed only message MimeBodyPart decrypted = mailUtil.getSignedContent(message); String content = getText(decrypted); System.out.println(content); } else { System.out.println(message.getContentType()); } } //5) close the store and folder objects emailFolder.close(false); emailStore.close(); } catch (NoSuchProviderException e) {e.printStackTrace();} catch (MessagingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} } public static void main(String[] a) { ReceiveEncryptedMail receiveDemo = new ReceiveEncryptedMail(); receiveDemo.receiveEmail("mail.mysite.com", "myname@mysite.com", "my mail password"); } } |
Sending PGP/MIME signed emails with Java
The sending of PGP/MIME signed email is quite easy with DidiSoft OpenPGP Library for Java. Again the whole process consists of constructing the initial email message as it should look like to the recipient and afterwards transforming it to PGP/MIME signed format transparently by invoking PGPMailLib.signMessage:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; import com.didisoft.pgp.mail.PGPMailLib; public class SendSignedMail { public static void main(String[] args) { // Recipient's email String to = "recipient@company.com"; // Sender email String from = "me@organization.com"; // SMTP host String host = "mail.organization.com"; Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", host); properties.setProperty("mail.smtp.port", "25"); properties.setProperty("mail.user", from); properties.setProperty("mail.password", "my SMTP password"); // Get the default Session object. Session session = Session.getDefaultInstance(properties); try{ // Create a default MimeMessage object. MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // Set Subject: header field message.setSubject("This is the Subject Line!"); // Now set the actual message message.setText("This is the actual message"); // PGP encrypt here the message PGPMailLib mailUtil = new PGPMailLib(); String privateKeyFileName = "examples/DataFiles/private.key"; String privateKeyPassword = "changeit"; MimeMessage pgpMessage = mailUtil.signMessage(session, message, privateKeyFileName, privateKeyPassword); // Send message Transport.send(pgpMessage); System.out.println("Sent message successfully...."); }catch (com.didisoft.pgp.PGPException ex) { ex.printStackTrace(); // PGP error }catch (java.io.IOException ex) { ex.printStackTrace(); // I/O error }catch (MessagingException mex) { mex.printStackTrace(); // Mail transport error } } } |
Sending PGP/MIME signed and encrypted emails with Java
Signed and encrypted PGP/MIME email according to the PGP/MIME specification can be first signed and then encrypted or using the OpenPGP signed and encrypted format. The PGPMailLib.signAndEncryptMessage method produces OpenPGP signed and encrypted format:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; import com.didisoft.pgp.mail.PGPMailLib; public class SendSignedMail { public static void main(String[] args) { // Recipient's email String to = "recipient@company.com"; // Sender email String from = "me@organization.com"; // SMTP host String host = "mail.organization.com"; Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", host); properties.setProperty("mail.smtp.port", "25"); properties.setProperty("mail.user", from); properties.setProperty("mail.password", "my SMTP password"); // Get the default Session object. Session session = Session.getDefaultInstance(properties); try{ // Create a default MimeMessage object. MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // Set Subject: header field message.setSubject("This is the Subject Line!"); // Now set the actual message message.setText("This is the actual message"); // PGP encrypt here the message PGPMailLib mailUtil = new PGPMailLib(); String privateKeyFileName = "examples/DataFiles/private.key"; String privateKeyPassword = "changeit"; String publicKeyFileName = "examples/DataFiles/public.key"; MimeMessage pgpMessage = mailUtil.signAndEncryptMessage(session, message, privateKeyFileName, privateKeyPassword, publicKeyFileName); // Send message Transport.send(pgpMessage); System.out.println("Sent message successfully...."); }catch (com.didisoft.pgp.PGPException ex) { ex.printStackTrace(); // PGP error }catch (java.io.IOException ex) { ex.printStackTrace(); // I/O error }catch (MessagingException mex) { mex.printStackTrace(); // Mail transport error } } } |
Summary
This article demonstrated the basics of the PGP/MIME functionality provided by OpenPGP Library for Java. These functions are provided by the com.didisoft.pgp.mail.PGPMailUtils class located in additional JAR file.