filter mails by property contact alias
This commit is contained in:
@@ -49,6 +49,8 @@ class EmailIngestionService(
|
||||
@Value("\${mail.imap.protocol:imaps}")
|
||||
private val protocol: String
|
||||
) {
|
||||
@Value("\${storage.emails.publicBaseUrl}")
|
||||
private val publicBaseUrl: String = ""
|
||||
private val running = AtomicBoolean(false)
|
||||
@Value("\${mail.imap.enabled:false}")
|
||||
private val enabled: Boolean = false
|
||||
@@ -86,9 +88,10 @@ class EmailIngestionService(
|
||||
|
||||
val subject = message.subject
|
||||
val from = message.from?.firstOrNull()?.toString()
|
||||
val recipients = extractRecipients(message)
|
||||
val receivedAt = message.receivedDate?.toInstant()?.atOffset(OffsetDateTime.now().offset)
|
||||
val body = extractText(message)
|
||||
val property = matchProperty(subject, body)
|
||||
val property = matchProperty(subject, body, recipients)
|
||||
|
||||
val inbound = InboundEmail(
|
||||
property = property,
|
||||
@@ -98,6 +101,10 @@ class EmailIngestionService(
|
||||
receivedAt = receivedAt
|
||||
)
|
||||
|
||||
val rawBytes = extractRawMessage(message)
|
||||
if (rawBytes != null) {
|
||||
inbound.rawEmlPath = emailStorage.storeEml(property?.id, messageId, rawBytes)
|
||||
}
|
||||
inbound.rawPdfPath = emailStorage.storePdf(property?.id, messageId, subject, body)
|
||||
inboundEmailRepo.save(inbound)
|
||||
|
||||
@@ -153,7 +160,8 @@ class EmailIngestionService(
|
||||
}
|
||||
|
||||
val guest = resolveGuest(property, extracted)
|
||||
val booking = createBooking(property, guest, extracted, sourceBookingId)
|
||||
val emailUrl = "${publicBaseUrl}/properties/${property.id}/inbound-emails/${inbound.id}/file"
|
||||
val booking = createBooking(property, guest, extracted, sourceBookingId, emailUrl)
|
||||
inbound.booking = booking
|
||||
inbound.status = InboundEmailStatus.CREATED
|
||||
inbound.processedAt = OffsetDateTime.now()
|
||||
@@ -214,7 +222,8 @@ class EmailIngestionService(
|
||||
property: Property,
|
||||
guest: Guest,
|
||||
extracted: Map<String, String>,
|
||||
sourceBookingId: String
|
||||
sourceBookingId: String,
|
||||
emailAuditPdfUrl: String?
|
||||
): Booking {
|
||||
val zone = ZoneId.of(property.timezone)
|
||||
val checkin = parsedDate(extracted["checkinDate"], zone)
|
||||
@@ -226,7 +235,8 @@ class EmailIngestionService(
|
||||
source = extracted["otaSource"]?.takeIf { !it.contains("NONE", true) } ?: "OTA",
|
||||
sourceBookingId = sourceBookingId,
|
||||
expectedCheckinAt = checkin,
|
||||
expectedCheckoutAt = checkout
|
||||
expectedCheckoutAt = checkout,
|
||||
emailAuditPdfUrl = emailAuditPdfUrl
|
||||
)
|
||||
return bookingRepo.save(booking)
|
||||
}
|
||||
@@ -253,10 +263,20 @@ class EmailIngestionService(
|
||||
}
|
||||
}
|
||||
|
||||
private fun matchProperty(subject: String?, body: String): Property? {
|
||||
private fun matchProperty(subject: String?, body: String, recipients: List<String>): Property? {
|
||||
val haystack = "${subject ?: ""}\n$body".lowercase()
|
||||
val properties = propertyRepo.findAll()
|
||||
val matches = properties.filter { property ->
|
||||
if (recipients.isNotEmpty()) {
|
||||
val propertyEmails = property.emailAddresses.map { it.lowercase() }.toSet()
|
||||
if (propertyEmails.isNotEmpty() && recipients.any { it.lowercase() in propertyEmails }) {
|
||||
return@filter true
|
||||
}
|
||||
val orgEmails = property.org.emailAliases.map { it.lowercase() }.toSet()
|
||||
if (orgEmails.isNotEmpty() && recipients.any { it.lowercase() in orgEmails }) {
|
||||
return@filter true
|
||||
}
|
||||
}
|
||||
val aliases = mutableSetOf<String>()
|
||||
aliases.add(property.name)
|
||||
aliases.add(property.code)
|
||||
@@ -267,6 +287,15 @@ class EmailIngestionService(
|
||||
return if (matches.size == 1) matches.first() else null
|
||||
}
|
||||
|
||||
private fun extractRecipients(message: Message): List<String> {
|
||||
val list = mutableListOf<String>()
|
||||
val to = message.getRecipients(Message.RecipientType.TO)
|
||||
val cc = message.getRecipients(Message.RecipientType.CC)
|
||||
(to ?: emptyArray()).forEach { list.add(it.toString()) }
|
||||
(cc ?: emptyArray()).forEach { list.add(it.toString()) }
|
||||
return list
|
||||
}
|
||||
|
||||
private fun extractText(message: Message): String {
|
||||
return try {
|
||||
val content = message.content
|
||||
@@ -280,6 +309,16 @@ class EmailIngestionService(
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractRawMessage(message: Message): ByteArray? {
|
||||
return try {
|
||||
val out = java.io.ByteArrayOutputStream()
|
||||
message.writeTo(out)
|
||||
out.toByteArray()
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractFromMultipart(multipart: Multipart): String {
|
||||
var text: String? = null
|
||||
var html: String? = null
|
||||
|
||||
Reference in New Issue
Block a user