惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
Arctic Wolf
T
The Blog of Author Tim Ferriss
月光博客
月光博客
Recent Announcements
Recent Announcements
V
V2EX
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 三生石上(FineUI控件)
P
Proofpoint News Feed
The Register - Security
The Register - Security
博客园 - 叶小钗
博客园 - Franky
The Cloudflare Blog
雷峰网
雷峰网
罗磊的独立博客
M
MIT News - Artificial intelligence
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
爱范儿
爱范儿
博客园 - 司徒正美
Recorded Future
Recorded Future
酷 壳 – CoolShell
酷 壳 – CoolShell
Google DeepMind News
Google DeepMind News
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
F
Full Disclosure
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
B
Blog
大猫的无限游戏
大猫的无限游戏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
WordPress大学
WordPress大学
小众软件
小众软件
K
Kaspersky official blog
Attack and Defense Labs
Attack and Defense Labs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Forbes - Security
Forbes - Security
aimingoo的专栏
aimingoo的专栏
IT之家
IT之家
The Last Watchdog
The Last Watchdog
N
News and Events Feed by Topic
B
Blog RSS Feed
S
Security @ Cisco Blogs
美团技术团队
量子位
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cloudbric
Cloudbric
Hacker News - Newest:
Hacker News - Newest: "LLM"

Hacker News: Show HN

