From 0a1b3fcf957324737a5f1bb87b523c445f0e6d6c Mon Sep 17 00:00:00 2001 From: Eike Kettner Date: Wed, 29 Apr 2020 22:44:05 +0200 Subject: [PATCH] Set list-id header for notification mails --- Changelog.md | 11 ++++++++++- build.sbt | 3 +++ .../main/scala/docspell/backend/ops/OMail.scala | 1 + .../scala/docspell/common/MailSendConfig.scala | 3 +++ modules/joex/src/main/resources/reference.conf | 13 +++++++++++++ .../joex/src/main/scala/docspell/joex/Config.scala | 5 +++-- .../src/main/scala/docspell/joex/JoexAppImpl.scala | 2 +- .../main/scala/docspell/joex/mail/EmilHeader.scala | 14 ++++++++++++++ .../docspell/joex/notify/NotifyDueItemsTask.scala | 13 +++++++++---- 9 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 modules/common/src/main/scala/docspell/common/MailSendConfig.scala create mode 100644 modules/joex/src/main/scala/docspell/joex/mail/EmilHeader.scala diff --git a/Changelog.md b/Changelog.md index 7f6376d5..1ff637e5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,12 +9,21 @@ the periodic-task framework introduced in the last release. - Fix issues when converting HTML with unkown links. This especially happens with e-mails that contain images to attachments. -- Fix issues when importing e-mail files: +- Fix various issues when importing e-mail files, for example: - fixes encoding problems for mails without explicit transfer encoding - add meta info (from, to, subject) to the converted pdf document - clean html mails to remove unwanted content (like javascript) - Fix classpath issue with javax.mail vs jakarta.mail +### Configuration Changes + +The Joex component has config changes: + +- A new section `send-mail` containing a `List-Id` e-mail header to + use. Use an empty string (the default) to avoid setting such header. + This header is only applied for notification mails. + + ## v0.4.0 *Mar. 29, 2020* diff --git a/build.sbt b/build.sbt index e1c14aa2..04a89ead 100644 --- a/build.sbt +++ b/build.sbt @@ -141,6 +141,9 @@ val openapiScalaSettings = Seq( // --- Modules +// Base module, everything depends on this – including restapi and +// joexapi modules. This should aim to have least possible +// dependencies val common = project.in(file("modules/common")). disablePlugins(RevolverPlugin). settings(sharedSettings). diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OMail.scala b/modules/backend/src/main/scala/docspell/backend/ops/OMail.scala index a51045da..c334964e 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OMail.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OMail.scala @@ -158,6 +158,7 @@ object OMail { val fields: Seq[Trans[F]] = Seq( From(sett.mailFrom), Tos(m.recipients), + XMailer.emil, Subject(m.subject), TextBody[F](m.body) ) diff --git a/modules/common/src/main/scala/docspell/common/MailSendConfig.scala b/modules/common/src/main/scala/docspell/common/MailSendConfig.scala new file mode 100644 index 00000000..ae05b496 --- /dev/null +++ b/modules/common/src/main/scala/docspell/common/MailSendConfig.scala @@ -0,0 +1,3 @@ +package docspell.common + +case class MailSendConfig(listId: String) diff --git a/modules/joex/src/main/resources/reference.conf b/modules/joex/src/main/resources/reference.conf index b05685a2..ff90f24f 100644 --- a/modules/joex/src/main/resources/reference.conf +++ b/modules/joex/src/main/resources/reference.conf @@ -31,6 +31,19 @@ docspell.joex { password = "" } + send-mail { + # This is used as the List-Id e-mail header when mails are sent + # from docspell to its users (example: for notification mails). It + # is not used when sending to external recipients. If it is empty, + # no such header is added. Using this header is often useful when + # filtering mails. + # + # It should be a string in angle brackets. See + # https://tools.ietf.org/html/rfc2919 for a formal specification + # of this header. + list-id = "" + } + # Configuration for the job scheduler. scheduler { diff --git a/modules/joex/src/main/scala/docspell/joex/Config.scala b/modules/joex/src/main/scala/docspell/joex/Config.scala index d72abcee..98280392 100644 --- a/modules/joex/src/main/scala/docspell/joex/Config.scala +++ b/modules/joex/src/main/scala/docspell/joex/Config.scala @@ -1,7 +1,7 @@ package docspell.joex import docspell.analysis.TextAnalysisConfig -import docspell.common.{Ident, LenientUri} +import docspell.common._ import docspell.joex.scheduler.{PeriodicSchedulerConfig, SchedulerConfig} import docspell.store.JdbcConfig import docspell.convert.ConvertConfig @@ -18,7 +18,8 @@ case class Config( houseKeeping: HouseKeepingConfig, extraction: ExtractConfig, textAnalysis: TextAnalysisConfig, - convert: ConvertConfig + convert: ConvertConfig, + sendMail: MailSendConfig ) object Config { diff --git a/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala b/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala index 9ab7e46e..e17c4b98 100644 --- a/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala +++ b/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala @@ -78,7 +78,7 @@ object JoexAppImpl { .withTask( JobTask.json( NotifyDueItemsArgs.taskName, - NotifyDueItemsTask[F](JavaMailEmil(blocker)), + NotifyDueItemsTask[F](cfg.sendMail, JavaMailEmil(blocker)), NotifyDueItemsTask.onCancel[F] ) ) diff --git a/modules/joex/src/main/scala/docspell/joex/mail/EmilHeader.scala b/modules/joex/src/main/scala/docspell/joex/mail/EmilHeader.scala new file mode 100644 index 00000000..9fbdb609 --- /dev/null +++ b/modules/joex/src/main/scala/docspell/joex/mail/EmilHeader.scala @@ -0,0 +1,14 @@ +package docspell.joex.mail + +import emil.builder._ + +object EmilHeader { + + // Remove with next emil version + def optionalHeader[F[_]](name: String, value: Option[String]): Trans[F] = + value.map(v => CustomHeader[F](name, v)).getOrElse(Trans[F](identity)) + + def listId[F[_]](listId: String): Trans[F] = + optionalHeader("List-Id", Option(listId).filter(_.nonEmpty)) + +} diff --git a/modules/joex/src/main/scala/docspell/joex/notify/NotifyDueItemsTask.scala b/modules/joex/src/main/scala/docspell/joex/notify/NotifyDueItemsTask.scala index 67ee2745..2f6eb196 100644 --- a/modules/joex/src/main/scala/docspell/joex/notify/NotifyDueItemsTask.scala +++ b/modules/joex/src/main/scala/docspell/joex/notify/NotifyDueItemsTask.scala @@ -12,6 +12,7 @@ import docspell.store.records._ import docspell.store.queries.QItem import docspell.joex.scheduler.{Context, Task} import cats.data.OptionT +import docspell.joex.mail.EmilHeader import docspell.joex.notify.MailContext import docspell.joex.notify.MailTemplate @@ -19,7 +20,7 @@ object NotifyDueItemsTask { val maxItems: Long = 7 type Args = NotifyDueItemsArgs - def apply[F[_]: Sync](emil: Emil[F]): Task[F, Args, Unit] = + def apply[F[_]: Sync](cfg: MailSendConfig, emil: Emil[F]): Task[F, Args, Unit] = Task { ctx => for { _ <- ctx.logger.info("Getting mail configuration") @@ -27,7 +28,7 @@ object NotifyDueItemsTask { _ <- ctx.logger.info( s"Searching for items due in ${ctx.args.remindDays} days…." ) - _ <- createMail(mailCfg, ctx) + _ <- createMail(cfg, mailCfg, ctx) .semiflatMap { mail => for { _ <- ctx.logger.info(s"Sending notification mail to ${ctx.args.recipients}") @@ -56,12 +57,13 @@ object NotifyDueItemsTask { } def createMail[F[_]: Sync]( + sendCfg: MailSendConfig, cfg: RUserEmail, ctx: Context[F, Args] ): OptionT[F, Mail[F]] = for { items <- OptionT.liftF(findItems(ctx)).filter(_.nonEmpty) - mail <- OptionT.liftF(makeMail(cfg, ctx.args, items)) + mail <- OptionT.liftF(makeMail(sendCfg, cfg, ctx.args, items)) } yield mail def findItems[F[_]: Sync](ctx: Context[F, Args]): F[Vector[QItem.ListItem]] = @@ -81,6 +83,7 @@ object NotifyDueItemsTask { } yield res def makeMail[F[_]: Sync]( + sendCfg: MailSendConfig, cfg: RUserEmail, args: Args, items: Vector[QItem.ListItem] @@ -99,7 +102,9 @@ object NotifyDueItemsTask { MailBuilder.build( From(cfg.mailFrom), Tos(recp), - Subject("Next due items"), + XMailer.emil, + Subject("[Docspell] Next due items"), + EmilHeader.listId(sendCfg.listId), MarkdownBody[F](md).withConfig( MarkdownConfig("body { font-size: 10pt; font-family: sans-serif; }") )