11package code .api .util
22
33import code .util .Helper .MdcLoggable
4+ import jakarta .activation .{DataHandler , FileDataSource , URLDataSource }
5+ import jakarta .mail ._
6+ import jakarta .mail .internet ._
47import net .liftweb .common .{Box , Empty , Full }
5- import org .apache .commons .mail ._
68
9+ import java .io .File
710import java .net .URL
11+ import java .util .Properties
812
913/**
10- * Apache Commons Email Wrapper for OBP-API
11- * This wrapper provides a simple interface to send emails using Apache Commons Email
12- * instead of Lift Web's Mailer
14+ * Jakarta Mail Wrapper for OBP-API
15+ * This wrapper provides a simple interface to send emails using Jakarta Mail
1316 */
1417object CommonsEmailWrapper extends MdcLoggable {
1518
16- /**
17- * Email configuration case class
18- */
1919 case class EmailConfig (
2020 smtpHost : String ,
2121 smtpPort : Int ,
@@ -24,12 +24,9 @@ object CommonsEmailWrapper extends MdcLoggable {
2424 useTLS : Boolean = true ,
2525 useSSL : Boolean = false ,
2626 debug : Boolean = false ,
27- tlsProtocols : String = " TLSv1.2" // TLS protocols to use
27+ tlsProtocols : String = " TLSv1.2"
2828 )
2929
30- /**
31- * Email content case class
32- */
3330 case class EmailContent (
3431 from : String ,
3532 to : List [String ],
@@ -41,9 +38,12 @@ object CommonsEmailWrapper extends MdcLoggable {
4138 attachments : List [EmailAttachment ] = List .empty
4239 )
4340
44- /**
45- * Get default email configuration from OBP-API properties
46- */
41+ case class EmailAttachment (
42+ filePath : Option [String ] = None ,
43+ url : Option [String ] = None ,
44+ name : Option [String ] = None
45+ )
46+
4747 def getDefaultEmailConfig (): EmailConfig = {
4848 EmailConfig (
4949 smtpHost = APIUtil .getPropsValue(" mail.smtp.host" , " localhost" ),
@@ -57,156 +57,137 @@ object CommonsEmailWrapper extends MdcLoggable {
5757 )
5858 }
5959
60- /**
61- * Send simple text email with default configuration
62- */
6360 def sendTextEmail (content : EmailContent ): Box [String ] = {
6461 sendTextEmail(getDefaultEmailConfig(), content)
6562 }
6663
67- /**
68- * Send HTML email with default configuration
69- */
7064 def sendHtmlEmail (content : EmailContent ): Box [String ] = {
7165 sendHtmlEmail(getDefaultEmailConfig(), content)
7266 }
7367
74- /**
75- * Send email with attachments using default configuration
76- */
7768 def sendEmailWithAttachments (content : EmailContent ): Box [String ] = {
7869 sendEmailWithAttachments(getDefaultEmailConfig(), content)
7970 }
8071
81- /**
82- * Send simple text email
83- */
8472 def sendTextEmail (config : EmailConfig , content : EmailContent ): Box [String ] = {
8573 try {
86- logger.info(s " Sending text email from ${content.from} to ${content.to.mkString(" , " )}" )
87-
88- val email = new SimpleEmail ()
89- configureEmail(email, config, content)
90-
91- // Set text content
92- content.textContent match {
93- case Some (text) => email.setMsg(text)
94- case None => email.setMsg(" " )
95- }
96-
97- val messageId = email.send()
98- logger.info(s " Email sent successfully with Message-ID: $messageId" )
99- Full (messageId)
74+ logger.debug(s " Sending text email from ${content.from} to ${content.to.mkString(" , " )}" )
75+ val session = createSession(config)
76+ val message = new MimeMessage (session)
77+ setCommonHeaders(message, content)
78+ message.setText(content.textContent.getOrElse(" " ), " UTF-8" )
79+ Transport .send(message)
80+ Full (message.getMessageID)
10081 } catch {
10182 case e : Exception =>
10283 logger.error(s " Failed to send text email: ${e.getMessage}" , e)
10384 Empty
10485 }
10586 }
10687
107- /**
108- * Send HTML email
109- */
11088 def sendHtmlEmail (config : EmailConfig , content : EmailContent ): Box [String ] = {
11189 try {
112- logger.info(s " Sending HTML email from ${content.from} to ${content.to.mkString(" , " )}" )
113-
114- val email = new HtmlEmail ()
115- configureEmail(email, config, content)
116-
117- // Set HTML content
118- content.htmlContent match {
119- case Some (html) => email.setHtmlMsg(html)
120- case None => email.setHtmlMsg(" <html><body>No content</body></html>" )
90+ logger.debug(s " Sending HTML email from ${content.from} to ${content.to.mkString(" , " )}" )
91+ val session = createSession(config)
92+ val message = new MimeMessage (session)
93+ setCommonHeaders(message, content)
94+ val multipart = {
95+ new MimeMultipart (" alternative" )
96+ }
97+ content.textContent.foreach { text =>
98+ val textPart = new MimeBodyPart ()
99+ textPart.setText(text, " UTF-8" )
100+ multipart.addBodyPart(textPart)
101+ }
102+ content.htmlContent.foreach { html =>
103+ val htmlPart = new MimeBodyPart ()
104+ htmlPart.setContent(html, " text/html; charset=UTF-8" )
105+ multipart.addBodyPart(htmlPart)
121106 }
122-
123- // Set text content as fallback
124- content.textContent.foreach(email.setTextMsg)
125-
126- val messageId = email.send()
127- logger.info(s " HTML email sent successfully with Message-ID: $messageId" )
128- Full (messageId)
107+ message.setContent(multipart)
108+ Transport .send(message)
109+ Full (message.getMessageID)
129110 } catch {
130111 case e : Exception =>
131112 logger.error(s " Failed to send HTML email: ${e.getMessage}" , e)
132113 Empty
133114 }
134115 }
135116
136- /**
137- * Send email with attachments
138- */
139117 def sendEmailWithAttachments (config : EmailConfig , content : EmailContent ): Box [String ] = {
140118 try {
141- logger.info(s " Sending email with attachments from ${content.from} to ${content.to.mkString(" , " )}" )
142-
143- val email = new MultiPartEmail ()
144- configureEmail(email, config, content)
145-
146- // Set text content
147- content.textContent.foreach(email.setMsg)
148-
119+ logger.debug(s " Sending email with attachments from ${content.from} to ${content.to.mkString(" , " )}" )
120+ val session = createSession(config)
121+ val message = new MimeMessage (session)
122+ setCommonHeaders(message, content)
123+ val multipart = new MimeMultipart ()
124+ // Add text or HTML part
125+ (content.htmlContent, content.textContent) match {
126+ case (Some (html), _) =>
127+ val htmlPart = new MimeBodyPart ()
128+ htmlPart.setContent(html, " text/html; charset=UTF-8" )
129+ multipart.addBodyPart(htmlPart)
130+ case (None , Some (text)) =>
131+ val textPart = new MimeBodyPart ()
132+ textPart.setText(text, " UTF-8" )
133+ multipart.addBodyPart(textPart)
134+ case _ =>
135+ val textPart = new MimeBodyPart ()
136+ textPart.setText(" " , " UTF-8" )
137+ multipart.addBodyPart(textPart)
138+ }
149139 // Add attachments
150- content.attachments.foreach(email.attach)
151-
152- val messageId = email.send()
153- logger.info(s " Email with attachments sent successfully with Message-ID: $messageId" )
154- Full (messageId)
140+ content.attachments.foreach { att =>
141+ val attachPart = new MimeBodyPart ()
142+ if (att.filePath.isDefined) {
143+ val fds = new FileDataSource (new File (att.filePath.get))
144+ attachPart.setDataHandler(new DataHandler (fds))
145+ attachPart.setFileName(att.name.getOrElse(new File (att.filePath.get).getName))
146+ } else if (att.url.isDefined) {
147+ val uds = new URLDataSource (new URL (att.url.get))
148+ attachPart.setDataHandler(new DataHandler (uds))
149+ attachPart.setFileName(att.name.getOrElse(att.url.get.split('/' ).last))
150+ }
151+ multipart.addBodyPart(attachPart)
152+ }
153+ message.setContent(multipart)
154+ Transport .send(message)
155+ Full (message.getMessageID)
155156 } catch {
156157 case e : Exception =>
157158 logger.error(s " Failed to send email with attachments: ${e.getMessage}" , e)
158159 Empty
159160 }
160161 }
161162
162- /**
163- * Configure email with common settings
164- */
165- private def configureEmail (email : Email , config : EmailConfig , content : EmailContent ): Unit = {
166- // SMTP Configuration
167- email.setHostName(config.smtpHost)
168- email.setSmtpPort(config.smtpPort)
169- email.setAuthenticator(new DefaultAuthenticator (config.username, config.password))
170- email.setSSLOnConnect(config.useSSL)
171- email.setStartTLSEnabled(config.useTLS)
172- email.setDebug(config.debug)
173- email.getMailSession.getProperties.setProperty(" mail.smtp.ssl.protocols" , config.tlsProtocols)
174-
175- // Set charset
176- email.setCharset(" UTF-8" )
177-
178- // Set sender
179- email.setFrom(content.from)
180-
181- // Set recipients
182- content.to.foreach(email.addTo)
183- content.cc.foreach(email.addCc)
184- content.bcc.foreach(email.addBcc)
185-
186- // Set subject
187- email.setSubject(content.subject)
163+ private def createSession (config : EmailConfig ): Session = {
164+ val props = new Properties ()
165+ props.put(" mail.smtp.host" , config.smtpHost)
166+ props.put(" mail.smtp.port" , config.smtpPort.toString)
167+ props.put(" mail.smtp.auth" , " true" )
168+ props.put(" mail.smtp.starttls.enable" , config.useTLS.toString)
169+ props.put(" mail.smtp.ssl.enable" , config.useSSL.toString)
170+ props.put(" mail.debug" , config.debug.toString)
171+ props.put(" mail.smtp.ssl.protocols" , config.tlsProtocols)
172+ val authenticator = new Authenticator () {
173+ override def getPasswordAuthentication : PasswordAuthentication =
174+ new PasswordAuthentication (config.username, config.password)
175+ }
176+ Session .getInstance(props, authenticator)
188177 }
189178
190- /**
191- * Create email attachment from file
192- */
193- def createFileAttachment (filePath : String , name : Option [String ] = None ): EmailAttachment = {
194- val attachment = new EmailAttachment ()
195- attachment.setPath(filePath)
196- attachment.setDisposition(EmailAttachment .ATTACHMENT )
197- name.foreach(attachment.setName)
198- attachment
179+ private def setCommonHeaders (message : MimeMessage , content : EmailContent ): Unit = {
180+ message.setFrom(new InternetAddress (content.from))
181+ content.to.foreach(addr => message.addRecipient(Message .RecipientType .TO , new InternetAddress (addr)))
182+ content.cc.foreach(addr => message.addRecipient(Message .RecipientType .CC , new InternetAddress (addr)))
183+ content.bcc.foreach(addr => message.addRecipient(Message .RecipientType .BCC , new InternetAddress (addr)))
184+ message.setSubject(content.subject, " UTF-8" )
199185 }
200186
201- /**
202- * Create email attachment from URL
203- */
204- def createUrlAttachment (url : String , name : String ): EmailAttachment = {
205- val attachment = new EmailAttachment ()
206- attachment.setURL(new URL (url))
207- attachment.setDisposition(EmailAttachment .ATTACHMENT )
208- attachment.setName(name)
209- attachment
210- }
187+ def createFileAttachment (filePath : String , name : Option [String ] = None ): EmailAttachment =
188+ EmailAttachment (filePath = Some (filePath), url = None , name = name)
189+
190+ def createUrlAttachment (url : String , name : String ): EmailAttachment =
191+ EmailAttachment (filePath = None , url = Some (url), name = Some (name))
211192
212193}
0 commit comments