Set list-id header for notification mails

This commit is contained in:
Eike Kettner 2020-04-29 22:44:05 +02:00
parent 03003f2317
commit 0a1b3fcf95
9 changed files with 57 additions and 8 deletions

View File

@ -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*

View File

@ -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).

View File

@ -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)
)

View File

@ -0,0 +1,3 @@
package docspell.common
case class MailSendConfig(listId: String)

View File

@ -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 {

View File

@ -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 {

View File

@ -78,7 +78,7 @@ object JoexAppImpl {
.withTask(
JobTask.json(
NotifyDueItemsArgs.taskName,
NotifyDueItemsTask[F](JavaMailEmil(blocker)),
NotifyDueItemsTask[F](cfg.sendMail, JavaMailEmil(blocker)),
NotifyDueItemsTask.onCancel[F]
)
)

View File

@ -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))
}

View File

@ -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; }")
)