6.10.  Validate PDF as Mail Attachment

Initial Situation

Your company sends monthly electronic invoices to customers via email.

Problem

How can you ensure that the PDF document in the email is valid?

There are two problems which need to be solved. First, an email has to be sent during the test. And second, the attachment of the received email has to be analyzed.

Solution Approach

The first problem can be solved using Dumbster, a Java-API for testing mail applications. The second problem can be solved using PDFUnit. The important step is that the attached PDF document is given as a byte-array to PDFUnit.

Solution

/**
 * This test invokes a business system which sends a mail with a PDF attachment.
 * After sending the mail the PDF file is validated using PDFUnit.
 */
@Test
public void verifyPDFReceivedByEmail() throws Exception {
  // Arrange:
  BusinessSystem myBusinessSystem = BusinessSystem.newInstance();
  
  // Act:
  myBusinessSystem.doSomethingImportant();
  myBusinessSystem.sendMailWithPDFAttachment();
  
  // Assert:
  String pdfFileName = myBusinessSystem.getAttachedPDFName();
  byte[] attachmentAsByteArray = ReceiveMailHelper.getInstance(server)
                                                  .getAttachmentFromLastMail(pdfFileName);
  DocumentValidator pdfDocument = AssertThat.document(attachmentAsByteArray);
  pdfDocument.hasNumberOfPages(4);
  pdfDocument.restrictedTo(EVERY_PAGE)
             .hasText()
             .containing("http://pdfunit.com")
  ;
}

Here are the remaining lines of the test:

/**
 * Validation of a PDF document received by email.
 * This example uses <a href="https://github.com/rjo1970/dumbster.git">dumbster</a>,
 * as a mail testing API.
 * 
 * @author Carsten Siedentop, August 2014
 */
public class MailWithPDFAttachmentTest {

  private SmtpServer server;
  
  @Before
  public void createEmptyMailStoreDirectory() throws Exception {
    ServerOptions options = new ServerOptions();
    options.port = SendMailHelper.SMTP_PORT;
    options.threaded = false;
    server = SmtpServerFactory.startServer(options);
  }

  @After
  public void teardown() {
    server.stop();
  }

  // @Test
  // public void verifyPDFReceivedByEmail()...
  
}

In addition to this simple test, it is also possible to validate, say, invoice data from ZUGFeRD. For example, the next test checks that the IBAN value of the ZUGFeRD data is the same as the IBAN value on the first page of the document.

...
XMLNode nodeIBAN = new XMLNode("ram:IBANID");
PageRegion regionIBAN = createRegionIBAN();

DocumentValidator pdfDocument = AssertThat.document(pdfStream);
pdfDocument.restrictedTo(FIRST_PAGE)
           .restrictedTo(regionIBAN)
           .hasText()
           .containingZugferdData(nodeIBAN)
;
...