mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-05 22:55:58 +00:00
Store message-id of eml files
This commit is contained in:
parent
6b13993257
commit
09ea724c13
@ -20,12 +20,12 @@ object ReadMail {
|
|||||||
def readBytesP[F[_]: ConcurrentEffect: ContextShift](
|
def readBytesP[F[_]: ConcurrentEffect: ContextShift](
|
||||||
logger: Logger[F]
|
logger: Logger[F]
|
||||||
): Pipe[F, Byte, Binary[F]] =
|
): Pipe[F, Byte, Binary[F]] =
|
||||||
s =>
|
_.through(bytesToMail(logger)).flatMap(mailToEntries[F](logger))
|
||||||
Stream.eval(logger.debug(s"Converting e-mail into its parts")) >>
|
|
||||||
bytesToMail(s).flatMap(mailToEntries[F](logger))
|
|
||||||
|
|
||||||
def bytesToMail[F[_]: Sync](data: Stream[F, Byte]): Stream[F, Mail[F]] =
|
def bytesToMail[F[_]: Sync](logger: Logger[F]): Pipe[F, Byte, Mail[F]] =
|
||||||
data.through(Binary.decode(StandardCharsets.US_ASCII)).foldMonoid.evalMap(read[F])
|
s =>
|
||||||
|
Stream.eval(logger.debug(s"Converting e-mail file...")) >>
|
||||||
|
s.through(Binary.decode(StandardCharsets.US_ASCII)).foldMonoid.evalMap(read[F])
|
||||||
|
|
||||||
def mailToEntries[F[_]: ConcurrentEffect: ContextShift](
|
def mailToEntries[F[_]: ConcurrentEffect: ContextShift](
|
||||||
logger: Logger[F]
|
logger: Logger[F]
|
||||||
@ -62,7 +62,8 @@ object ReadMail {
|
|||||||
val str = cnt.asString.trim.toLowerCase
|
val str = cnt.asString.trim.toLowerCase
|
||||||
val head = htmlHeader(cnt.charsetOrUtf8)
|
val head = htmlHeader(cnt.charsetOrUtf8)
|
||||||
if (str.startsWith("<html")) cnt
|
if (str.startsWith("<html")) cnt
|
||||||
else cnt match {
|
else
|
||||||
|
cnt match {
|
||||||
case BodyContent.StringContent(s) =>
|
case BodyContent.StringContent(s) =>
|
||||||
BodyContent(head + s + htmlHeaderEnd)
|
BodyContent(head + s + htmlHeaderEnd)
|
||||||
case BodyContent.ByteContent(bv, cs) =>
|
case BodyContent.ByteContent(bv, cs) =>
|
||||||
@ -72,7 +73,6 @@ object ReadMail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
implicit class MimeTypeConv(m: emil.MimeType) {
|
implicit class MimeTypeConv(m: emil.MimeType) {
|
||||||
def toDocspell: MimeType =
|
def toDocspell: MimeType =
|
||||||
MimeType(m.primary, m.sub, m.params)
|
MimeType(m.primary, m.sub, m.params)
|
||||||
|
@ -120,7 +120,7 @@ object ExtractArchive {
|
|||||||
|
|
||||||
zipData
|
zipData
|
||||||
.through(Zip.unzipP[F](8192, ctx.blocker))
|
.through(Zip.unzipP[F](8192, ctx.blocker))
|
||||||
.flatMap(handleEntry(ctx, ra, archive))
|
.flatMap(handleEntry(ctx, ra, archive, None))
|
||||||
.foldMonoid
|
.foldMonoid
|
||||||
.compile
|
.compile
|
||||||
.lastOrError
|
.lastOrError
|
||||||
@ -130,14 +130,19 @@ object ExtractArchive {
|
|||||||
ctx: Context[F, _],
|
ctx: Context[F, _],
|
||||||
archive: Option[RAttachmentArchive]
|
archive: Option[RAttachmentArchive]
|
||||||
)(ra: RAttachment): F[Extracted] = {
|
)(ra: RAttachment): F[Extracted] = {
|
||||||
val email = ctx.store.bitpeace
|
val email: Stream[F, Byte] = ctx.store.bitpeace
|
||||||
.get(ra.fileId.id)
|
.get(ra.fileId.id)
|
||||||
.unNoneTerminate
|
.unNoneTerminate
|
||||||
.through(ctx.store.bitpeace.fetchData2(RangeDef.all))
|
.through(ctx.store.bitpeace.fetchData2(RangeDef.all))
|
||||||
|
|
||||||
email
|
email
|
||||||
.through(ReadMail.readBytesP[F](ctx.logger))
|
.through(ReadMail.bytesToMail[F](ctx.logger))
|
||||||
.flatMap(handleEntry(ctx, ra, archive))
|
.flatMap { mail =>
|
||||||
|
val mId = mail.header.messageId
|
||||||
|
ReadMail
|
||||||
|
.mailToEntries(ctx.logger)(mail)
|
||||||
|
.flatMap(handleEntry(ctx, ra, archive, mId))
|
||||||
|
}
|
||||||
.foldMonoid
|
.foldMonoid
|
||||||
.compile
|
.compile
|
||||||
.lastOrError
|
.lastOrError
|
||||||
@ -146,7 +151,8 @@ object ExtractArchive {
|
|||||||
def handleEntry[F[_]: Sync](
|
def handleEntry[F[_]: Sync](
|
||||||
ctx: Context[F, _],
|
ctx: Context[F, _],
|
||||||
ra: RAttachment,
|
ra: RAttachment,
|
||||||
archive: Option[RAttachmentArchive]
|
archive: Option[RAttachmentArchive],
|
||||||
|
messageId: Option[String]
|
||||||
)(
|
)(
|
||||||
entry: Binary[F]
|
entry: Binary[F]
|
||||||
): Stream[F, Extracted] = {
|
): Stream[F, Extracted] = {
|
||||||
@ -163,7 +169,7 @@ object ExtractArchive {
|
|||||||
ra.created,
|
ra.created,
|
||||||
Option(entry.name).map(_.trim).filter(_.nonEmpty)
|
Option(entry.name).map(_.trim).filter(_.nonEmpty)
|
||||||
)
|
)
|
||||||
val aa = archive.getOrElse(RAttachmentArchive.of(ra)).copy(id = id)
|
val aa = archive.getOrElse(RAttachmentArchive.of(ra, messageId)).copy(id = id)
|
||||||
Extracted.of(nra, aa)
|
Extracted.of(nra, aa)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@ CREATE TABLE `attachment_archive` (
|
|||||||
`id` varchar(254) not null primary key,
|
`id` varchar(254) not null primary key,
|
||||||
`file_id` varchar(254) not null,
|
`file_id` varchar(254) not null,
|
||||||
`filename` varchar(254),
|
`filename` varchar(254),
|
||||||
|
`message_id` varchar(254),
|
||||||
`created` timestamp not null,
|
`created` timestamp not null,
|
||||||
foreign key (`file_id`) references `filemeta`(`id`),
|
foreign key (`file_id`) references `filemeta`(`id`),
|
||||||
foreign key (`id`) references `attachment`(`attachid`)
|
foreign key (`id`) references `attachment`(`attachid`)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE INDEX `attachment_archive_message_id_idx`
|
||||||
|
ON `attachment_archive`(`message_id`);
|
||||||
|
@ -2,7 +2,11 @@ CREATE TABLE "attachment_archive" (
|
|||||||
"id" varchar(254) not null primary key,
|
"id" varchar(254) not null primary key,
|
||||||
"file_id" varchar(254) not null,
|
"file_id" varchar(254) not null,
|
||||||
"filename" varchar(254),
|
"filename" varchar(254),
|
||||||
|
"message_id" varchar(254),
|
||||||
"created" timestamp not null,
|
"created" timestamp not null,
|
||||||
foreign key ("file_id") references "filemeta"("id"),
|
foreign key ("file_id") references "filemeta"("id"),
|
||||||
foreign key ("id") references "attachment"("attachid")
|
foreign key ("id") references "attachment"("attachid")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE INDEX "attachment_archive_message_id_idx"
|
||||||
|
ON "attachment_archive"("message_id");
|
||||||
|
@ -14,6 +14,7 @@ case class RAttachmentArchive(
|
|||||||
id: Ident, //same as RAttachment.id
|
id: Ident, //same as RAttachment.id
|
||||||
fileId: Ident,
|
fileId: Ident,
|
||||||
name: Option[String],
|
name: Option[String],
|
||||||
|
messageId: Option[String],
|
||||||
created: Timestamp
|
created: Timestamp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,18 +26,19 @@ object RAttachmentArchive {
|
|||||||
val id = Column("id")
|
val id = Column("id")
|
||||||
val fileId = Column("file_id")
|
val fileId = Column("file_id")
|
||||||
val name = Column("filename")
|
val name = Column("filename")
|
||||||
|
val messageId = Column("message_id")
|
||||||
val created = Column("created")
|
val created = Column("created")
|
||||||
|
|
||||||
val all = List(id, fileId, name, created)
|
val all = List(id, fileId, name, messageId, created)
|
||||||
}
|
}
|
||||||
|
|
||||||
import Columns._
|
import Columns._
|
||||||
|
|
||||||
def of(ra: RAttachment): RAttachmentArchive =
|
def of(ra: RAttachment, mId: Option[String]): RAttachmentArchive =
|
||||||
RAttachmentArchive(ra.id, ra.fileId, ra.name, ra.created)
|
RAttachmentArchive(ra.id, ra.fileId, ra.name, mId, ra.created)
|
||||||
|
|
||||||
def insert(v: RAttachmentArchive): ConnectionIO[Int] =
|
def insert(v: RAttachmentArchive): ConnectionIO[Int] =
|
||||||
insertRow(table, all, fr"${v.id},${v.fileId},${v.name},${v.created}").update.run
|
insertRow(table, all, fr"${v.id},${v.fileId},${v.name},${v.messageId},${v.created}").update.run
|
||||||
|
|
||||||
def findById(attachId: Ident): ConnectionIO[Option[RAttachmentArchive]] =
|
def findById(attachId: Ident): ConnectionIO[Option[RAttachmentArchive]] =
|
||||||
selectSimple(all, table, id.is(attachId)).query[RAttachmentArchive].option
|
selectSimple(all, table, id.is(attachId)).query[RAttachmentArchive].option
|
||||||
@ -66,7 +68,9 @@ object RAttachmentArchive {
|
|||||||
selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentArchive].option
|
selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentArchive].option
|
||||||
}
|
}
|
||||||
|
|
||||||
def findByItemWithMeta(id: Ident): ConnectionIO[Vector[(RAttachmentArchive, FileMeta)]] = {
|
def findByItemWithMeta(
|
||||||
|
id: Ident
|
||||||
|
): ConnectionIO[Vector[(RAttachmentArchive, FileMeta)]] = {
|
||||||
import bitpeace.sql._
|
import bitpeace.sql._
|
||||||
|
|
||||||
val aId = Columns.id.prefix("a")
|
val aId = Columns.id.prefix("a")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user