feature/used Apache Commons Email instead of LiftMail- step1

This commit is contained in:
hongwei 2025-08-05 10:40:02 +02:00
parent b6e8fd0ec1
commit ba36503a1e
3 changed files with 257 additions and 4 deletions

View File

@ -101,6 +101,12 @@
<artifactId>commons-text</artifactId>
<version>1.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-email -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>

View File

@ -0,0 +1,201 @@
package code.api.util
import org.apache.commons.mail.{Email, SimpleEmail, HtmlEmail, MultiPartEmail, EmailAttachment, DefaultAuthenticator}
import java.io.File
import java.net.URL
import code.util.Helper.MdcLoggable
import net.liftweb.common.{Box, Empty, Full}
import net.liftweb.util.Helpers.now
/**
* 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
*/
object CommonsEmailWrapper extends MdcLoggable {
/**
* Email configuration case class
*/
case class EmailConfig(
smtpHost: String,
smtpPort: Int,
username: String,
password: String,
useTLS: Boolean = true,
useSSL: Boolean = false,
debug: Boolean = false
)
/**
* Email content case class
*/
case class EmailContent(
from: String,
to: List[String],
cc: List[String] = List.empty,
bcc: List[String] = List.empty,
subject: String,
textContent: Option[String] = None,
htmlContent: Option[String] = None,
attachments: List[EmailAttachment] = List.empty
)
/**
* Send simple text email
*/
def sendTextEmail(config: EmailConfig, content: EmailContent): Box[String] = {
try {
logger.info(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.info(s"Email sent successfully with Message-ID: $messageId")
Full(messageId)
} catch {
case e: Exception =>
logger.error(s"Failed to send text email: ${e.getMessage}", e)
Empty
}
}
/**
* Send HTML email
*/
def sendHtmlEmail(config: EmailConfig, content: EmailContent): Box[String] = {
try {
logger.info(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("<html><body>No content</body></html>")
}
// Set text content as fallback
content.textContent.foreach(email.setTextMsg)
val messageId = email.send()
logger.info(s"HTML email sent successfully with Message-ID: $messageId")
Full(messageId)
} catch {
case e: Exception =>
logger.error(s"Failed to send HTML email: ${e.getMessage}", e)
Empty
}
}
/**
* Send email with attachments
*/
def sendEmailWithAttachments(config: EmailConfig, content: EmailContent): Box[String] = {
try {
logger.info(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)
// Add attachments
content.attachments.foreach(email.attach)
val messageId = email.send()
logger.info(s"Email with attachments sent successfully with Message-ID: $messageId")
Full(messageId)
} catch {
case e: Exception =>
logger.error(s"Failed to send email with attachments: ${e.getMessage}", e)
Empty
}
}
/**
* 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)
// 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)
}
/**
* 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
}
/**
* 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
}
/**
* Test MailHog configuration, this for testing
*/
def testMailHogConfig(): Unit = {
val config = EmailConfig(
smtpHost = "localhost",
smtpPort = 1025,
username = "",
password = "",
useTLS = false,
debug = true
)
val content = EmailContent(
from = "test@localhost",
to = List("receive@mailhog.local"),
subject = "Test MailHog with Apache Commons Email",
textContent = Some("This is a test email sent to MailHog using Apache Commons Email wrapper.")
)
logger.info("Testing MailHog configuration with Apache Commons Email...")
sendTextEmail(config, content) match {
case Full(messageId) => logger.info(s"MailHog email sent successfully: $messageId")
case Empty => logger.error("Failed to send MailHog email")
}
}
}

View File

@ -83,8 +83,8 @@ import net.liftweb.json.JsonDSL._
import net.liftweb.json.Serialization.write
import net.liftweb.json._
import net.liftweb.util.Helpers.{now, tryo}
import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To, XHTMLMailBodyType}
import net.liftweb.util.{Helpers, Mailer, StringHelpers}
import net.liftweb.util.{Helpers, StringHelpers}
import code.api.util.CommonsEmailWrapper._
import org.apache.commons.lang3.StringUtils
import java.net.URLEncoder
@ -3368,7 +3368,30 @@ trait APIMethods400 extends MdcLoggable {
.replace(WebUIPlaceholder.activateYourAccount, link)
logger.debug(s"customHtmlText: ${customHtmlText}")
logger.debug(s"Before send user invitation by email. Purpose: ${UserInvitationPurpose.DEVELOPER}")
Mailer.sendMail(From(from), Subject(subject), To(invitation.email), PlainMailBodyType(customText), XHTMLMailBodyType(XML.loadString(customHtmlText)))
// Use Apache Commons Email wrapper instead of Lift Mailer
val emailConfig = EmailConfig(
smtpHost = APIUtil.getPropsValue("mail.smtp.host", "localhost"),
smtpPort = APIUtil.getPropsValue("mail.smtp.port", "1025").toInt,
username = APIUtil.getPropsValue("mail.smtp.user", ""),
password = APIUtil.getPropsValue("mail.smtp.password", ""),
useTLS = APIUtil.getPropsValue("mail.smtp.starttls.enable", "false").toBoolean,
debug = APIUtil.getPropsValue("mail.debug", "false").toBoolean
)
val emailContent = EmailContent(
from = from,
to = List(invitation.email),
subject = subject,
textContent = Some(customText),
htmlContent = Some(customHtmlText)
)
sendHtmlEmail(emailConfig, emailContent) match {
case Full(messageId) => logger.debug(s"Email sent successfully with Message-ID: $messageId")
case Empty => logger.error("Failed to send user invitation email")
}
logger.debug(s"After send user invitation by email. Purpose: ${UserInvitationPurpose.DEVELOPER}")
} else {
val subject = getWebUiPropsValue("webui_customer_user_invitation_email_subject", "Welcome to the API Playground")
@ -3380,7 +3403,30 @@ trait APIMethods400 extends MdcLoggable {
.replace(WebUIPlaceholder.activateYourAccount, link)
logger.debug(s"customHtmlText: ${customHtmlText}")
logger.debug(s"Before send user invitation by email.")
Mailer.sendMail(From(from), Subject(subject), To(invitation.email), PlainMailBodyType(customText), XHTMLMailBodyType(XML.loadString(customHtmlText)))
// Use Apache Commons Email wrapper instead of Lift Mailer
val emailConfig = EmailConfig(
smtpHost = APIUtil.getPropsValue("mail.smtp.host", "localhost"),
smtpPort = APIUtil.getPropsValue("mail.smtp.port", "1025").toInt,
username = APIUtil.getPropsValue("mail.smtp.user", ""),
password = APIUtil.getPropsValue("mail.smtp.password", ""),
useTLS = APIUtil.getPropsValue("mail.smtp.starttls.enable", "false").toBoolean,
debug = APIUtil.getPropsValue("mail.debug", "false").toBoolean
)
val emailContent = EmailContent(
from = from,
to = List(invitation.email),
subject = subject,
textContent = Some(customText),
htmlContent = Some(customHtmlText)
)
sendHtmlEmail(emailConfig, emailContent) match {
case Full(messageId) => logger.debug(s"Email sent successfully with Message-ID: $messageId")
case Empty => logger.error("Failed to send user invitation email")
}
logger.debug(s"After send user invitation by email.")
}
(JSONFactory400.createUserInvitationJson(invitation), HttpCode.`201`(callContext))