Files
TrisolarisServer/src/main/kotlin/com/android/trisolarisserver/component/EmailStorage.kt
androidlover5842 9b64b34ab9
All checks were successful
build-and-deploy / build-deploy (push) Successful in 33s
Deduplicate logic across controllers, auth, and schema fixes
2026-01-28 23:03:48 +05:30

115 lines
4.2 KiB
Kotlin

package com.android.trisolarisserver.component
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.pdmodel.PDPage
import org.apache.pdfbox.pdmodel.PDPageContentStream
import org.apache.pdfbox.pdmodel.common.PDRectangle
import org.apache.pdfbox.pdmodel.font.PDType1Font
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import java.nio.file.Files
import java.nio.file.Paths
import java.time.OffsetDateTime
import java.util.UUID
@Component
class EmailStorage(
@Value("\${storage.emails.root:/home/androidlover5842/docs/emails}")
private val rootPath: String
) {
fun storePdf(propertyId: UUID?, messageId: String?, subject: String?, body: String): String {
val dir = if (propertyId != null) {
Paths.get(rootPath, propertyId.toString())
} else {
Paths.get(rootPath, "unassigned")
}
Files.createDirectories(dir)
val safeName = (messageId ?: UUID.randomUUID().toString()).replace(Regex("[^A-Za-z0-9._-]"), "_")
val fileName = "${safeName}_${OffsetDateTime.now().toEpochSecond()}.pdf"
val path = dir.resolve(fileName).normalize()
val tmp = dir.resolve("${fileName}.tmp").normalize()
val document = PDDocument()
val page = PDPage(PDRectangle.LETTER)
document.addPage(page)
val header = "Subject: ${subject ?: ""}\n\n"
writeText(document, page, header + body)
document.save(tmp.toFile())
document.close()
atomicMove(tmp, path)
return path.toString()
}
private fun writeText(document: PDDocument, firstPage: PDPage, text: String) {
var page = firstPage
var y = 730f
val marginX = 50f
val lineHeight = 14f
val maxLines = 48
var linesOnPage = 0
var content = PDPageContentStream(document, page)
content.beginText()
content.setFont(PDType1Font.HELVETICA, 11f)
content.newLineAtOffset(marginX, y)
fun newLine() {
content.newLineAtOffset(0f, -lineHeight)
y -= lineHeight
linesOnPage++
if (linesOnPage >= maxLines) {
content.endText()
content.close()
page = PDPage(PDRectangle.LETTER)
document.addPage(page)
content = PDPageContentStream(document, page)
content.beginText()
content.setFont(PDType1Font.HELVETICA, 11f)
y = 730f
linesOnPage = 0
content.newLineAtOffset(marginX, y)
}
}
val lines = text.split("\n")
for (line in lines) {
val chunks = line.chunked(90)
for (chunk in chunks) {
content.showText(chunk)
newLine()
}
}
content.endText()
content.close()
}
fun storeEml(propertyId: UUID?, messageId: String?, rawBytes: ByteArray): String {
val dir = if (propertyId != null) {
Paths.get(rootPath, propertyId.toString(), "raw")
} else {
Paths.get(rootPath, "unassigned", "raw")
}
Files.createDirectories(dir)
val safeName = (messageId ?: UUID.randomUUID().toString()).replace(Regex("[^A-Za-z0-9._-]"), "_")
val fileName = "${safeName}_${OffsetDateTime.now().toEpochSecond()}.eml"
val path = dir.resolve(fileName).normalize()
val tmp = dir.resolve("${fileName}.tmp").normalize()
Files.write(tmp, rawBytes)
atomicMove(tmp, path)
return path.toString()
}
fun storeUploadedPdf(propertyId: UUID, originalName: String?, bytes: ByteArray): String {
val dir = Paths.get(rootPath, propertyId.toString(), "manual")
Files.createDirectories(dir)
val safeName = (originalName ?: UUID.randomUUID().toString()).replace(Regex("[^A-Za-z0-9._-]"), "_")
val fileName = "${safeName}_${OffsetDateTime.now().toEpochSecond()}.pdf"
val path = dir.resolve(fileName).normalize()
val tmp = dir.resolve("${fileName}.tmp").normalize()
Files.write(tmp, bytes)
atomicMove(tmp, path)
return path.toString()
}
}