Skip to content

Commit

Permalink
Merge pull request #35 from lightningkite/email-bulk-sending
Browse files Browse the repository at this point in the history
Email bulk sending
  • Loading branch information
UnknownJoe796 committed Apr 18, 2024
2 parents 39ba602 + c206b91 commit b360f6d
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 11 deletions.
Expand Up @@ -46,9 +46,9 @@ suspend fun Email.toJavaX(session: Session = Session.getDefaultInstance(Properti
val email = this@toJavaX
subject = email.subject
email.fromEmail?.let { setFrom(InternetAddress(it, email.fromLabel)) }
email.to.forEach { setRecipient(Message.RecipientType.TO, InternetAddress(it.value, it.label)) }
email.cc.forEach { setRecipient(Message.RecipientType.CC, InternetAddress(it.value, it.label)) }
email.bcc.forEach { setRecipient(Message.RecipientType.BCC, InternetAddress(it.value, it.label)) }
email.to.map { InternetAddress(it.value, it.label) }.also { setRecipients(Message.RecipientType.TO, it.toTypedArray()) }
email.cc.map { InternetAddress(it.value, it.label) }.also { setRecipients(Message.RecipientType.CC, it.toTypedArray()) }
email.bcc.map { InternetAddress(it.value, it.label) }.also { setRecipients(Message.RecipientType.BCC, it.toTypedArray()) }
HttpContentAndHeaders(
headers = email.customHeaders,
content = HttpContent.Multipart(
Expand Down
Expand Up @@ -7,6 +7,7 @@ import jakarta.mail.Authenticator
import jakarta.mail.PasswordAuthentication
import jakarta.mail.Session
import jakarta.mail.Transport
import jakarta.mail.internet.InternetAddress

/**
* An email client that will send real emails through SMTP.
Expand All @@ -15,7 +16,7 @@ class SmtpEmailClient(val smtpConfig: SmtpConfig) : EmailClient {

val session = Session.getInstance(
Properties().apply {
smtpConfig.username?.let{ username ->
smtpConfig.username?.let { username ->
put("mail.smtp.user", username)
}
put("mail.smtp.host", smtpConfig.hostName)
Expand All @@ -37,11 +38,39 @@ class SmtpEmailClient(val smtpConfig: SmtpConfig) : EmailClient {
)

override suspend fun send(email: Email) {
if(email.to.isEmpty() && email.cc.isEmpty() && email.bcc.isEmpty()) return
Transport.send(
email.copy(
fromEmail = email.fromEmail ?: smtpConfig.fromEmail,
fromLabel = email.fromLabel ?: generalSettings().projectName
).toJavaX(session)
)
}
}

override suspend fun sendBulk(template: Email, personalizations: List<EmailPersonalization>) {
if (personalizations.isEmpty()) return
session.transport
.also { it.connect() }
.use { transport ->
personalizations
.asSequence()
.map {
it(template).copy(
fromEmail = template.fromEmail ?: smtpConfig.fromEmail,
fromLabel = template.fromLabel ?: generalSettings().projectName
)
}
.forEach { email ->
transport.sendMessage(
email.toJavaX(session).also { it.saveChanges() },
email.to
.plus(email.cc)
.plus(email.bcc)
.map { InternetAddress(it.value, it.label) }
.toTypedArray()
.also { if (it.isEmpty()) return@forEach }
)
}
}
}
}
Expand Up @@ -14,13 +14,80 @@ class SmtpTest {
println("No credentials to test with at ${credentials.absolutePath}")
return
}
val client = SmtpEmailClient(credentials.readText().let { Serialization.json.decodeFromString(credentials.readText()) })
val client =
SmtpEmailClient(credentials.readText().let { Serialization.json.decodeFromString(credentials.readText()) })
runBlocking {
client.send(Email(
subject = "Subject 2", fromLabel = "Joseph Ivie", fromEmail = "joseph@lightningkite.com",
to = listOf(EmailLabeledValue("joseph@lightningkite.com", "Joseph Ivie")),
html = "<p>Hello world!</p>",
))
client.send(
Email(
subject = "Subject 2", fromLabel = "Joseph Ivie", fromEmail = "joseph@lightningkite.com",
to = listOf(EmailLabeledValue("joseph@lightningkite.com", "Joseph Ivie")),
html = "<p>Hello world!</p>",
)
)
}
}

@Test
fun testSendBulk(): Unit = runBlocking {

val credentials = File("local/test-smtp.json")
if (!credentials.exists()) {
println("No credentials to test with at ${credentials.absolutePath}")
return@runBlocking
}

val client =
SmtpEmailClient(credentials.readText().let { Serialization.json.decodeFromString(credentials.readText()) })

val email1 = EmailLabeledValue(
"joseph@lightningkite.com",
"Joseph Ivie One"
)
val email2 = EmailLabeledValue(
"joseph+two@lightningkite.com",
"Joseph Ivie Two"
)
val email3 = EmailLabeledValue(
"joseph+three@lightningkite.com",
"Joseph Ivie Three"
)

client.sendBulk(
Email(
subject = "Bulk Email Test", fromLabel = "Joseph Ivie", fromEmail = "joseph@lightningkite.com",
to = emptyList(),
html = "<p>Hello {{UserName}}!</p>",
),
personalizations = listOf(
EmailPersonalization(
to = listOf(email1),
cc = listOf(email2),
bcc = listOf(email3),
substitutions = mapOf("{{UserName}}" to email1.label)
),
EmailPersonalization(
to = listOf(email2),
cc = listOf(email3),
bcc = listOf(email1),
substitutions = mapOf("{{UserName}}" to email2.label)
),
EmailPersonalization(
to = listOf(email3),
cc = listOf(email1),
bcc = listOf(email2),
substitutions = mapOf("{{UserName}}" to email3.label)
),
EmailPersonalization(
to = listOf(email1, email2, email3),
substitutions = mapOf(
"{{UserName}}" to listOf(
email1.label,
email2.label,
email3.label
).joinToString { it })
),
),
)

}
}

0 comments on commit b360f6d

Please sign in to comment.