Go implementation of the JWZ email threading algorithm

Go Report Card PkgGoDev Release

The JWZ Threading algorithm written in Go

Gather Stars Logo

This is an open source Go implementation of the widely known JWZ message threading algorithm originally written by Jamie Zawinsky - see https://www.jwz.org/doc/threading.html[his explanation here].

You will find an example of implementing the interface(s) needed to operate this package in the /examples/visualize directory.

See the godoc for examples in documentation form, and the example in examples\visualize

Functionality

The package provides the original JWZ algorithm to implementors of the Threadable interface. It has been tested against many thousands of emails. The interface provides a few extra features over the original Java version, but these are additions and enhancements to the interface, not algorithmic changes.

As well as providing the threading capability itself, the package also provides:

  • A generic walker, to which you can provide a function to operate upon the nodes in the threaded tree.
  • A generic sorter, to which you can provide your own comparison function (a byDate example is provided)

Feel free to report any issues and offer any additions by pull requests.

Quick start

  include "github.com/gatherstars-com/jwz"
  ~/myproject: go mod tidy
	// Use the enmime package to build all the emails we find under the given directory and store them in a slice
	// of structs which implement the Threadable interface
	//
	//
	threadables, err := buildEnvelopes(testData, sizeHint)
	if err != nil {
		log.Printf("Unable to walk the eml directory: %#v", err)
		os.Exit(1)
	}

	// Now we have a big slice of all the emails, lets use our jwz algorithm to place them in to a thread tree
	//
	threader := jwz.NewThreader()
	sliceRoot, err := threader.ThreadSlice(threadables)
	if err != nil {
		log.Fatalf("Email threading operation return fatal error: %#v", err)
	}

	// Sort it Rodney!
	//
	x := jwz.Sort(sliceRoot, byDate)

An implementation of buildEnvelopes can be found in examples\visualizer\handlers.go

Similar Resources

End-to-end encrypted email for the mesh networking age

Yggmail It's email, but not as you know it. Introduction Yggmail is a single-binary all-in-one mail transfer agent which sends and receives email nati

Jan 2, 2023

envio de email via SMTP com anexo usando Go

gosendmail - SMTP This repo is a simple net/smtp abstraction for sending emails using SMTP. With it we can send emails With copy, with blind copy and

Aug 18, 2022

a simple api that sent spam via sms and email

a simple api that sent spam via sms and email routes: /sms /email example request with python

Oct 19, 2021

📮 Simple (but useful) email sender written in pure Go v1.17. Support HTML templates and attachments.

📮 Go Email Sender Simple (but useful) email sender written in pure Go v1.17. Yes, yet another email package here! 😅 Support HTML templates and attac

Dec 31, 2021

Monitoring and automation for Open Source email servers, starting with Postfix.

Monitoring and automation for Open Source email servers, starting with Postfix.

Welcome to Lightmeter Control Center, the Open Source mailops monitoring application.

Dec 19, 2022

Experimental email attachment downloader for Kobo devices (gmail only ATM)

KoboMail Experimental email attachment downloader for Kobo devices (gmail only ATM) What is KoboMail? It is a software that will read emails sent to u

Jan 9, 2023

In this project I just created email-verification Code.

mail-verification In this project I just created email-verification Code. Setup Before run the program. Type go mod tidy on terminal. After that chang

Nov 4, 2021

aerc is an email client for your terminal.

aerc aerc is an email client for your terminal. This is a fork of the original aerc by Drew DeVault. A short demonstration can be found on https://aer

Dec 14, 2022

📧 Go client for the OhMySMTP email service

go-ohmysmtp A Go wrapper for the OhMySMTP email service. Package https://github.com/jackcoble/go-ohmysmtp Examples Send an email. package main impor

