In part 1 of this series, I outlined the start of an implementation of the “Birthday Greetings” kata.

The first part covered reading the data file, this part deals with sending emails.

Sending email

Email has been around since the start of the Internet, it was the first “internet” application and is still very widely used.

The original mail protocol was published in September 1980, and the basics of internet mail transfer haven’t changed much, and fortunately, we don’t really need to know too much about how it works, we just need to know who we want to send an email to, and the subject and body that we want to send.

This leads to a really simple interface…

interface EmailSender {
    fun send(from: String, to: String, subject: String, body: String)
}

Adding a test for a simple Smtp based implementation of this…

class SmtpEmailSenderTest {
    @Rule @JvmField
    public val greenMail = GreenMailRule(ServerSetupTest.SMTP)

    @Test
    fun `sends the correct fields as parts of the email`() {
        val sender = SmtpEmailSender("localhost", greenMail.smtp.port)

        sender.send("test@example.com", "to@example.com", "testing", "This is a test message")

        val email = greenMail.receivedMessages.first()
        assertEquals("testing", email.subject)
        assertEquals("test@example.com", email.getFrom().first().toString())
        assertEquals("to@example.com", email.allRecipients.first().toString())
        assertEquals("This is a test message", GreenMailUtil.getBody(email))
    }
}

This uses GreenMail to create a fake SMTP server to test the email being sent.

The resulting message comes back as a MimeMessage and the interface for getting values out can be tidied up with a bit of Kotlin sugar.

fun MimeMessage.to(): String {
    return allRecipients.first().toString()
}

fun MimeMessage.from(): String {
    return getFrom().first().toString()
}

fun MimeMessage.body(): String {
    return GreenMailUtil.getBody(this)
}

These are Kotlin extension functions see here for more information.

This tidies up the test a little bit.

    @Test
    fun `sends the correct fields as parts of the email`() {
        val sender = SmtpEmailSender("localhost", greenMail.smtp.port)

        sender.send("test@example.com", "to@example.com", "testing", "This is a test message")

        val email = greenMail.receivedMessages.first()
        assertEquals("testing", email.subject)
        assertEquals("test@example.com", email.from())
        assertEquals("to@example.com", email.to())
        assertEquals("This is a test message", email.body())
    }

There’s nothing specific about this implementation of the EmailSender interface to the birthday greetings code, it’s fairly standalone, it does one thing, it sends emails.