DefaultMailCreator implements MailCreator { @Override public boolean createErrorEmail(final ExecutableFlow flow, final List<ExecutableFlow> pastExecutions, final EmailMessage message, final String azkabanName, final String scheme, final String clientHostname, final String clientPortNumber, final String... reasons) { final ExecutionOptions option = flow.getExecutionOptions(); final List<String> emailList = option.getFailureEmails(); final int execId = flow.getExecutionId(); if (emailList != null && !emailList.isEmpty()) { message.addAllToAddress(emailList); message.setMimeType("text/html"); message.setSubject("Flow '" + flow.getFlowId() + "' has failed on " + azkabanName); message.println("<h2 style=\"color:#FF0000\"> Execution '" + execId + "' of flow '" + flow.getFlowId() + "' of project '" + flow.getProjectName() + "' has failed on " + azkabanName + "</h2>"); message.println("<table>"); message.println("<tr><td>Start Time</td><td>" + TimeUtils.formatDateTimeZone(flow.getStartTime()) + "</td></tr>"); message.println("<tr><td>End Time</td><td>" + TimeUtils.formatDateTimeZone(flow.getEndTime()) + "</td></tr>"); message.println("<tr><td>Duration</td><td>" + TimeUtils.formatDuration(flow.getStartTime(), flow.getEndTime()) + "</td></tr>"); message.println("<tr><td>Status</td><td>" + flow.getStatus() + "</td></tr>"); message.println("</table>"); message.println(""); final String executionUrl = scheme + ": + "executor?" + "execid=" + execId; message.println("<a href=\"" + executionUrl + "\">" + flow.getFlowId() + " Execution Link</a>"); message.println(""); message.println("<h3>Reason</h3>"); final List<String> failedJobs = findFailedJobs(flow); message.println("<ul>"); for (final String jobId : failedJobs) { message.println("<li><a href=\"" + executionUrl + "&job=" + jobId + "\">Failed job '" + jobId + "' Link</a></li>"); } for (final String reason : reasons) { message.println("<li>" + reason + "</li>"); } message.println("</ul>"); message.println(""); int failedCount = 0; for (final ExecutableFlow executableFlow : pastExecutions) { if (executableFlow.getStatus().equals(Status.FAILED)) { failedCount++; } } message.println(String.format("<h3>Executions from past 72 hours (%s out %s) failed</h3>", failedCount, pastExecutions.size())); for (final ExecutableFlow executableFlow : pastExecutions) { message.println("<table>"); message.println( "<tr><td>Execution Id</td><td>" + (executableFlow.getExecutionId()) + "</td></tr>"); message.println("<tr><td>Start Time</td><td>" + TimeUtils.formatDateTimeZone(executableFlow.getStartTime()) + "</td></tr>"); message.println("<tr><td>End Time</td><td>" + TimeUtils.formatDateTimeZone(executableFlow.getEndTime()) + "</td></tr>"); message.println("<tr><td>Status</td><td>" + executableFlow.getStatus() + "</td></tr>"); message.println("</table>"); } return true; } return false; }  static void registerCreator(final String name, final MailCreator creator); static MailCreator getCreator(final String name); @Override boolean createFirstErrorMessage(final ExecutableFlow flow,
      final EmailMessage message, final String azkabanName, final String scheme,
      final String clientHostname, final String clientPortNumber); @Override boolean createErrorEmail(final ExecutableFlow flow, final List<ExecutableFlow>
      pastExecutions, final EmailMessage message, final String azkabanName, final String scheme,
      final String clientHostname, final String clientPortNumber, final String... reasons); @Override boolean createSuccessEmail(final ExecutableFlow flow, final EmailMessage message,
      final String azkabanName, final String scheme, final String clientHostname,
      final String clientPortNumber); @Override boolean createFailedUpdateMessage(final List<ExecutableFlow> flows,
      final Executor executor, final ExecutorManagerException updateException,
      final EmailMessage message, final String azkabanName,
      final String scheme, final String clientHostname, final String clientPortNumber); @Override boolean createFailedExecutorHealthCheckMessage(final List<ExecutableFlow> flows,
      final Executor executor, final ExecutorManagerException failureException,
      final EmailMessage message, final String azkabanName,
      final String scheme, final String clientHostname, final String clientPortNumber,
      final List<String> emailList); static final String DEFAULT_MAIL_CREATOR; }
@Test public void createErrorEmail() throws Exception { setJobStatus(Status.FAILED); this.executableFlow.setEndTime(END_TIME_MILLIS); this.executableFlow.setStatus(Status.FAILED); final List<ExecutableFlow> executableFlows = new ArrayList<>(); final ExecutableFlow executableFlow1 = new ExecutableFlow(this.project, this.flow); executableFlow1.setExecutionId(1); executableFlow1.setStartTime(START_TIME_MILLIS); executableFlow1.setEndTime(END_TIME_MILLIS); executableFlow1.setStatus(Status.FAILED); executableFlows.add(executableFlow1); final ExecutableFlow executableFlow2 = new ExecutableFlow(this.project, this.flow); executableFlow2.setExecutionId(2); executableFlow2.setStartTime(START_TIME_MILLIS); executableFlow2.setEndTime(END_TIME_MILLIS); executableFlow2.setStatus(Status.SUCCEEDED); executableFlows.add(executableFlow2); assertTrue(this.mailCreator.createErrorEmail( this.executableFlow, executableFlows, this.message, this.azkabanName, this.scheme, this .clientHostname, this.clientPortNumber)); assertEquals("Flow 'mail-creator-test' has failed on unit-tests", this.message.getSubject()); assertThat(TestUtils.readResource("errorEmail.html", this)) .isEqualToIgnoringWhitespace(this.message.getBody()); }