diff --git a/obp-api/pom.xml b/obp-api/pom.xml
index 867840a7c..9955f4ad7 100644
--- a/obp-api/pom.xml
+++ b/obp-api/pom.xml
@@ -101,11 +101,6 @@
commons-text
1.10.0
-
- org.apache.commons
- commons-email
- 1.5
-
org.postgresql
postgresql
@@ -524,6 +519,16 @@
test
+
+ com.sun.mail
+ jakarta.mail
+ 2.0.1
+
+
+ jakarta.activation
+ jakarta.activation-api
+ 2.0.1
+
com.sun.activation
jakarta.activation
diff --git a/obp-api/src/main/scala/code/api/util/CommonsEmailWrapper.scala b/obp-api/src/main/scala/code/api/util/CommonsEmailWrapper.scala
index d83657110..f4cf89b56 100644
--- a/obp-api/src/main/scala/code/api/util/CommonsEmailWrapper.scala
+++ b/obp-api/src/main/scala/code/api/util/CommonsEmailWrapper.scala
@@ -1,21 +1,21 @@
package code.api.util
import code.util.Helper.MdcLoggable
+import jakarta.activation.{DataHandler, FileDataSource, URLDataSource}
+import jakarta.mail._
+import jakarta.mail.internet._
import net.liftweb.common.{Box, Empty, Full}
-import org.apache.commons.mail._
+import java.io.File
import java.net.URL
+import java.util.Properties
/**
- * Apache Commons Email Wrapper for OBP-API
- * This wrapper provides a simple interface to send emails using Apache Commons Email
- * instead of Lift Web's Mailer
+ * Jakarta Mail Wrapper for OBP-API
+ * This wrapper provides a simple interface to send emails using Jakarta Mail
*/
object CommonsEmailWrapper extends MdcLoggable {
- /**
- * Email configuration case class
- */
case class EmailConfig(
smtpHost: String,
smtpPort: Int,
@@ -24,12 +24,9 @@ object CommonsEmailWrapper extends MdcLoggable {
useTLS: Boolean = true,
useSSL: Boolean = false,
debug: Boolean = false,
- tlsProtocols: String = "TLSv1.2" // TLS protocols to use
+ tlsProtocols: String = "TLSv1.2"
)
- /**
- * Email content case class
- */
case class EmailContent(
from: String,
to: List[String],
@@ -41,9 +38,12 @@ object CommonsEmailWrapper extends MdcLoggable {
attachments: List[EmailAttachment] = List.empty
)
- /**
- * Get default email configuration from OBP-API properties
- */
+ case class EmailAttachment(
+ filePath: Option[String] = None,
+ url: Option[String] = None,
+ name: Option[String] = None
+ )
+
def getDefaultEmailConfig(): EmailConfig = {
EmailConfig(
smtpHost = APIUtil.getPropsValue("mail.smtp.host", "localhost"),
@@ -57,46 +57,27 @@ object CommonsEmailWrapper extends MdcLoggable {
)
}
- /**
- * Send simple text email with default configuration
- */
def sendTextEmail(content: EmailContent): Box[String] = {
sendTextEmail(getDefaultEmailConfig(), content)
}
- /**
- * Send HTML email with default configuration
- */
def sendHtmlEmail(content: EmailContent): Box[String] = {
sendHtmlEmail(getDefaultEmailConfig(), content)
}
- /**
- * Send email with attachments using default configuration
- */
def sendEmailWithAttachments(content: EmailContent): Box[String] = {
sendEmailWithAttachments(getDefaultEmailConfig(), content)
}
- /**
- * Send a simple text email
- */
def sendTextEmail(config: EmailConfig, content: EmailContent): Box[String] = {
try {
logger.debug(s"Sending text email from ${content.from} to ${content.to.mkString(", ")}")
-
- val email = new SimpleEmail()
- configureEmail(email, config, content)
-
- // Set text content
- content.textContent match {
- case Some(text) => email.setMsg(text)
- case None => email.setMsg("")
- }
-
- val messageId = email.send()
- logger.debug(s"Email sent successfully with Message-ID: $messageId")
- Full(messageId)
+ val session = createSession(config)
+ val message = new MimeMessage(session)
+ setCommonHeaders(message, content)
+ message.setText(content.textContent.getOrElse(""), "UTF-8")
+ Transport.send(message)
+ Full(message.getMessageID)
} catch {
case e: Exception =>
logger.error(s"Failed to send text email: ${e.getMessage}", e)
@@ -104,28 +85,28 @@ object CommonsEmailWrapper extends MdcLoggable {
}
}
- /**
- * Send HTML email
- */
def sendHtmlEmail(config: EmailConfig, content: EmailContent): Box[String] = {
try {
logger.debug(s"Sending HTML email from ${content.from} to ${content.to.mkString(", ")}")
-
- val email = new HtmlEmail()
- configureEmail(email, config, content)
-
- // Set HTML content
- content.htmlContent match {
- case Some(html) => email.setHtmlMsg(html)
- case None => email.setHtmlMsg("No content")
+ val session = createSession(config)
+ val message = new MimeMessage(session)
+ setCommonHeaders(message, content)
+ val multipart = {
+ new MimeMultipart("alternative")
}
-
- // Set text content as fallback
- content.textContent.foreach(email.setTextMsg)
-
- val messageId = email.send()
- logger.debug(s"HTML email sent successfully with Message-ID: $messageId")
- Full(messageId)
+ content.textContent.foreach { text =>
+ val textPart = new MimeBodyPart()
+ textPart.setText(text, "UTF-8")
+ multipart.addBodyPart(textPart)
+ }
+ content.htmlContent.foreach { html =>
+ val htmlPart = new MimeBodyPart()
+ htmlPart.setContent(html, "text/html; charset=UTF-8")
+ multipart.addBodyPart(htmlPart)
+ }
+ message.setContent(multipart)
+ Transport.send(message)
+ Full(message.getMessageID)
} catch {
case e: Exception =>
logger.error(s"Failed to send HTML email: ${e.getMessage}", e)
@@ -133,25 +114,45 @@ object CommonsEmailWrapper extends MdcLoggable {
}
}
- /**
- * Send email with attachments
- */
def sendEmailWithAttachments(config: EmailConfig, content: EmailContent): Box[String] = {
try {
logger.debug(s"Sending email with attachments from ${content.from} to ${content.to.mkString(", ")}")
-
- val email = new MultiPartEmail()
- configureEmail(email, config, content)
-
- // Set text content
- content.textContent.foreach(email.setMsg)
-
+ val session = createSession(config)
+ val message = new MimeMessage(session)
+ setCommonHeaders(message, content)
+ val multipart = new MimeMultipart()
+ // Add text or HTML part
+ (content.htmlContent, content.textContent) match {
+ case (Some(html), _) =>
+ val htmlPart = new MimeBodyPart()
+ htmlPart.setContent(html, "text/html; charset=UTF-8")
+ multipart.addBodyPart(htmlPart)
+ case (None, Some(text)) =>
+ val textPart = new MimeBodyPart()
+ textPart.setText(text, "UTF-8")
+ multipart.addBodyPart(textPart)
+ case _ =>
+ val textPart = new MimeBodyPart()
+ textPart.setText("", "UTF-8")
+ multipart.addBodyPart(textPart)
+ }
// Add attachments
- content.attachments.foreach(email.attach)
-
- val messageId = email.send()
- logger.debug(s"Email with attachments sent successfully with Message-ID: $messageId")
- Full(messageId)
+ content.attachments.foreach { att =>
+ val attachPart = new MimeBodyPart()
+ if (att.filePath.isDefined) {
+ val fds = new FileDataSource(new File(att.filePath.get))
+ attachPart.setDataHandler(new DataHandler(fds))
+ attachPart.setFileName(att.name.getOrElse(new File(att.filePath.get).getName))
+ } else if (att.url.isDefined) {
+ val uds = new URLDataSource(new URL(att.url.get))
+ attachPart.setDataHandler(new DataHandler(uds))
+ attachPart.setFileName(att.name.getOrElse(att.url.get.split('/').last))
+ }
+ multipart.addBodyPart(attachPart)
+ }
+ message.setContent(multipart)
+ Transport.send(message)
+ Full(message.getMessageID)
} catch {
case e: Exception =>
logger.error(s"Failed to send email with attachments: ${e.getMessage}", e)
@@ -159,54 +160,34 @@ object CommonsEmailWrapper extends MdcLoggable {
}
}
- /**
- * Configure email with common settings
- */
- private def configureEmail(email: Email, config: EmailConfig, content: EmailContent): Unit = {
- // SMTP Configuration
- email.setHostName(config.smtpHost)
- email.setSmtpPort(config.smtpPort)
- email.setAuthenticator(new DefaultAuthenticator(config.username, config.password))
- email.setSSLOnConnect(config.useSSL)
- email.setStartTLSEnabled(config.useTLS)
- email.setDebug(config.debug)
- email.getMailSession.getProperties.setProperty("mail.smtp.ssl.protocols", config.tlsProtocols)
-
- // Set charset
- email.setCharset("UTF-8")
-
- // Set sender
- email.setFrom(content.from)
-
- // Set recipients
- content.to.foreach(email.addTo)
- content.cc.foreach(email.addCc)
- content.bcc.foreach(email.addBcc)
-
- // Set subject
- email.setSubject(content.subject)
+ private def createSession(config: EmailConfig): Session = {
+ val props = new Properties()
+ props.put("mail.smtp.host", config.smtpHost)
+ props.put("mail.smtp.port", config.smtpPort.toString)
+ props.put("mail.smtp.auth", "true")
+ props.put("mail.smtp.starttls.enable", config.useTLS.toString)
+ props.put("mail.smtp.ssl.enable", config.useSSL.toString)
+ props.put("mail.debug", config.debug.toString)
+ props.put("mail.smtp.ssl.protocols", config.tlsProtocols)
+ val authenticator = new Authenticator() {
+ override def getPasswordAuthentication: PasswordAuthentication =
+ new PasswordAuthentication(config.username, config.password)
+ }
+ Session.getInstance(props, authenticator)
}
- /**
- * Create email attachment from file
- */
- def createFileAttachment(filePath: String, name: Option[String] = None): EmailAttachment = {
- val attachment = new EmailAttachment()
- attachment.setPath(filePath)
- attachment.setDisposition(EmailAttachment.ATTACHMENT)
- name.foreach(attachment.setName)
- attachment
+ private def setCommonHeaders(message: MimeMessage, content: EmailContent): Unit = {
+ message.setFrom(new InternetAddress(content.from))
+ content.to.foreach(addr => message.addRecipient(Message.RecipientType.TO, new InternetAddress(addr)))
+ content.cc.foreach(addr => message.addRecipient(Message.RecipientType.CC, new InternetAddress(addr)))
+ content.bcc.foreach(addr => message.addRecipient(Message.RecipientType.BCC, new InternetAddress(addr)))
+ message.setSubject(content.subject, "UTF-8")
}
- /**
- * Create email attachment from URL
- */
- def createUrlAttachment(url: String, name: String): EmailAttachment = {
- val attachment = new EmailAttachment()
- attachment.setURL(new URL(url))
- attachment.setDisposition(EmailAttachment.ATTACHMENT)
- attachment.setName(name)
- attachment
- }
+ def createFileAttachment(filePath: String, name: Option[String] = None): EmailAttachment =
+ EmailAttachment(filePath = Some(filePath), url = None, name = name)
+
+ def createUrlAttachment(url: String, name: String): EmailAttachment =
+ EmailAttachment(filePath = None, url = Some(url), name = Some(name))
}
\ No newline at end of file