Dec 13, 2021
Comments
  • fix: don't add a link if parentRef is already linked to ref

    fix: don't add a link if parentRef is already linked to ref

    Certain email threads can have References in differing orders which can create an issue when parsing. When parsing other emails within the tree, it is possible for a node have it's parent set to an node which is already the self-node's child. For example, B has parent A and also child A. This situation creates an infinite loop in the findChild routine, resulting in a runtime panic.

    Per the JWZ algorithm:

    Do not add a link if adding that link would introduce a loop: that is, before asserting A->B, search down the children of B to see if A is reachable, and also search down the children of A to see if B is reachable. If either is already reachable as a child of the other, don't add the link.

    The implementation currently only inspects for B in the children of A. Add a check for A in the children of B before creating new links. Add two test emails which create a panic when threading without this check.

    Update test values to reflect new threading results. Note that 6 emails in the original test suite are now included in the threads that weren't before. The passing test quantities are therefore 6 + 2 = 8 additional emails in the threaded view. See attached images for the before and after views of the threads.

    Before

    before

    After

    Note that the thread "bad focus ..." has the full tree now

    after

  • fix: don't add a link if parentRef is already linked to ref

    fix: don't add a link if parentRef is already linked to ref

    Certain email threads can have References in differing orders which can create an issue when parsing. When parsing other emails within the tree, it is possible for a node have it's parent set to an node which is already the self-node's child. For example, B has parent A and also child A. This situation creates an infinite loop in the findChild routine, resulting in a runtime panic.

    Per the JWZ algorithm: Do not add a link if adding that link would introduce a loop: that is, before asserting A->B, search down the children of B to see if A is reachable, and also search down the children of A to see if B is reachable. If either is already reachable as a child of the other, don't add the link.

    The implementation currently only inspects for B in the children of A. Add a check for A in the children of B before creating new links. Add two test emails which create a panic when threading without this check.

    Update test values to reflect new threading results. Note that 6 emails in the original test suite are now included in the threads that weren't before. The passing test quantities are therefore 6 + 2 = 8 additional emails in the threaded view. See attached images for the before and after views of the threads.

  • tests: fix corrupted date header in sample messages

    tests: fix corrupted date header in sample messages

    Two sample email files in test/testdata contain corrupted date headers. Since https://github.com/golang/go/commit/3ef8562c9c2c7 (go 1.19), this invalid date format is somehow parsed successfully. With go 1.18 and earlier, the parsing fails and Email.GetDate() returns time.Unix(0, 0) (from jwz_test.go).

    https://github.com/gatherstars-com/jwz/blob/v1.3.0/jwz_test.go#L178-L180

    This causes the order of threads to be different in go 1.19 and causes the unit tests to fail.

    --- FAIL: ExampleSort (0.08s)
    got:
    First node subject: 2002-02-01 05:44:14 +0000 UTC : Please help a newbie compile mplayer :-)
    want:
    First node subject: 1970-01-01 00:00:00 +0000 UTC : Re: My source: RE: A biblical digression :: node synthesized by https://gatherstars.com/
    

    Fix the corrupted date headers and adjust unit test expected result accordingly.

Related tags
Email-searcher - Given a domain name and real name, attempt to find an existing email for that user.

email-searcher Given a domain name and real name, attempt to find an existing email for that user. Using Run it with both the domain and name flags, l

Jan 2, 2022
Sending emails using email server talking to RabbitMQ and send grid server sending emails to email ids consumed from RabbitMQ
Sending emails using email server talking to RabbitMQ and send grid server sending emails to email ids consumed from RabbitMQ

Sending emails using email server talking to RabbitMQ and send grid server sending emails to email ids consumed from RabbitMQ

Oct 27, 2022
Sieve email filtering language (RFC 5228) implementation in Go.

go-sieve Sieve email filtering language (RFC 5228) implementation in Go.

Sep 29, 2022
Robust and flexible email library for Go

email Robust and flexible email library for Go Email for humans The email package is designed to be simple to use, but flexible enough so as not to be

Dec 30, 2022
:white_check_mark: A Go library for email verification without sending any emails.

email-verifier ✉️ A Go library for email verification without sending any emails. Features Email Address Validation: validates if a string contains a

Dec 30, 2022
Golang package for send email. Support keep alive connection, TLS and SSL. Easy for bulk SMTP.

Go Simple Mail The best way to send emails in Go with SMTP Keep Alive and Timeout for Connect and Send. IMPORTANT Examples in this README are for v2.2

Jan 8, 2023
An email MIME artist for golang

Marcel is a tool to generate IETF compliant emails in raw MIME format. I mainly use this for generating emails with attachments and sending them via amazon SES. If that's what you're doing too, you may want notifications

Nov 7, 2022
:incoming_envelope: Simple email interface across multiple service providers (ses, postmark, mandrill, smtp)
:incoming_envelope: Simple email interface across multiple service providers (ses, postmark, mandrill, smtp)

go-mail Lightweight email package with multi-provider support (ses, mandrill, postmark) Table of Contents Installation Documentation Examples & Tests

Dec 10, 2022
EMail Searcher By Golang
EMail Searcher By Golang

GiveMeMail ▄████ ██▓ ██▒ ██▓ ▓██████ ███▄ ▄███▓▓██████ ███▄ ▄███▓ ██ ██▓ ██▓ ██▒ ▀█▒ ▓██▒ ▓██░ █▒ ▓█ ▀ ▓██▒▀█▀ ██▒▓█

Dec 4, 2021
✉️ A Go library for email verification without sending any emails.

email-verifier ✉️ A Go library for email verification without sending any emails. Features Email Address Validation: validates if a string contains a

Jun 24, 2021