Newer
Older
marking / src / main / java / report / SendReport.java
package report;

import com.sun.mail.util.MailConnectException;
import dao.MarkingProperties;
import dao.ResultDAO;
import io.github.resilience4j.core.IntervalFunction;
import io.github.resilience4j.retry.Retry;
import io.github.resilience4j.retry.RetryConfig;
import io.github.resilience4j.retry.RetryRegistry;
import jakarta.activation.FileDataSource;
import jakarta.mail.AuthenticationFailedException;
import java.awt.Window;
import java.net.ConnectException;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import model.Student;
import org.simplejavamail.MailException;
import org.simplejavamail.api.email.Email;
import org.simplejavamail.api.mailer.Mailer;
import org.simplejavamail.api.mailer.config.TransportStrategy;
import org.simplejavamail.email.EmailBuilder;
import org.simplejavamail.mailer.MailerBuilder;

import static report.TimeStamp.getTimeStamp;
import ui.BatchMailer;

/**
 *
 * @author Mark George <mark.george@otago.ac.nz>
 */
public class SendReport {

	private static String password = null;
	private static Window parent;

	public SendReport(Window parent) {
		SendReport.parent = parent;
	}

	public Boolean sendReport(Student student, String reportFileName, Boolean batch) throws AuthenticationFailedException, ConnectException {

		String assessment = MarkingProperties.assessmentDescription();
		String file = MarkingProperties.attachmentEmailName();

		String mName = MarkingProperties.markerName();
		String mEmail = MarkingProperties.markerEmail();
		String ccEmail = MarkingProperties.ccEmail();
		String mCode = MarkingProperties.paperCode();

		String message
			= "Hi " + student.getFirstName() + ".\n"
			+ "\n"
			+ "Here is our feedback from marking your " + mCode + " " + assessment + " submission.  The feedback is in the attached PDF document.\n"
			+ "\n"
			+ "Cheers,\n"
			+ mName;

		Email email = EmailBuilder.startingBlank()
			.from(mName, mEmail)
			.to(student.getEmail())
			.cc(ccEmail)
			.withSubject(mCode + " " + assessment + " Result")
			.withPlainText(message)
			.withAttachment(file, new FileDataSource(reportFileName))
			.buildEmail();

		try {

			String userName = MarkingProperties.smtpUserName();

			if (password == null && userName != null) {
				String result = getPassword("Staff E-Mail Password");
				if (result != null) {
					password = result;
				} else {
					System.out.println("Cancelled");
					return false;
				}
			}

			TransportStrategy transport = TransportStrategy.SMTP;

			if (MarkingProperties.isTls()) {
				transport = TransportStrategy.SMTP_TLS;
			}

			RetryConfig cfg = RetryConfig.custom()
				.maxAttempts(10)
				.failAfterMaxAttempts(true)
				.intervalFunction(IntervalFunction.ofExponentialBackoff(5000, 2))
				.build();

			RetryRegistry registry = RetryRegistry.of(cfg);

			Retry retry = registry.retry("mailer");

			if (parent instanceof BatchMailer bm) {
				Retry.EventPublisher eventPublisher = retry.getEventPublisher();
				eventPublisher.onRetry(event -> bm.addMessage(getTimeStamp() + " -     Retry " + event.getNumberOfRetryAttempts() + " of " + cfg.getMaxAttempts()));
				eventPublisher.onSuccess(event -> bm.addMessage(getTimeStamp() + " -     Retry succeeded: "));
				eventPublisher.onEvent(event -> bm.addMessage(event.getLastThrowable().getCause().getClass().getName()));
			}

			Mailer mailer = MailerBuilder
				.withSMTPServer(MarkingProperties.smtpHost(), MarkingProperties.smtpPort(), userName, password)
				.withTransportStrategy(transport)
				.buildMailer();

			try {
				mailer.testConnection();
			} catch (MailException ex) {
				if (ex.getCause() instanceof AuthenticationFailedException) {
					JOptionPane.showMessageDialog(parent, "Authentication Failed!");
					password = null;
					throw new AuthenticationFailedException();
				} else if (ex.getCause() instanceof MailConnectException) {
					JOptionPane.showMessageDialog(parent, "Could not connect to SMTP server!");
					throw new ConnectException("Could not connect to server.  Check smtp.host in properties file.");
				}
			}

			if (parent instanceof BatchMailer bm) {
				bm.addMessage(getTimeStamp() + " - " + student.getUsername());
			}

			retry.executeRunnable(() -> {
				mailer.sendMail(email);
			});

			new ResultDAO().mailSent(student);

		} catch (MailException ex) {
			if (!batch) {
				password = null;
			}
			if (parent instanceof BatchMailer bm) {
				bm.addMessage(getTimeStamp() + " - RETRIES EXCEEDED!");
			}
			throw new SendException(ex);
		}

		return true;

	}

	public static String getPassword(String prompt) {
		JPasswordField txtPasswd = new JPasswordField();
		int resp = JOptionPane.showConfirmDialog(parent, txtPasswd, prompt,
			JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
		if (resp == JOptionPane.OK_OPTION) {
			return new String(txtPasswd.getPassword());
		}
		return null;
	}

}