PurrrrrFocus: Pomodoro Timer App - App Store Workflow Engine — Multi-Step Orchestration for Bun RapidPhoto: Pro Photo Editor App - App Store GitHub - DheerG/swarms: Achieve extraordinary results with claude code across a variety of tasks SPICE simulation → oscilloscope → verification with Claude Code — Lucas Gerads Show HN: VCoding – A 5 MB native Windows IDE with no dynamic dependencies Show HN: LLMs don't hallucinate because they're bad at math, it's the format GitHub - Agent-FM/agentfm-core: AgentFM is a peer-to-peer network that turns everyday computers into a decentralized AI supercomputer. AgentFM lets you run massive AI workloads directly across a global mesh of idle CPUs and GPUs. Show HN: Tracking Top US Science Olympiad Alumni over Last 25 Years GitHub - Potarix/agent-hub: One place to talk to all your agents Show HN: Runtime security for AI agents(injection,tool abuse, data exfiltration) GitHub - dubeyKartikay/lazyspotify: Terminal Spotify client for macOS and Linux GitHub - the-banana-tool/king-louie: Easy to use GUI Personal AI Assistant. Win/Linux/Mac. Show HN I made my vacation rental bookable by AI agents–no Airbnb, 0% commission GitHub - basteez/jsf-autoreload: maven plugin to enable hot reload on jsf projects uvm32/hosts/host-gdbstub at main · ringtailsoftware/uvm32 GitHub - labsai/EDDI: Config-driven engine that turns JSON into production-grade AI agents. Multi-agent orchestration, 12+ LLM providers, MCP/A2A protocols, RAG, persistent memory, and enterprise compliance (EU AI Act, GDPR, HIPAA). Built on Quarkus. GitHub - glitchnsec/fortyone-oss: AI Executive Assistant Platform Quickstart | Alien GitHub - muxshed/shed: One stream in, or many. Every destination, simultaneously. No cloud middleman, no per-channel fees, no limits. GitHub - ocrbase-hq/ocrbase: 📄 PDF/IMG ->.MD/JSON Document OCR API for PaddleOCR and GLMOCR. Self-hostable. GitHub - impactjo/home-memory: MCP server that lets your AI assistant remember everything about your home. GitHub - Sets88/dbcls: DbCls is a powerful terminal database client that supports various databases GitHub - neptun2000/heor-agent-mcp GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh RollQuation: Math Puzzles - Apps on Google Play GitHub - dropbox/witchcraft Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis GitHub - opentalon/opentalon: OpenTalon is an open-source platform built from the ground up in Go as a robust alternative to OpenClaw LinkedIn™ 职位抓取工具 - Chrome 应用商店 GitHub - EdoardoBambini/Agent-Armor-Iaga: AI agents are getting tool access — shell, file system, databases, APIs, secrets. But **nobody is governing what they actually do with it**. Frameworks like LangChain, CrewAI, AutoGen, and Claude Code give agents the power to execute. Agent Armor gives you the power to control, audit, and approve every single action before it happens. HN Vibes — Week 15, Apr 7–13 2026 GitHub - chojs23/ec: Easy terminal-native 3-way git mergetool vim-like workflow GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. GitHub - JakOb-dotcom/cloud-sandbox-security-analysis: Technical analysis and Proof of Concept (PoC) regarding environment variable exfiltration in containerized cloud sandboxes via side-channel data leaks. Springboards - Flint Alpha Show HN: A simpler coding agent harness GitHub - audiodude/sudomake-friends GitHub - 256thFission/mini-mythos: OSS clone of Anthropic’s Mythos harness to locate C/C++ memory vulnerabilities Show HN: OpenParallax: OS-level privilege separation for AI agent execution Hacker News Sorted - Chrome 应用商店 Show HN: How to Install Docker on Ubuntu 24.04 LTS: Complete 2026 Guide GitHub - himanshudongre/smriti GitHub - sverrirsig/claude-control: macOS desktop dashboard for monitoring and managing multiple Claude Code sessions GitHub - ory/dockertest: Write better integration tests! Dockertest helps you boot up ephermal docker images for your Go tests with minimal work. Chiral - Chrome 应用商店 Show HN: Two Claudes collaborating through shared memory on a $100 mini-PC GitHub - pmichaillat/latex-cv: Minimalist LaTeX template for academic CVs GitHub - oguzbilgic/posse: A web UI for Anthropic Managed Agents. GitHub - sshiraz/depsly: Dependency risk analysis tool for npm packages ABI Add safari/agent-harness — Safari browser automation via safari-mcp by achiya-automation · Pull Request #212 · HKUDS/CLI-Anything GitHub - Halfblood-Prince/trustcheck: Verify PyPI package attestations and improve Python supply-chain security GitHub - oguzbilgic/kern-ai: Agents that do the work and show it. GitHub - bruits/satteri: High-performance Markdown and MDX processing for the JavaScript ecosystem GitHub - tylergibbs1/feedstock: High-performance web crawler and scraper for TypeScript, powered by Bun and Playwright GitHub - Grimm67123/grimmbot: The self-improving sandboxed and open-source AI agent. With persistent memory and scheduling. GitHub - whitevanillaskies/whitebloom: Local whiteboard that blooms. GitHub - hwdsl2/docker-whisper: Docker image for a self-hosted Whisper speech-to-text server with speaker diarization and OpenAI-compatible transcription and translation APIs. Powered by faster-whisper. Supports all Whisper models, NVIDIA GPU (CUDA) acceleration, JSON/SRT/VTT output, SSE streaming, offline mode, and multi-arch (amd64, arm64). GitHub - yisding/reviewwiggum GitHub - MarwanAlsoltany/serrors: Structured errors for Go: sentinel hierarchies, typed data, custom formatting, and slog integration. GitHub - soatok/age-php GitHub - Luthiraa/markitme GitHub - stagas/rtdiff: realtime git diff gui and AI-assisted commits GitHub - tombedor/excalicharts GitHub - wh1le/excalidraw-edit: Open and edit .excalidraw files from the terminal. Offline, auto-saves to disk. MalExt Sentry - Malicious Extension Scanner - Chrome 应用商店 GitHub - syi0808/asciianimesvg: Generate animated ASCII art SVGs from text. CLI, Rust library, WASM, and web editor. GitHub - zaina-ml/ml_forge: A visual-based graph node editor for training computer vision models. GitHub - anakin87/llm-rl-environments-lil-course: 🌱 A little course on Reinforcement Learning Environments for evaluating and training Language Models GitHub - takaakit/superpowers-uml: Superpowers-UML modifies Superpowers to ensure a software development workflow in which AI agents design through UML modeling. AdriByte Studio - Sviluppo Web e Soluzioni Digitali GitHub - chouligi/angel-copilot: Your personalized Angel Investment Advisor Show HN: MoodSense AI (ML and FastAPI and Gradio, Deployed on Hugging Face) Moodsense Ai - a Hugging Face Space by aman179102 GitHub - agenteractai/lodmem: Level Of Detail Context Management for Agents GitHub - ostefani/subnetlens: A fast, concurrent network scanner with a TUI and plain-text CLI, built in Go. It discovers live hosts on your network, scans their open ports, resolves hostnames, and fingerprints operating systems—delivered. Cyber Pulse: Agentic Intel - Apps on Google Play Whisper API: Self-Hostable Speech to Text Transcription The Agent-Web Protocol Stack: A Research Thesis GitHub - msmarkgu/RelayFreeLLM: A restful API designed to route user prompts to various AI model providers. Show HN: Provepy – A Python decorator that proves your code using Lean and LLMs Show HN: Pardonned.com – A searchable database of US Pardons GitHub - patrickdappollonio/dux: Dux is a terminal UI that lets you run multiple AI coding agents side by side, each in its own git worktree, with full companion terminals, macros, commit generation, and a command palette that knows more tricks than you do. kMC Crystal Simulator Show HN: HyperFlow – A self-improving agent framework built on LangGraph GitHub - stef41/vibescore: 🎵 Grade your vibe-coded project. One command, instant letter grade across security, quality, dependencies, and testing. GitHub - stef41/lmscan: 🔍 Detect AI-generated text and fingerprint which LLM wrote it. Open-source GPTZero alternative. Zero dependencies, works offline. imgur.com GitHub - visionscaper/collabmem: Enabling long-term collaboration with Agentic AI - building up episodic and world model memory over time with in-context awareness 在 Steam 上购买 FriedrichAI: Offline AI 立省 10% GitHub - atripati/ark: AI Runtime Kernel — a context operating system for AI agents. Eliminates tool bloat, loads only what’s needed, and gives LLMs their reasoning space back. GitHub - nowork-studio/toprank: Open-source Claude Code skills for SEO, SEM, Google Ads GitHub - tacomanator/sash: Lightweight macOS menu bar app for reliably cycling through windows of the current application. Appents | Social Media Management for Product-First Teams GitHub - pnhoang/youtube-spam-blocker: Automatically detects and hides spam messages in YouTube Live chat. Set rate limits, keyword filters, and block repeat offenders. GitHub - decisionnode/DecisionNode: CLI + Local MCP - A shared structured memory store across Claude Code, Cursor, Windsurf, Antigravity, and every MCP client. Semantically queryable. GitHub - AvaCodeSolutions/django-email-learning: An open source Django app for creating email-based learning platforms with IMAP integration and React frontend components. The $100K Gap in Kubernetes Security Tooling Function Calling Harness: From 6.75% to 100%
Sanitising Email
mike-cardwel · 2026-06-23 · via Hacker News: Show HN
View Markdown Other Articles

