From 153204bad7396e3dc0018e4c885a9ca4e00c44e8 Mon Sep 17 00:00:00 2001 From: BLasan Date: Tue, 27 Apr 2021 23:44:49 +0530 Subject: [PATCH] Fix email sending using smtp (FINERACT-1070) --- build.gradle | 1 + fineract-provider/dependencies.gradle | 14 ++++-- ...icesPropertiesReadPlatformServiceImpl.java | 6 +-- .../GmailBackedPlatformEmailService.java | 46 +++++++++++-------- .../V265__modify_external_service_schema.sql | 2 +- 5 files changed, 42 insertions(+), 27 deletions(-) diff --git a/build.gradle b/build.gradle index 7cc60fb3d..70be440e0 100644 --- a/build.gradle +++ b/build.gradle @@ -138,6 +138,7 @@ allprojects { dependency 'org.mock-server:mockserver-junit-jupiter:5.11.2' dependency 'org.webjars.npm:swagger-ui-dist:3.47.1' dependency 'org.webjars:webjars-locator-core:0.46' + dependency 'org.springframework.boot:spring-boot-starter-mail:2.3.4.RELEASE' // fineract client dependencies dependency "com.squareup.retrofit2:retrofit:$retrofitVersion" diff --git a/fineract-provider/dependencies.gradle b/fineract-provider/dependencies.gradle index 2337e3265..12c49e793 100644 --- a/fineract-provider/dependencies.gradle +++ b/fineract-provider/dependencies.gradle @@ -68,9 +68,6 @@ dependencies { 'com.github.spullara.mustache.java:compiler', 'com.jayway.jsonpath:json-path', - // JAX-B dependencies for JDK 9+ - 'jakarta.xml.bind:jakarta.xml.bind-api', - 'org.dom4j:dom4j', 'javax.cache:cache-api', @@ -80,8 +77,12 @@ dependencies { 'org.webjars:webjars-locator-core', 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.2.2', - 'com.squareup.retrofit2:converter-gson' + 'com.squareup.retrofit2:converter-gson', + 'com.sun.activation:jakarta.activation:1.2.2' ) + implementation ('jakarta.xml.bind:jakarta.xml.bind-api') { + exclude group: 'jakarta.activation' + } implementation ('org.apache.activemq:activemq-broker') { exclude group: 'org.apache.geronimo.specs' } @@ -114,7 +115,7 @@ dependencies { // Although fineract (at the time of writing) doesn't have any compile time dep. on httpclient, // it's useful to have this for the Spring Boot TestRestTemplate http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-rest-templates-test-utility - 'org.apache.httpcomponents:httpclient', + 'org.apache.httpcomponents:httpclient' ) // testCompile dependencies are ONLY used in src/test, not src/main. @@ -128,5 +129,8 @@ dependencies { testImplementation ('org.springframework.boot:spring-boot-starter-test') { exclude group: 'com.jayway.jsonpath', module: 'json-path' exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' + exclude group: 'jakarta.activation' + exclude group: 'javax.activation' } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java index 2b8e5b733..8bde32705 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java @@ -72,7 +72,7 @@ public class ExternalServicesPropertiesReadPlatformServiceImpl implements Extern String username = null; String password = null; String host = null; - String port = "25"; + String port = "587"; boolean useTLS = false; String fromEmail = null; String fromName = null; @@ -83,12 +83,12 @@ public class ExternalServicesPropertiesReadPlatformServiceImpl implements Extern if (ExternalServicesConstants.SMTP_USERNAME.equalsIgnoreCase(name)) { username = value; + } else if (ExternalServicesConstants.SMTP_PORT.equalsIgnoreCase(port)) { + port = value; } else if (ExternalServicesConstants.SMTP_PASSWORD.equalsIgnoreCase(name)) { password = value; } else if (ExternalServicesConstants.SMTP_HOST.equalsIgnoreCase(name)) { host = value; - } else if (ExternalServicesConstants.SMTP_PORT.equalsIgnoreCase(name)) { - port = value; } else if (ExternalServicesConstants.SMTP_USE_TLS.equalsIgnoreCase(name)) { useTLS = Boolean.parseBoolean(value); } else if (ExternalServicesConstants.SMTP_FROM_EMAIL.equalsIgnoreCase(name)) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/GmailBackedPlatformEmailService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/GmailBackedPlatformEmailService.java index 321fa74ca..318355036 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/GmailBackedPlatformEmailService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/GmailBackedPlatformEmailService.java @@ -18,14 +18,13 @@ */ package org.apache.fineract.infrastructure.core.service; -import org.apache.commons.mail.DefaultAuthenticator; -import org.apache.commons.mail.Email; -import org.apache.commons.mail.EmailException; -import org.apache.commons.mail.SimpleEmail; +import java.util.Properties; import org.apache.fineract.infrastructure.configuration.data.SMTPCredentialsData; import org.apache.fineract.infrastructure.configuration.service.ExternalServicesPropertiesReadPlatformService; import org.apache.fineract.infrastructure.core.domain.EmailDetail; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.stereotype.Service; @Service @@ -55,31 +54,42 @@ public class GmailBackedPlatformEmailService implements PlatformEmailService { @Override public void sendDefinedEmail(EmailDetail emailDetails) { - final Email email = new SimpleEmail(); final SMTPCredentialsData smtpCredentialsData = this.externalServicesReadPlatformService.getSMTPCredentials(); final String authuser = smtpCredentialsData.getUsername(); final String authpwd = smtpCredentialsData.getPassword(); - // Very Important, Don't use email.setAuthentication() - email.setAuthenticator(new DefaultAuthenticator(authuser, authpwd)); - email.setDebug(false); // true if you want to debug - email.setHostName(smtpCredentialsData.getHost()); + final JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost(smtpCredentialsData.getHost()); // smtp.gmail.com + mailSender.setPort(Integer.parseInt(smtpCredentialsData.getPort())); // 587 + + // Important: Enable less secure app access for the gmail account used in the following authentication + + mailSender.setUsername(authuser); // use valid gmail address + mailSender.setPassword(authpwd); // use password of the above gmail account + + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", "true"); + props.put("mail.debug", "true"); try { if (smtpCredentialsData.isUseTLS()) { - // FINERACT-1070: NOT email.setSSLOnConnect(true); email.setSslSmtpPort(smtpCredentialsData.getPort()); - email.setStartTLSRequired(true); + // Needs to disable startTLS if the port is 465 in order to send the email successfully when using the + // smtp.gmail.com as the host + if (smtpCredentialsData.getPort().equals("465")) { + props.put("mail.smtp.starttls.enable", "false"); + } } - email.setSmtpPort(Integer.parseInt(smtpCredentialsData.getPort())); - email.setFrom(smtpCredentialsData.getFromEmail(), smtpCredentialsData.getFromName()); - email.setSubject(emailDetails.getSubject()); - email.setMsg(emailDetails.getBody()); + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(smtpCredentialsData.getFromEmail()); // same email address used for the authentication + message.setTo(emailDetails.getAddress()); + message.setSubject(emailDetails.getSubject()); + message.setText(emailDetails.getBody()); + mailSender.send(message); - email.addTo(emailDetails.getAddress(), emailDetails.getContactName()); - email.send(); - } catch (EmailException e) { + } catch (Exception e) { throw new PlatformEmailSendException(e); } } diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql index e2c7bf240..b4e8d2c0f 100644 --- a/fineract-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql @@ -55,7 +55,7 @@ insert into c_external_service_properties (`name`, `value`, `external_service_id insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('host', 'smtp.gmail.com', (select id from c_external_service where name = 'SMTP_Email_Account')); -insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('port', '25', (select id from c_external_service where name = 'SMTP_Email_Account')); +insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('port', '587', (select id from c_external_service where name = 'SMTP_Email_Account')); insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('useTLS', 'true', (select id from c_external_service where name = 'SMTP_Email_Account'));