// Path: src/main/java/com/jipasoft/task/AsyncMailSender.java
// public class AsyncMailSender extends JavaMailSenderImpl {
// 
// 	@Async
// 	@Override
// 	public void send(SimpleMailMessage simpleMessage) throws MailException {
// 		super.send(simpleMessage);
// 	}
// 
// 	@Async
// 	@Override
// 	public void send(SimpleMailMessage... simpleMessages) throws MailException {
// 		super.send(simpleMessages);
// 	}
// }
// 
// Path: src/main/java/com/jipasoft/task/ExceptionAspect.java
// @Slf4j
// @Aspect
// @Component
// public class ExceptionAspect {
// 
// 	@Inject
// 	private MailSender mailSender;
// 	@Value("${spring.user.email}")
// 	private String[] to;
// 
// 	@Pointcut("within(com.jipasoft.web..*)")
// 	public void mailingPointcut() {
// 	}
// 
// 	@AfterThrowing(pointcut = "mailingPointcut()", throwing = "e")
// 	public void mailAfterThrowing(JoinPoint joinPoint, Throwable e) {
// 		// @formatter:off
// 		// Building stack trace string
// 		StringWriter stackTrace = new StringWriter();
// 		e.printStackTrace(new PrintWriter(stackTrace));
// 		// Building e-mail
// 		SimpleMailMessage email = new SimpleMailMessage();
// 		email.setTo(to);
// 		email.setSubject("[Spring Profiles Aspect] Exception in '" + joinPoint.getSignature().getName() + "' method");
// 		email.setText(
// 			"Exception in: " + joinPoint.getSignature().getName() + "\n\n" +
// 			"Class: " + joinPoint.getSignature().getDeclaringTypeName()  + "\n\n" +
// 			"Time: " + ZonedDateTime.now() + "\n\n" +
// 			"Message: " + e.getMessage() + "\n\n" +
// 			"StackTrace:\n" + stackTrace.getBuffer().toString()
// 		);
// 		// Sending e-mail
// 		try {
// 			this.mailSender.send(email);
// 		} catch (MailException mailException) {
// 			log.error(mailException.getMessage());
// 		}
// 	}
// }
// 
// Path: src/main/java/com/jipasoft/task/ExceptionInterceptor.java
// @Slf4j
// public class ExceptionInterceptor implements MethodInterceptor {
// 	@Inject
// 	private MailSender mailSender;
// 	@Value("${spring.user.email}")
// 	private String[] to;
// 
// 	@Override
// 	public Object invoke(MethodInvocation method) throws Throwable {
// 		Object result = null;
// 		try {
// 			result = method.proceed();
// 		} catch (Exception e) {
// 			// @formatter:off
// 			// Building stack trace string
// 			StringWriter stackTrace = new StringWriter();
// 			e.printStackTrace(new PrintWriter(stackTrace));
// 			// Building e-mail
// 			SimpleMailMessage email = new SimpleMailMessage();
// 			email.setTo(to);
// 			email.setSubject("[Spring Profiles] Exception in '" + method.getMethod().getName() + "' method");
// 			email.setText(
// 				"Exception in: " + method.getMethod().getName() + "\n\n" +
// 				"Class: " + method.getMethod().getDeclaringClass().getName() + "\n\n" +
// 				"Time: " + ZonedDateTime.now() + "\n\n" +
// 				"Message: " + e.getMessage() + "\n\n" +
// 				"StackTrace:\n" + stackTrace.getBuffer().toString()
// 			);
// 			// Sending e-mail
// 			try {
// 				this.mailSender.send(email);
// 			} catch (MailException mailException) {
// 				log.error(mailException.getMessage());
// 			}
// 			throw e;
// 			// @formatter:on
// 
// 		}
// 		return result;
// 	}
// }
// 
// Path: src/main/java/com/jipasoft/util/Profiles.java
// public class Profiles {
// 	public static final String H2 = "h2";
// 	public static final String POSTGRES = "postgres";
// 	public static final String MYSQL = "mysql";
// 	public static final String MONGO = "mongo";
// 	public static final String EMAIL = "email";
// 	public static final String HEROKU = "heroku";
// 	public static final String ASPECT = "aspect";
// }


import com.jipasoft.task.AsyncMailSender;
import com.jipasoft.task.ExceptionAspect;
import com.jipasoft.task.ExceptionInterceptor;
import com.jipasoft.util.Profiles;
import java.util.Map;
import java.util.Properties;
import javax.inject.Inject;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
		sender.setProtocol(this.mailProperties.getProtocol());
		if (this.mailProperties.getDefaultEncoding() != null) {
			sender.setDefaultEncoding(this.mailProperties.getDefaultEncoding().name());
		}
		if (!this.mailProperties.getProperties().isEmpty()) {
			sender.setJavaMailProperties(asProperties(this.mailProperties.getProperties()));
		}
	}

	private Properties asProperties(Map<String, String> source) {
		Properties properties = new Properties();
		properties.putAll(source);
		return properties;
	}

	@Bean
	public JavaMailSender mailSender() {
		JavaMailSenderImpl sender = new AsyncMailSender();

		applyProperties(sender);

		return sender;
	}

	/**
	 * Bean to intercept all application exceptions and queue them for asynchronous mail sending
	 * 
	 * @return ExceptionInterceptor
	 */
	// @Bean uncomment to enable
