As of version 1.3.2 DidiSoft OpenPGP Library for Android provides a separate JAR file located under [product ZIP]\Library\Mail\pgplib-mail-android-<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.
Prerequisites: Your Android application will require Internet access permissions in AndroidManifest.xml:
Table of contents
1. Setup
2. Sending encrypted email (PGP/MIME)
3. Sending encrypted email (PGP/inline)
4. Receiving encrypted email
5. Sending signed 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-android-x.x.x.jar
[product ZIP archive]\Library\Mail\pgplib-android-x.x.x.jar
[product ZIP archive]\Library\Mail\mail.jar
[product ZIP archive]\Library\Mail\activation.jar
[product ZIP archive]\Library\Mail\additional.jar
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 class 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 in encrypted PGP/MIME format using a public (encryption) key located in a file in the Assets folder of the application:
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 | import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; import com.didisoft.pgp.mail.PGPMailUtils; public class MailSendActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); setContentView(R.layout.activity_mail_send); // 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 PGPMailUtils mailUtil = new PGPMailUtils(); MimeMessage pgpMessage = null; InputStream keyStream = null; try { keyStream = getApplicationContext().getAssets().open("recipient_key.asc"); pgpMessage = mailUtil.encryptMessage(session, message, keyStream); } finally { if (keyStream != null) { keyStream.close(); } } // Send message Transport.send(pgpMessage); android.util.Log.e("PGP_DEMO", "Email sent", "Message successfully sent"); }catch (Exception ex) { android.util.Log.e("PGP_DEMO", "Error sending email", ex); } } } |
3. Sending encrypted email (PGP/inline)
The PGP/inline email message format is from the early days of PGP version 2.x. Technically it is an email with content type “text/plain” and message body containing the ASCII armored encrypted OpenPGP message. In order to create OpenPGP encrypted message in ASCII armored format we are going to use the com.didisoft.pgp.PGPLib class.
The example below shows how to produce a javax.mail.internet.MimeMessage in PGP/inline format encrypted with a public key located in a file in the Assets folder of the application:
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 | import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; import com.didisoft.pgp.PGPLib; public class MailSendActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); setContentView(R.layout.activity_mail_send); // 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!"); PGPLib pgp = new PGPLib(); String messageText = "This is my email message text \n\r Best Regards"; message.setText(pgp.encryptString(messageText, publicKeyFileName)); // Send message Transport.send(message); android.util.Log.e("PGP_DEMO", "Email sent", "Message successfully sent"); }catch (Exception ex) { android.util.Log.e("PGP_DEMO", "Error sending email", ex); } } } |
4. 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]); PGPMailUtils mailUtil = new PGPMailUtils(); 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"); } } |
5. Sending PGP/MIME signed emails with Java
Here 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 PGPMailUtils.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.PGPMailUtils; 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 PGPMailUtils mailUtil = new PGPMailUtils(); 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 } } } |
Summary
This article demonstrated the basics of the PGP/MIME functionality provided by OpenPGP Library for Android. These functions are provided by the com.didisoft.pgp.mail.PGPMailUtils class located in additional JAR file.