Skip to content

Releases: anonaddy/anonaddy

v1.6.1

10 May 21:02
79ba215

Choose a tag to compare

v1.6.0

07 May 13:55
2ccafba

Choose a tag to compare

  • Added inbound quarantined to failed deliveries for emails that were previously rejected as spam
  • Added failed delivery notification preferences, allowing you to turn off failed delivery notifications
  • Added modal confirmation for downloading a quarantined email
  • Improved some failed delivery error codes to be more clear
  • Added quarantine action to rules
  • Recipients are no longer detached from aliases when the alias is deleted

Breaking Changes

In order to quarantine spam emails detected by Rspamd instead of rejecting them we need to make some changes to Rspamd config.

Edit /etc/rspamd/local.d/milter_headers.conf and update the add_should_quarantine_header routine (this should already be present):

  add_should_quarantine_header = <<EOD
return function(task, common_meta)
  local metric = task:get_metric_score('default')
  local score = metric and metric[1] or 0
  local reject_threshold = 15.0
  local should_quarantine = false
  local quarantine_reason = nil

  if score >= reject_threshold then
    should_quarantine = true
    quarantine_reason = quarantine_reason or '5.7.1 Spam message rejected'
  end

  if should_quarantine then
    return nil,
      {
        ['X-AnonAddy-Should-Quarantine'] = 'Yes',
        ['X-AnonAddy-Quarantine-Reason'] = quarantine_reason or '5.7.1 Spam message rejected'
      },
      {
        ['X-AnonAddy-Should-Quarantine'] = 0,
        ['X-AnonAddy-Quarantine-Reason'] = 0
      },
      {}
  end

  return nil,
    {},
    {
      ['X-AnonAddy-Should-Quarantine'] = 0,
      ['X-AnonAddy-Quarantine-Reason'] = 0
    },
    {}
end
EOD;
}

Then edit (or create) /etc/rspamd/local.d/actions.conf and set a high score threshold for the rejection action. This is to prevent Rspamd rejecting messages outright so that we can instead quarantine them:

reject = 500;      # disable hard reject in order to quarantine

Then run sudo service rspamd reload to reflect these changes.

v1.5.1

05 May 12:37

Choose a tag to compare

  • Upgraded to Laravel 13
  • Added pagination to Blocklist entries
  • Added filters and sorting to blocklist
  • Improved parsing of mail log, 4.X.X deferrals are no longer stored, fixed an issue with IPv6 addresses
  • Upgraded Webauthn package

Full Changelog: v1.5.0...v1.5.1

v1.5.0

10 Apr 15:43

Choose a tag to compare

  • Added inbound rejections to failed deliveries. This means that attempts to send emails to your aliases that were rejected by the addy.io mail servers can now be seen.
  • Added pagination to failed deliveries
  • Added inbound/outbound filter to failed deliveries
  • Added an email notification when an alias is deactivated or deleted via one-click unsubscribe
  • Performance improvements to AccessPolicy and recipient lookups
  • Updated self-hosting guide with these breaking changes

Breaking Changes

In order to parse the Postfix log files and display inbound rejections for your aliases you will need to give web app system user (e.g. johndoe) permission to view the mail log:

sudo setfacl -m u:johndoe:r /var/log/mail.log

Run sudo apt install acl if the above command fails.

You may also need to add the following to the postrotate hook of logrotate so that this is reapplied when you mail log is rotated:

sudo vim /etc/logrotate.d/rsyslog
/var/log/mail.log
{
        ...
        postrotate
                /usr/lib/rsyslog/rsyslog-rotate
                [ -f /var/log/mail.log ] && setfacl -m u:johndoe:r /var/log/mail.log
        endscript
}

If your mail log is at a location other than /var/log/mail.log you can set this in your .env file:

POSTFIX_LOG_PATH=/path/to/mail.log

v1.4.1

08 Apr 13:19

Choose a tag to compare

  • πŸ“Œ Added pinned aliases feature. Pinned aliases will always appear at the top of your alias list.
  • Added new alias_count filter to the recipients API endpoint, set it to false to omit alias count for a faster response.

v1.4.0

08 Apr 11:22

Choose a tag to compare

  • Added new blocklist feature that allows you to block senders by their email address or entire domain
  • Added List-Unsubscribe behaviour setting
  • Added quick option to add sender to blocklist from failed deliveries page

Breaking Changes

  1. The new blocklist feature requires an update to Rspamd config in order to work.

