private void writeBody(
     HttpClientRequest clientRequest,
     MailgunSendRequest sendRequest,
     Handler<AsyncResult<Void>> completionHandler) {
   EmailEntity emailEntity = sendRequest.getEmailEntity();
   if (emailEntity == null) {
     if (completionHandler != null) {
       completionHandler.handle(Future.failedFuture(new Exception("Null Email Entity.")));
     }
     return;
   }
   if (emailEntity.getFrom() == null || emailEntity.getFrom().isEmpty()) {
     if (completionHandler != null) {
       completionHandler.handle(Future.failedFuture(new Exception("Null or Empty From Field.")));
     }
     return;
   }
   if (emailEntity.getTo() == null || emailEntity.getTo().isEmpty()) {
     if (completionHandler != null) {
       completionHandler.handle(Future.failedFuture(new Exception("Null or Empty To Field.")));
     }
     return;
   }
   MultiPartUtility mpu = new MultiPartUtility();
   // from
   mpu.formField("from", emailEntity.getFrom());
   // to
   String[] toList = emailEntity.getTo().split(";|,|\\s");
   for (String to : toList) {
     mpu.formField("to", to);
   }
   // cc
   if (emailEntity.getCc() != null && !emailEntity.getCc().isEmpty()) {
     String[] ccList = emailEntity.getCc().split(";|,|\\s");
     for (String cc : ccList) {
       mpu.formField("cc", cc);
     }
   }
   // subject
   mpu.formField(
       "subject",
       (emailEntity.getSubject() == null ? "" : sendRequest.getEmailEntity().getSubject()));
   // text
   if (emailEntity.getTextBody() != null && !emailEntity.getTextBody().isEmpty()) {
     mpu.formField("text", emailEntity.getTextBody());
   }
   // html
   if (emailEntity.getHtmlBody() != null && !emailEntity.getHtmlBody().isEmpty()) {
     mpu.formField("html", emailEntity.getHtmlBody());
   }
   // write to client
   clientRequest.write(mpu.get());
 }
  private void sendEmail(final MailgunSendRequest sendRequest) {
    sendRequest.incrementAttempts();
    final HttpClientRequest clientRequest =
        client
            .post("/messages")
            .handler(new HttpResponseHandler(sendRequest))
            .exceptionHandler(throwable -> failure(sendRequest, throwable))
            .setChunked(true);
    clientRequest.putHeader(HttpHeaders.AUTHORIZATION, "api:" + apiKey);
    clientRequest.putHeader(
        HttpHeaders.CONTENT_TYPE,
        ContentType.MULTIPART_FORM_DATA.getMimeType() + "; boundary=" + MultiPartUtility.BOUNDARY);
    writeBodyObservable(clientRequest, sendRequest)
        .doOnError(
            throwable -> {
              if (sendRequest.getCompletionHandler() != null) {
                sendRequest.getCompletionHandler().handle(Future.failedFuture(throwable));
              }
            })
        .doOnNext(
            aVoid -> {
              if (sendRequest.getEmailEntity().isAttachments()) {
                getAttachmentEntitiesObservable(sendRequest.getEmailEntity())
                    .doOnError(throwable -> failure(sendRequest, throwable))
                    .doOnNext(
                        attachmentEntities ->
                            new FilePipeIterator(
                                    clientRequest,
                                    attachmentEntities.iterator(),
                                    new FileGetPipeHandler() {
                                      @Override
                                      public void onComplete() {
                                        clientRequest.end();
                                      }

                                      @Override
                                      public void onFailure(Throwable throwable) {
                                        failure(sendRequest, throwable);
                                      }
                                    })
                                .start());
              } else {
                clientRequest.end();
              }
            });
  }
 @Override
 public void handle(HttpClientResponse httpClientResponse) {
   if (httpClientResponse.statusCode() == HttpStatus.SC_OK) {
     httpClientResponse.bodyHandler(buffer -> totalBuffer.appendBuffer(buffer));
     httpClientResponse.endHandler(
         aVoid -> {
           try {
             MailgunSendResponse response =
                 jsonMapper.readValue(totalBuffer.toString(), MailgunSendResponse.class);
             if (response == null || response.getId() == null || response.getId().isEmpty()) {
               failure(sendRequest, new Exception("Invalid Response to Send Request"));
               return;
             }
             EmailEntity emailEntity = sendRequest.getEmailEntity();
             emailEntity.setMessageId(response.getId());
             updateRecords(emailEntity);
             publishEvent(emailEntity, true);
             success(sendRequest, emailEntity);
           } catch (Throwable throwable) {
             updateRecords(sendRequest.getEmailEntity());
             publishEvent(sendRequest.getEmailEntity(), false);
             failure(sendRequest, throwable);
           }
         });
   } else {
     if (sendRequest.getAttempts() < ALLOWED_ATTEMPTS) {
       sendEmail(sendRequest);
     } else {
       updateRecords(sendRequest.getEmailEntity());
       publishEvent(sendRequest.getEmailEntity(), false);
       failure(
           sendRequest,
           new Exception(
               "Failed to Send Email Using "
                   + ALLOWED_ATTEMPTS
                   + " Attempts with Response Code: "
                   + httpClientResponse.statusCode()));
     }
   }
 }