Article written by a human: Mike Cardwell

For the past 15 years or so, I've been using a simple Perl script that I wrote called gpgit to encrypt email stored on my mail server, both incoming and outgoing. It just takes a raw email on stdin and writes the modified email to stdout. It has always been in the back of my mind that I could do a lot more than just encrypting an email, from a privacy and security perspective, but I never felt I had the time to do the project justice. That is, until LLMs came onto the scene.

I have just made available an open source project called Sanimail which I have been using on my own email for a little while now. It does what gpgit does, plus a lot more:

  • Inlining remote content
  • Policy based sanitising of html/css/svg parts
  • Removal of tracking params in links
  • Disarming of privacy invading headers
  • PGP and S/MIME encryption/decryption/signing
  • Other noteworthy options
  • Hardening
  • Deployment
  • Usage tips
  • Project status

Inlining remote content #

One of the long standing issues with email has been pixel tracking via remote images referenced in email HTML parts:

<img src="https://example.com/pixel.png?emailId=U21hcnQgYXkCg">

You view an email, the image is fetched, the sender can now know that you read the email, when, and what your IP was at the time. Some of the larger email providers have started addressing this problem by replacing these links with links to their own proxies:

<img src="https://proxy.example.net/?url=https%3A%2F%2Fexample.com%2Fpixel.png%3FemailId%3DU21hcnQgYXkCg">

So when you view the email, the sender only sees the proxy's IP, not yours. Some even claim to fetch remote content and cache it as soon as the email is delivered (Apple lies about doing this). So that the sender doesn't even know if you actually read the message, let alone when, or from where.

I host my own email and I wanted this functionality for myself, so I added it to Sanimail. Technically, my solution is better because the download is permanent. The proxy solutions created by the big mail providers will expire content from their cache, causing you to re-fetch it if you look at an older email.

$ sanimail --remote-inline < in.eml > out.eml

This searches HTML, CSS and SVGs in the email, to find URLs that would be fetched, fetches them, attaches them to the email, and then updates the link to refer to the attachment instead of the remote URL. There are a whole bunch of limits, timeouts and image optimisations, to make this work well, with corresponding command line options. You can even proxy through Tor if you want to confuse the sender some more --remote-fetch-proxy socks5h://127.0.0.1:9050

