Skip to content

Instantly share code, notes, and snippets.

@spoptchev
Last active December 6, 2022 19:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spoptchev/e0821c4bf39032eb1f5f208f2f8fd8d8 to your computer and use it in GitHub Desktop.
Save spoptchev/e0821c4bf39032eb1f5f208f2f8fd8d8 to your computer and use it in GitHub Desktop.
How to improve third-party libraries with Kotlin extensions
package tech.zone2.mime
import org.apache.james.mime4j.dom.Message
import org.apache.james.mime4j.dom.Multipart
import org.apache.james.mime4j.message.BodyPartBuilder
import org.apache.james.mime4j.message.MultipartBuilder
import tech.zone2.mime.html
import tech.zone2.mime.text
fun main() {
val textPart = BodyPartBuilder.create()
.setBody("plain text content", "plain", Charsets.UTF_8)
val htmlPart = BodyPartBuilder.create()
.setBody("<html><body>content</body></html>", "html", Charsets.UTF_8)
val multipart: Multipart = MultipartBuilder.create("alternative")
.addBodyPart(textPart)
.addBodyPart(htmlPart)
.build()
val message = Message.Builder.of()
.setBody(multipart)
.build()
println(message.text) // -> plain text content
println(message.html) // -> <html><body>content</body></html>
}
package tech.zone2.mime
import org.apache.james.mime4j.Charsets
import org.apache.james.mime4j.dom.Entity
import org.apache.james.mime4j.dom.Message
import org.apache.james.mime4j.dom.Multipart
import org.apache.james.mime4j.dom.TextBody
import org.apache.james.mime4j.dom.field.FieldName
import java.io.ByteArrayOutputStream
import java.nio.charset.Charset
import java.nio.charset.IllegalCharsetNameException
import java.nio.charset.UnsupportedCharsetException
private const val textHtml = "text/html"
private const val textPlain = "text/plain"
val Message.html: String?
get() {
val textBody = findTextBody(setOf(textHtml)) ?: return null
return textBody.content
}
val Message.text: String?
get() {
val textBody = findTextBody(setOf(textPlain, null)) ?: return null
return textBody.content
}
private val Entity.isNotAttachment
get() = dispositionType == null
private val Entity.isInlinedWithoutCid
get() = dispositionType == "inline" && header.getField(FieldName.CONTENT_ID) == null
private fun Entity.findTextBody(validMimeTypes: Set<String?>): TextBody? {
if (body is TextBody && mimeType in validMimeTypes && (isNotAttachment || isInlinedWithoutCid)) {
return body as TextBody
}
if (!isMultipart) {
return null
}
return (body as Multipart).bodyParts
.firstNotNullOfOrNull { it.findTextBody(validMimeTypes) }
}
private val TextBody.contentCharset
get() = try {
Charset.forName(mimeCharset)
} catch (e: IllegalCharsetNameException) {
Charsets.DEFAULT_CHARSET
} catch (e: IllegalArgumentException) {
Charsets.DEFAULT_CHARSET
} catch (e: UnsupportedCharsetException) {
Charsets.DEFAULT_CHARSET
}
private val TextBody.content: String
get() {
val byteArrayOutputStream = ByteArrayOutputStream()
writeTo(byteArrayOutputStream)
return String(byteArrayOutputStream.toByteArray(), contentCharset)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment