ag.orbia.common.infrastructure.email.AmazonEmailSender.kt Maven / Gradle / Ivy
package ag.orbia.common.infrastructure.email
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService
import com.amazonaws.services.simpleemail.model.RawMessage
import com.amazonaws.services.simpleemail.model.SendRawEmailRequest
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
import java.util.*
import javax.activation.DataHandler
import javax.mail.Message
import javax.mail.Session
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMessage
import javax.mail.internet.MimeMultipart
import javax.mail.util.ByteArrayDataSource
@Service
class AmazonEmailSender @Autowired constructor(
private val sesClient: AmazonSimpleEmailService,
private val emailBodyResolver: EmailBodyResolver
) : EmailSender() {
@Value("\${aws.ses.configuration-set:#{null}}")
private var configurationSet: String? = null
override fun sendEmail(email: Email) {
try {
send(email)
} catch (exception: Exception) {
throw EmailNotSentException(exception)
}
}
private fun send(email: Email) {
if (email.configurationSetName == null) {
email.configurationSetName = configurationSet
}
val emailRequest = createEmailRequest(email)
send(emailRequest, email)
}
private fun createEmailRequest(email: Email): MimeMessage {
val replyToAddresses = email.replyTo.map { addr -> InternetAddress(addr) }.toTypedArray()
val message = MimeMessage(Session.getDefaultInstance(Properties()))
message.setSubject(email.subject, "UTF-8")
message.setFrom(InternetAddress(email.from))
message.replyTo = replyToAddresses
setRecipients(message, email)
setBody(message, email)
return message
}
private fun setRecipients(message: MimeMessage, email: Email) {
val toAddresses = getInternetAddresses(email.to)
val ccAddresses = getInternetAddresses(email.cc)
val bccAddresses = getInternetAddresses(email.bcc)
message.setRecipients(Message.RecipientType.TO, toAddresses)
message.setRecipients(Message.RecipientType.CC, ccAddresses)
message.setRecipients(Message.RecipientType.BCC, bccAddresses)
}
private fun getInternetAddresses(emailAddresses: Collection): Array {
return emailAddresses.map { addr -> InternetAddress(addr) }.toTypedArray()
}
private fun setBody(message: MimeMessage, email: Email) {
val textBodyContainer = setBodyText(email)
val emailContainer = setAttachments(textBodyContainer, email)
message.setContent(emailContainer)
}
private fun setBodyText(email: Email): MimeBodyPart {
val body = MimeMultipart("alternative")
val wrap = MimeBodyPart()
val bodyText = MimeBodyPart()
val bodyHtml = emailBodyResolver.resolve(email.body)
bodyText.setContent(bodyHtml, "text/html; charset=UTF-8")
body.addBodyPart(bodyText)
wrap.setContent(body)
return wrap
}
private fun setAttachments(emailTextBody: MimeBodyPart, email: Email): MimeMultipart {
val emailContainer = MimeMultipart("mixed")
emailContainer.addBodyPart(emailTextBody)
email.attachments.forEach { attachment -> addAttachmentToContainer(attachment, emailContainer) }
return emailContainer
}
private fun addAttachmentToContainer(emailAttachment: EmailAttachment, container: MimeMultipart) {
val attachment = MimeBodyPart()
val dataSource = ByteArrayDataSource(emailAttachment.fileContent, emailAttachment.mime)
attachment.dataHandler = DataHandler(dataSource)
attachment.fileName = emailAttachment.name
container.addBodyPart(attachment)
}
private fun send(message: MimeMessage, email: Email) {
val outputStream = ByteArrayOutputStream()
message.writeTo(outputStream)
val rawMessage = RawMessage(ByteBuffer.wrap(outputStream.toByteArray()))
val rawRequest = SendRawEmailRequest(rawMessage)
rawRequest.setDestinations(email.to)
rawRequest.configurationSetName = email.configurationSetName
sesClient.sendRawEmail(rawRequest)
}
}