--remote-inline                            Fetch remote images and @font-face fonts and attach them inline (cid:); needs network

--remote-fetch-proxy string                Route remote fetches through a SOCKS5/HTTP proxy with remote DNS (works with Tor/.onion)
--remote-fetch-proxy-password string       Password for --remote-fetch-proxy authentication (visible in argv; prefer --remote-fetch-proxy-password-file)
--remote-fetch-proxy-password-file string  Read the --remote-fetch-proxy password from this file (trailing newline trimmed)
--remote-fetch-proxy-user string           Username for --remote-fetch-proxy authentication

--remote-img-deanimate                     Flatten a fetched animated GIF/APNG to its resting frame
--remote-img-deanimate-cap duration        Wall-time cap on de-animating one image; on expiry keep the frame composited so far (0 = unlimited) (default 500ms)
--remote-img-jpeg-quality int              Recompress fetched JPEGs at quality 1-100 (0 = off; re-encodes forced by other flags use 80)
--remote-img-max-height int                Downscale fetched raster images taller than N px (0 = no limit)
--remote-img-max-ram size                  Max approx peak RAM per decoded image (0 = unlimited; e.g. 384MiB) (default 402653184)
--remote-img-max-width int                 Downscale fetched raster images wider than N px (0 = no limit)
--remote-img-optimise                      Convert fetched static images to JPEG, or losslessly recompress PNG, when smaller

--remote-item-max-bytes size               Per-fetch byte cap (0 = unlimited; e.g. 8MiB) (default 8388608)
--remote-max-bytes size                    Total remote-fetch byte budget per message (0 = unlimited; e.g. 16MiB) (default 16777216)
--remote-max-count int                     Max distinct remote URLs fetched per message (0 = unlimited) (default 42)
--remote-max-parallel int                  Max concurrent remote fetches per message (0 = unlimited) (default 16)
--remote-max-parallel-per-host int         Max concurrent remote fetches to one host (0 = unlimited) (default 6)
--remote-timeout duration                  Per-fetch timeout for remote fetches (default 15s)
--remote-total-timeout duration            Aggregate remote-fetch budget per message (0 = unlimited) (default 45s)

--remote-neutralize-failures string        Neutralize failed-fetch image URLs: gone (404/410), permanent (+4xx/unusable, default), all (+403/transient) (default "permanent")
--remote-user-agent string                 User-Agent sent on remote fetches

This of course makes emails larger as they now include attachments. What I do with my own email is route two incoming copies to different folders. One I route to an Archive folder, and the only change I make to it is encrypting with PGP. The other email goes to my Inbox, and has the remote content inlining and various other modifications. My thinking is, that the email in my Inbox is the stuff I actually look at, and I can freely delete it rather than keeping it around for years, as I know I have the original "unmodified" version in my Archive if anything goes wrong or I need to refer to it in the future.

I recommend you use the --remote-img-* options if you're going to inline remote content. These can make a big difference to the byte size of the final email.

Deanimation #

The --remote-img-deanimate options can be particularly effective: A lot of marketing mail embeds multi-megabyte animated GIFs and PNGs nowadays. Not only are these distracting, but they can be shrunk down to a few tens of kilobytes or less if you just capture one frame. And from what I've seen, there really is no need to see these animations. If you can capture the "resting" frame, then that has everything you need. The algorithm I used for capturing the resting frame, is to go to the end of the animation, and then work backwards until we don't have a blank frame. I also short circuit this based on wall time - If we have spent more than a certain amount of time traversing through frames, we just stop where we are and capture the current frame. The reason for this is that some animations have a lot of frames and can take a lot of processing power, and there is scope for somebody creating a malicious GIF with a lot of frames.

Memory usage #

People don't pre-optimise their images. I've seen examples of 30+ megapixel images for social media icons that are displayed using a 32x32 pixel image tag. These images can be small in byte size, because they compress well. However our max-width/height and optimise img options need to decompress these images in order to modify them and sometimes that can take hundreds of megabytes of RAM to do. So we have a --remote-img-max-ram to cap how much memory we are willing to use to optimise an image. If we estimate it is going to exceed this limit, then we don't bother and just attach the original. There is still a total byte size limit option for fetches so we can rely on that at least.