// Path: src/main/java/com/jipasoft/task/AsyncMailSender.java
// public class AsyncMailSender extends JavaMailSenderImpl {
// 
// 	@Async
// 	@Override
// 	public void send(SimpleMailMessage simpleMessage) throws MailException {
// 		super.send(simpleMessage);
// 	}
// 
// 	@Async
// 	@Override
// 	public void send(SimpleMailMessage... simpleMessages) throws MailException {
// 		super.send(simpleMessages);
// 	}
// }
// 
// Path: src/main/java/com/jipasoft/task/ExceptionAspect.java
// @Slf4j
// @Aspect
// @Component
// public class ExceptionAspect {
// 
// 	@Inject
// 	private MailSender mailSender;
// 	@Value("${spring.user.email}")
// 	private String[] to;
// 
// 	@Pointcut("within(com.jipasoft.web..*)")
// 	public void mailingPointcut() {
// 	}
// 
// 	@AfterThrowing(pointcut = "mailingPointcut()", throwing = "e")
// 	public void mailAfterThrowing(JoinPoint joinPoint, Throwable e) {
// 		// @formatter:off
// 		// Building stack trace string
// 		StringWriter stackTrace = new StringWriter();
// 		e.printStackTrace(new PrintWriter(stackTrace));
// 		// Building e-mail
// 		SimpleMailMessage email = new SimpleMailMessage();
// 		email.setTo(to);
// 		email.setSubject("[Spring Profiles Aspect] Exception in '" + joinPoint.getSignature().getName() + "' method");
// 		email.setText(
// 			"Exception in: " + joinPoint.getSignature().getName() + "\n\n" +
// 			"Class: " + joinPoint.getSignature().getDeclaringTypeName()  + "\n\n" +
// 			"Time: " + ZonedDateTime.now() + "\n\n" +
// 			"Message: " + e.getMessage() + "\n\n" +
// 			"StackTrace:\n" + stackTrace.getBuffer().toString()
// 		);
// 		// Sending e-mail
// 		try {
// 			this.mailSender.send(email);
// 		} catch (MailException mailException) {
// 			log.error(mailException.getMessage());
// 		}
// 	}
// }
// 
// Path: src/main/java/com/jipasoft/task/ExceptionInterceptor.java
// @Slf4j
// public class ExceptionInterceptor implements MethodInterceptor {
// 	@Inject
// 	private MailSender mailSender;
// 	@Value("${spring.user.email}")
// 	private String[] to;
// 
// 	@Override
// 	public Object invoke(MethodInvocation method) throws Throwable {
// 		Object result = null;
// 		try {
// 			result = method.proceed();
// 		} catch (Exception e) {
// 			// @formatter:off
// 			// Building stack trace string
// 			StringWriter stackTrace = new StringWriter();
// 			e.printStackTrace(new PrintWriter(stackTrace));
// 			// Building e-mail
// 			SimpleMailMessage email = new SimpleMailMessage();
// 			email.setTo(to);
// 			email.setSubject("[Spring Profiles] Exception in '" + method.getMethod().getName() + "' method");
// 			email.setText(
// 				"Exception in: " + method.getMethod().getName() + "\n\n" +
// 				"Class: " + method.getMethod().getDeclaringClass().getName() + "\n\n" +
// 				"Time: " + ZonedDateTime.now() + "\n\n" +
// 				"Message: " + e.getMessage() + "\n\n" +
// 				"StackTrace:\n" + stackTrace.getBuffer().toString()
// 			);
// 			// Sending e-mail
// 			try {
// 				this.mailSender.send(email);
// 			} catch (MailException mailException) {
// 				log.error(mailException.getMessage());
// 			}
// 			throw e;
// 			// @formatter:on
// 
// 		}
// 		return result;
// 	}
// }
// 
// Path: src/main/java/com/jipasoft/util/Profiles.java
// public class Profiles {
// 	public static final String H2 = "h2";
// 	public static final String POSTGRES = "postgres";
// 	public static final String MYSQL = "mysql";
// 	public static final String MONGO = "mongo";
// 	public static final String EMAIL = "email";
// 	public static final String HEROKU = "heroku";
// 	public static final String ASPECT = "aspect";
// }


// Path: src/main/java/com/jipasoft/config/AspectConfig.java
import com.jipasoft.task.AsyncMailSender;
import com.jipasoft.task.ExceptionAspect;
import com.jipasoft.task.ExceptionInterceptor;
import com.jipasoft.util.Profiles;
import java.util.Map;
import java.util.Properties;
import javax.inject.Inject;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

		sender.setProtocol(this.mailProperties.getProtocol());
		if (this.mailProperties.getDefaultEncoding() != null) {
			sender.setDefaultEncoding(this.mailProperties.getDefaultEncoding().name());
		}
		if (!this.mailProperties.getProperties().isEmpty()) {
			sender.setJavaMailProperties(asProperties(this.mailProperties.getProperties()));
		}
	}

	private Properties asProperties(Map<String, String> source) {
		Properties properties = new Properties();
		properties.putAll(source);
		return properties;
	}

	@Bean
	public JavaMailSender mailSender() {
		JavaMailSenderImpl sender = new AsyncMailSender();

		applyProperties(sender);

		return sender;
	}

	/**
	 * Bean to intercept all application exceptions and queue them for asynchronous mail sending
	 * 
	 * @return ExceptionInterceptor
	 */
	// @Bean uncomment to enable
	public ExceptionInterceptor exceptionInterceptor() {