Skip to content

d--j/go-milter

 
 

Repository files navigation

go-milter

GoDoc Build status Coverage Status

A Go library to write mail filters.

Features

  • With this library you can write both the client (MTA/SMTP-Server) and server (milter filter) in pure Go without sendmail's libmilter.
  • Easy wrapper of the milter protocol that abstracts away many milter protocol quirks and lets you write mail filters with little effort.
  • UTF-8 support
  • IDNA support
  • Client & Server support milter protocol version 6 with all features. E.g.:
    • all milter events including DATA, UNKNOWN, ABORT and QUIT NEW CONNECTION
    • milter can skip e.g. body chunks when it does not need all chunks
    • milter can send progress notifications when response can take some time
    • milter can automatically instruct the MTA which macros it needs.
  • Automatic integration tests that test the compatibility with Postfix and Sendmail.

Installation

go get -u github.com/d--j/go-milter

Usage

The following example is a milter filter that adds [⚠️EXTERNAL] to the subject of all messages of unauthenticated users.

See GoDoc for more documentation and an example for a milter client or a raw milter server.

package main

import (
  "context"
  "flag"
  "log"
  "strings"

  "github.com/d--j/go-milter/mailfilter"
)

func main() {
  // parse commandline arguments
  var protocol, address string
  flag.StringVar(&protocol, "proto", "tcp", "Protocol family (unix or tcp)")
  flag.StringVar(&address, "addr", "127.0.0.1:10003", "Bind to address or unix domain socket")
  flag.Parse()

  // create and start the mail filter
  mailFilter, err := mailfilter.New(protocol, address,
    func(_ context.Context, trx mailfilter.Trx) (mailfilter.Decision, error) {
      // Quarantine mail when it is addressed to our SPAM trap
      if trx.HasRcptTo("spam-trap@スパム.example.com") {
        return mailfilter.QuarantineResponse("train as spam"), nil
      }
      // Prefix subject with [⚠️EXTERNAL] when user is not logged in
      if trx.MailFrom().AuthenticatedUser() == "" {
        subject, _ := trx.Headers().Subject()
        if !strings.HasPrefix(subject, "[⚠️EXTERNAL] ") {
          subject = "[⚠️EXTERNAL] " + subject
          trx.Headers().SetSubject(subject)
        }
      }
      return mailfilter.Accept, nil
    },
    // optimization: call the decision function when all headers were sent to us
    mailfilter.WithDecisionAt(mailfilter.DecisionAtEndOfHeaders),
  )
  if err != nil {
    log.Fatal(err)
  }
  log.Printf("Started milter on %s:%s", mailFilter.Addr().Network(), mailFilter.Addr().String())

  // wait for the mail filter to end
  mailFilter.Wait()
}

License

BSD 2-Clause

Credits

Based on https://github.com/emersion/go-milter by Simon Ser which is based on https://github.com/phalaaxx/milter by Bozhin Zafirov. Max Mazurov made major contributions to this code as well.

About

Go library to write mail filters

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 98.1%
  • Shell 1.6%
  • Other 0.3%