Policy based sanitising of html/css/svg parts #

Should an email contain Javascript? Should it contain iframes, video, forms, meta refresh tags, onclick handlers, file:// URI's, CSS @font-face? You get to define a policy yourself about what should be allowed in HTML, CSS and SVG's. Be they remote, attached, inline, hidden inside data URI's, etc. There are some preset policies as you probably don't want the hassle of doing this (despite it being quite easy). The one I recommend and use myself is "standard". It strips or "unwraps" (removing the tags and leaving the inner text) everything by default, except for a large list of benign allowed HTML tags, attributes, URI schemes, and CSS. I built this list up over time by including things I saw in live email, and anything else myself and Claude could come up with that might need to be in there. It will be further added to over time, especially as new HTML and CSS features are released, but I feel like it's already more than good enough. Anything it does strip, you probably wont notice or miss.

I built a separate library for this policy language and implementation called htmlpolicy. There is also a minimal.policy embedded in Sanimail which does the opposite of the standard policy - it allows everything by default and then strips known bad markup like script tags and on* attributes etc. There are also other embedded policies where I've tried to replicate what Protonmail, Outlook, Yahoo and Gmail do in this regard, when displaying an email. Using what public information I could find. See sanimail policy presets for a list and sanimail policy export to view the raw policies from the command line. You can easily export a preset, modify it, and then use it if you want.

What this amounts to is, sanimail --policy standard < in.eml > out.eml now makes it safer to use email clients like Evolution Mail, which have privacy leaks that they have known about for years and done nothing about: 🤡

# Fix known Evolution Mail privacy leaks
strip-tag link[rel=preconnect],link[rel=dns-prefetch]

You might wonder, what is the point in stripping script tags and other such items, because your email or webmail client will strip or ignore them anyway... Given the number of flaws that the Email Privacy Tester has found over the years, I'd certainly not take that as a given.

--detrack-urls was an easy win as there is already a dataset out there for identifying tracking parameters in URLs. It removes known tracking parameters from anchor tags in html and also URLs in text/plain parts. It also handles known redirectors - https://redirect.example.com/redir?u=https%3A%2F%2Freal.example.com%2F may be replaced by https://real.example.com/ for example. A dataset is embedded in the sanimail binary, but it of course may get out of date. If you want the latest and greatest there are Sanimail commands to download a dataset, and a command line option to use that external dataset:

$ sanimail clearurls export -o ./clearurls.data # Cron this?
$ sanimail --detrack-urls --clearurls-data ./clearurls.data < in.eml > out.eml

Adding/removing/disarming/overwriting headers is all supported of course:

--headers-add stringArray       Add header "Name: value", keeping any existing of that name (repeatable)
--headers-set stringArray       Add header "Name: value", replacing any existing of that name (repeatable)
--headers-strip strings         Remove headers matching comma-separated glob patterns
--headers-disarm strings        Rename matching headers to Sanimail-Disarmed-{Name}

--headers-priority-disarm       Rename priority headers to Sanimail-Disarmed-{Name}
--headers-priority-strip        Remove priority headers
--headers-read-receipts-disarm  Rename read receipt headers to Sanimail-Disarmed-{Name}
--headers-read-receipts-strip   Remove read receipt headers

Why should the sender be able to dictate the priority of the message to you? Do you ever actually want to send read receipts? If not, strip/disarm the header so you can never do so accidentally.

PGP and S/MIME encryption/decryption/signing #

I still encrypt my email that goes into my Archive folder using PGP using the --pgp-encrypt option, but I also added S/MIME support to Sanimail, as I can't use PGP effectively on my iPhone. Especially given that I store my PGP subkeys on external hardware (Yubikey). For live/temporary copies of email that go into my Inbox, I use --smime-encrypt instead.

We also have options for both PGP and S/MIME for signing, if you need that, and also decrypting. You could easily set up Sanimail to automatically decrypt an incoming email (be it PGP or S/MIME encrypted), apply a sanitisation policy, and then re-encrypt with either PGP or S/MIME if you wanted. Sanimail also supports RFC 9788 header protection. I don't believe there is much client support out there yet, but if you have a client that supports it, Sanimail will happily protect the headers that you want to be protected.

I decided to defer to GnuPG for all of the crypto for PGP and S/MIME. It is the only external dependency of the project, and you only need it if you wish to use the PGP or S/MIME options.

Other noteworthy options #