You must create a new file named addy_blocklist.lua at /etc/rspamd/lua.local.d/addy_blocklist.lua, in this file enter the following contents (making sure to change blocklist_api_url and blocklist_secret to your own values):

--[[
  Rspamd Lua script: user blocklist check via Laravel HTTP API.

  Deploy this on each mail server that runs Rspamd. Point blocklist_api_url
  at your Laravel app.

  Required: rspamd_http (built-in). Symbol BLOCKLIST_USER is set when the
  API returns block=true; map this symbol to an action (reject/discard) in
  your Rspamd actions config.
--]]

local blocklist_api_url = 'https://your-addy-instance.com/api/blocklist-check'
local blocklist_secret = ''  -- same as BLOCKLIST_API_SECRET in .env, or leave '' if unset

-- Simple percent-encode for query parameter values (rspamd_http has no escape)
local function url_encode(s)
  if s == nil or s == '' then return '' end
  s = tostring(s)
  return (s:gsub('[^%w%-_.~ ]', function(c)
    return string.format('%%%02X', string.byte(c))
  end):gsub(' ', '%%20'))
end

local logger = require "rspamd_logger"
local rspamd_http = require 'rspamd_http'

rspamd_config:register_symbol({
  name = 'BLOCKLIST_USER',
  callback = function(task)
    local rcpts = task:get_recipients('smtp')
    local from_env = task:get_from('smtp')
    if not rcpts or #rcpts == 0 then
      logger.infox('blocklist: skip - missing recipient')
      return false
    end
    local recipient = (rcpts[1].addr and rcpts[1].addr:lower()) or ''

    local sender = ''
    if from_env and from_env.addr then
      sender = from_env.addr:lower()
    end

    local from_email = ''
    local from_hdr = task:get_header('From')
    if from_hdr then
      local raw = (type(from_hdr) == 'table') and (from_hdr[1] or from_hdr) or from_hdr
      raw = tostring(raw)
      from_email = raw:match('<([^>]+)>') or raw:match('%S+@%S+') or ''
      from_email = from_email:lower()
    end
    if from_email == '' then
      from_email = sender
    end

    if recipient == '' or (sender == '' and from_email == '') then
      logger.infox('blocklist: skip - missing recipient or from (recipient=%1, sender=%2, from_email=%3)', recipient, sender, from_email)
      return false
    end

    local url = blocklist_api_url
      .. '?recipient=' .. url_encode(recipient)
      .. '&from_email=' .. url_encode(from_email)

    local req_headers = {}
    if blocklist_secret ~= '' then
      req_headers['X-Blocklist-Secret'] = blocklist_secret
    end

    rspamd_http.request({
      url = url,
      headers = req_headers,
      timeout = 2.0,
      task = task,
      callback = function(err_message, code, body, _headers)
        if err_message then
          logger.warnx('blocklist: HTTP error - %1', err_message)
          return
        end
        if code == 200 and body and body:match('"block"%s*:%s*true') then
          task:set_pre_result('reject', '550 5.1.1 Address not found')
          task:insert_result(true, 'BLOCKLIST_USER', 1000.0, '550 5.1.1 Address not found')
          logger.infox('blocklist: BLOCKLIST_USER set for recipient=%1 from_email=%2', recipient, from_email)
        end
      end,
    })

    return false  -- do not match symbol here; only HTTP callback may add it via insert_result
  end,
  score = 1000.0,
})

You also need to update your .env file with the following new values:

# Blocklist API (Rspamd): comma-separated IPs allowed to call /api/blocklist-check; optional shared secret
BLOCKLIST_API_ALLOWED_IPS=127.0.0.1
BLOCKLIST_API_SECRET=

Make sure to add your own server's IP to the list above. If you have chosen to set a shared secret then make sure BLOCKLIST_API_SECRET is the same value as whatever you've chosen above in addy_blocklist.lua.

  1. Upgrade to Vite 8 may require you to update your node version to 20.19+.

v1.3.8

18 Feb 12:46

Choose a tag to compare

  • Added {{subject}} placeholder to replace subject rule action
  • Added setting to change spam warning behaviour
  • Added new alias formats and option to change alias separator

v1.3.7

21 Jan 10:23

Choose a tag to compare

v1.3.6

05 Jan 14:39

Choose a tag to compare

  • Added dark mode
  • Added Rules that allow you to forward to multiple recipients
  • Added ability to use both 2FA methods at the same time
  • Increased Rule condition values from 10 to 50
  • Fixed credentialId length issue in webauthn_keys table

v1.3.5

29 Jul 19:46

Choose a tag to compare

  • Fixed missing fillable property in v1.3.4