A few other options that are noteworthy:

  • --minify - This will shrink your HTML, CSS and SVG's. Why store/transfer more bytes than necessary?

  • --strip-type - Strip attachments with content-types that you don't trust.

  • --generate-plain - Often, a text/plain part is missing, or is a short message pointing to a webpage, or is just malformed. We can generate our own from the html part that is usually better than the one it came with. There are several modes dictating when it is suitable to generate one.

  • --keep-amp - We strip AMP parts by default. They're a waste of space, we don't do any sanitisation of them, and there will be a HTML part anyway so no need to keep the AMP one. If you are mad, or a Google employee, you might want to use this option to keep such parts.

  • --no-add-message-id - By default, we add a Message-Id header when one is missing. Every message SHOULD have one according to RFC 5322. Use this option if you disagree.

  • --strip-dark-mode - I use dark mode on my phone and laptop. Some transactional and marketing email arrives with dark mode styles that have clearly never been looked at by a human at the sending organisation. So I just strip them, to force light mode. You can do this entirely from policy, but I didn't want to include it in any presets as it's opinionated, so this is just a helper so you don't have to write your own policy to get it. This is the corresponding policy:

    css-strip-media prefers-color-scheme:dark
    css-strip       color-scheme
    strip-tag       meta[name=color-scheme]
    

Hardening #

Sanimail processes all kinds of untrusted and potentially malicious input in the form of MIME structures, HTML, CSS, SVG's and images or various formats. Because of this, I decided it was important to try and reduce the blast radius of any potential compromise. To that end, Sanimail uses Landlock and Seccomp where available, to limit system calls, filesystem access and network access to what is needed. We do this as early as possible during runtime, i.e before we start reading any email. If there is a chance that we will need to launch gpg or gpgsm, Sanimail will launch a second minimal copy of it's self at startup with higher privileges which only handles launching of gpg/gpgsm and passing data back and fourth to the main process. Substantial tests have been written, including fuzzing, to try and avoid compromise in the first place of course.

Deployment #

Statically compiled binaries for various architectures can be downloaded from the Gitlab release page. You can also just clone the repo and make build - As long as you have go installed, this will work.

There are numerous ways to run Sanimail as it simply reads an email from stdin and writes to stdout. I personally use it on my Dovecot server via a Sieve filter:

filter "sanimail" [
    "--detrack-urls",
    "--policy", "standard",
    "--policy-audit-comment",
    "--minify",
    "--generate-plain", "always",
    "--headers-read-receipts-disarm",
    "--headers-priority-disarm",
    "--remote-inline",
    "--remote-img-optimise",
    "--remote-img-deanimate",
    "--remote-img-max-width",  "800",
    "--remote-img-max-height", "600",
    "--strip-dark-mode",
    "--pgp-skip-encrypted",
    "--smime-encrypt", "mike.cardwell@example.com",
    "--gpgsm-path",    "/usr/bin/gpgsm"
];

You can also use an Exim transport or Procmail.

Usage tips #

If you're using --remote-inline, the amount of time it takes to run, is heavily dictated by how many remote items need to be fetched and how quickly that can happen. In Dovecot I had to extend the default amount of time that a sieve filter can run for, because of this.

I had to include --gpgsm-path for my Dovecot sieve filter, because Dovecot wipes out the PATH env variable.

I noticed something odd on my iPhone when I started delivering a PGP encrypted version of an email to the Archive folder, and a second S/MIME encrypted version of it to Inbox. Both had the same Message-Id header, so the iPhone used this to decide that they were the same email. So when I tried to open either copy of the email, I didn't know which one I was going to get. To address this issue I added --headers-strip Message-Id to the filter which created the Archive version. Sanimail strips the Message-Id on that one, but then automatically generates a new unique one to add, because I don't use --no-add-message-id.

Project status #

We are not at v1 yet, because I am still working on this project quite a lot and want the ability to make backwards incompatible changes. I feel like the risk is fairly low that I will need to now, but I don't wish to limit myself. If there is a backwards incompatible change, you'll see it mentioned in the release notes. I have released this project (and htmlpolicy) licensed under the AGPL, but with the possibility of obtaining a commercial license too. I am not interested in hearing why I should use MIT or some other license instead. One consequence of this dual licensing is that if you wish to contribute, you'll need to sign over the rights for me to relicense your contributions. Feature requests, suggestions and bug reports without corresponding patches are welcome of course. Like this article