• Stars
    star
    749
  • Rank 60,575 (Top 2 %)
  • Language
    Ruby
  • License
    MIT License
  • Created almost 13 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Generate complex gmail filters via a neat little ruby DSL

gmail-britta

API Docs Gem Version Build Status

This library helps you generate XML that you can import into gmail's filter settings. It makes it more pleasant to write simple (and even complex) filter chains.

Motivation

As a user of the internet, you probably use gmail, and you probably get a lot of Email - I do. Just like me, you're also likely to have a lot of filters that were once supposed to keep your inbox clean. But every time you click "Filter messages like this", you remember the enormous list of filters you have and how it is only ever going to make things worse in the long run.

But how do you make them better?

As a programmer, I write code. As a metaprogrammer, I write code that writes code. If only gmail filters could be written by a program. Oh wait, they can. There's an import & export function for gmail filters. These filters are exported as XML, and the import in turn takes XML files. What this library does is generate XML that you can import.

Examples

Here are some very simple examples of how gmail-britta can make your life easier:

Archiving (or not) semi-important email

Imagine you're on a discussion mailing list that you skim from time to time - so you want to label email to that list, and archive email from it so it doesn't clog up your inbox. Now, from time to time someone will Cc: you an important message, and you don't want to miss these - what to do?

Naively, you define a filter like this:

list:[email protected] !to:[email protected]
     -> Archive, Label "some-side-project"

But this also means email addressed to you but also sent to that list will be missing the "some-side-project" label. This means you need two filters!

list:[email protected] !to:[email protected]
     -> Archive
list:[email protected]
     -> Label "some-side-project"

Now this can get pretty hairy pretty quickly; and if you ever have to change the filter (e.g., the list changes email addresses), you have to change two filters! Ugh.

With gmail-britta, it's just this:

GmailBritta.filterset do
  filter {
    has %w{list:[email protected]}
    label "some-side-project"
  }.archive_unless_directed
end

That's it - this little piece of ruby code will generate these two filters; and if the list address changes, you just re-import these filters. Easy.

Better detection of your own email address

If you have issued a search for to:me on gmail in the last few months (and you get Email from iCloud nee MobileMe users), you'll notice that to:me also matches the "me" in [email protected]. This is very frustrating mostly because any filter as above that matches on to:me will now also not archive email sent from a me.com account. With gmail-britta, you can define a set of emails that are yours, and archive_unless_directed will generate a filter that matches on those:

GmailBritta.filterset(:me => ['[email protected]', '[email protected]']) do
  filter {
    has %w{list:[email protected]}
  }.archive_unless_directed
end

If/else chains on filters

There are instances where you can't only match on the mailing list - sometimes interesting stuff will be sent to one list (that you want to read), and lots of unnecessary silliness will be sent there too. So, to put email with a certain subject into one label, and to put all the rest into another, you have to make multiple filters. But gmail lacks if/else in filters - you have to duplicate and correctly negate each filter's condition in the next one. Luckily, you have gmail-britta to help you out there:

GmailBritta.filterset do
  filter {
    has %w{list:[email protected] subject:Important}
    label 'work/robots/important'
    # Do not archive
  }.otherwise {
    has %w{list:[email protected] subject:Chunder}
    label 'work/robots/irrelevant'
  }.archive_unless_directed(:mark_read => true).otherwise {
    has %w{list:[email protected] subject:Semirelevant}
    label 'work/robots/meh'
  }.archive_unless_directed
end

A lot of things going on here! First, I hope you notice that this looks similar to an if/else-if statement. Second, you may notice the liberal application of .archive_unless_directed, with an optional :mark_read parameter. Third, do check out the XML generated by this, it's pretty horriffic - but the filters do exactly what the code says:

  1. If the email is sent to that list and has "Important" in the subject, it gets labeled with the work/robots/important label, and won't be archived (unless another filter further down does archive that email).
  2. If the email does not match all the above criteria, but is sent to that list and has "Chunder" in the subject, label it irrelevant, archive it and mark the email as read.
  3. If the email does not match all the above criteria, but is sent to that list and has "Semirelevant" in the subject, label it "meh" and archive it, but don't mark it as read.

Installation & usage

Best to use gmail-britta from a ruby script; but install the gem first:

 gem install gmail-britta

Or include it in your Gemfile:

 gem 'gmail-britta'

This is a simple script that generates filters for you:

#!/bin/env ruby

require 'rubygems'
require 'gmail-britta'

fs = GmailBritta.filterset(:me => ['[email protected]']) do
  filter {
    has %w{from:[email protected]}
    label 'from-the-author-of-gmail-britta'
    never_spam
  }
end
puts fs.generate

Running this script will write to stdout the filter XML that you need. Redirect that to a file and upload it on the bottom of your gmail filter settings, and you'll label email from me and archive it unless I email you specifically. Not that useful, but with your own filters and the recipes above, you should be able to make it work (-:

Some general tips & tricks

Here are some things to note when performing filter-fu with gmail:

  • A filter condition tops out at 1500 chars, apparently. This fits a decent amount of conditions, but something to be careful about. There is no check in gmail-britta against this, but Gmail will refuse to import (or drop) filters that violate this.
  • If you use archive_unless_directed heavily, you almost certainly want to check the "Don't override filters" box in Gmail's Inbox preferences.

A short apology to you, dear code-diver

A lot of this is a bit hacky (particularly the filter condition merge logic), as it started as a oneoff ruby script - very sorry for any amateurish code you may encounter. There are few tests, but so far, it does work for me. Let me know if this made your life harder or easier! (-:

Contributing to gmail-britta

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. (Note that are only very few tests yet. I would totally appreciate if you started fleshing out this suite, but I wouldn't expect you to add much of anything.)
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright

Copyright (c) 2012 Andreas Fuchs. See LICENSE.txt for further details.

More Repositories

1

governor

A rate-limiting library for Rust (formerly ratelimit_meter)
Rust
421
star
2

chars

cha(rs) is a commandline tool to display information about unicode characters
Rust
168
star
3

o

Ring-buffers in go without interface{}
Go
34
star
4

ratelimit_meter

A leaky-bucket-as-a-meter rate-limiting implementation in Rust
Rust
33
star
5

slime

The official SLIME repo is now at https://github.com/slime/slime
Common Lisp
20
star
6

cl-beanstalk

Common Lisp implementation of the beanstalk protocol
Common Lisp
16
star
7

cl-stripe

A (toy) library for interfacing with stripe.com from Common Lisp
Common Lisp
16
star
8

nonzero_ext

Rust traits for nonzero generic integers
Rust
15
star
9

clucumber

Test drive your Common Lisp application from Cucumber!
Ruby
13
star
10

sonarr-plex-cleaner

Garbage-collect your "broadcatching" TV library by deleting seasons that Sonarr has fully downloaded and that are completely watched in Plex.
Rust
13
star
11

Gitrepo

This programmer wanted to use tools. You won't believe what he found!
Ruby
13
star
12

ansible-sshlxd-connection

Ansible 2.0 connection plugin that allows you to access LXD containers remotely through SSH
Python
13
star
13

deploy-flake

A tool for deploying nix flakes to remote systems
Rust
12
star
14

jquery.piemenu

jQuery plugin for HTML5 <canvas>-based radial pie menus.
JavaScript
12
star
15

sbcl

SBCL updated for the git age!
Common Lisp
11
star
16

htpasswd-login

A RESTful authentication service combining .htpasswd and nginx's auth_request
Go
10
star
17

cxml-rpc

XML-RPC for Common Lisp
Common Lisp
10
star
18

deptyr

Run your tty programs pseudo-headlessly under a process supervisor
C
10
star
19

cargo-template-ci

A cargo subcommand that updates .travis.yml from a template
Rust
10
star
20

bangbangcon-talk-2016

My talk at !!con 2016!
Rust
8
star
21

zle-sexp-navigation

Navigate your zsh commandline one (quoted) shell expression at a time
Shell
8
star
22

arsert

Fancy (received pronunciation) assertions with automatic debug information for failures
Rust
8
star
23

weblog

My hugo blog
HTML
8
star
24

disk-spinner

A burn-in tool for spinning rust HDDs
Rust
8
star
25

nix-flake-tests

Use lib.runTests in a nix flake
Nix
7
star
26

idna

Common Lisp IDNA encding / decoding functions
Common Lisp
7
star
27

gotest-ui-mode

Ergonomic output for your go test results in emacs
Emacs Lisp
7
star
28

clsem

A tool that extracts links and definitions from the CL HyperSpec as an RDF graph
Common Lisp
7
star
29

ShareWithBunny

A one-button iOS share extension that speeds up sending things to one recipient
Swift
6
star
30

mcclim

Unofficial CVS->git repo mirror (no longer operational). You are probably looking for https://github.com/robert-strandh/McCLIM
Common Lisp
6
star
31

aoi-swank-plugin

Simple Art of Illusion plugin that opens a Clojure Swank listener on port 4006
Clojure
6
star
32

tmux_min_attacher

Re-attach to the lowest detached TMUX session number
Rust
5
star
33

ratelimit_futures

Rate-limiting for rust futures v0.1
Rust
5
star
34

autobench

Automated Common Lisp implementation builder, version archiver and benchmarker. Supports SBCL, CLISP and CMUCL.
Common Lisp
5
star
35

gmail_synchronize

Something that might one day become an IMAP client for gmail & a local dovecot installation. Work in progress, not much to see here.
Erlang
5
star
36

lambdaheads-slime-demo

The slime/emacs demonstration I gave for Lambdaheads 2010-06-14
Common Lisp
4
star
37

credibility

Table testing and non-fatal assertion support for Rust
Rust
4
star
38

jofrli

Jo Frli, my personal URL shortener (in CL, using redis)
Common Lisp
4
star
39

vcs-gateway

A cron-runnable collection of shell scripts that make it easy to convert CVS-hosted Common Lisp software repostories to git. Includes configuration for CLISP, SBCL, and McCLIM.
Shell
4
star
40

ssh_bookmarker

Automatically create .webloc bookmarks from your SSH config
Rust
4
star
41

futures-ticker

A Ticker implementation based on futures_timer
Rust
4
star
42

technical-writing-workshop

A workshop for Code2040 fellows, at Stripe!
4
star
43

apply-inovelli-defaults

A little (proof-of-concept) tool that applies default values to zigbee2mqtt devices (mainly Inovelli dimmers)
Rust
4
star
44

zpool-exporter-textfile

A tool to export zpool metrics as prometheus metric textfiles
Nix
3
star
45

mz-certificate-transparency

Listen to certificate transparently logs and fire them into a streaming database
Go
3
star
46

intro_chapter_adder

A little tool that adds chapter markers to pauses in the beginning of mkv movies (e.g. after an intro / ad break)
Rust
3
star
47

generate-go-sri

A flake.parts module for generating a go module's NARhashes for use in nix's buildGoModule
Nix
3
star
48

amazon-autotracker

An amazon shipment notification email -> @TrackThis gateway
Ruby
3
star
49

slog-logfmt

a logfmt drain/formatter for slog
Rust
3
star
50

fibonacci_codec

An implementation of Fibonacci coding in Rust
Rust
3
star
51

safe-tls-defaults-mode

Less insecure defaults for TLS on emacs
Emacs Lisp
2
star
52

pgne-el

An emacs mode for electrically balancing expressions in tree-sitter modes
Emacs Lisp
2
star
53

mo-git-blame

An interactive, iterative β€˜git blame’ mode for Emacs
Emacs Lisp
2
star
54

3d-models

Some 3D models that can be printed
2
star
55

gearbox-maintenance

Perform ongoing maintenance on a transmission instance
Rust
2
star
56

py-flac2mp3

flac2mp3 implementation using the Mutagen ID3 library: Can operate incrementally, converts album art.
Python
2
star
57

exbencode

Bencode decoder and decoder in Elixir
Elixir
2
star
58

syslog_stdout

golang syslog->stdout server, based on mcuadros/go-syslog
Go
2
star
59

elixir-dash-docset

Elixir docset builder for Dash.app
Ruby
1
star
60

userscripts

JavaScript
1
star
61

kleinhirn

(experimental) process supervisor & code pre-loader in a container world
Ruby
1
star
62

QSSSHPlugin

(outdated) Quicksilver indexing plugin for SSH known_hosts and authorized_keys files
Objective-C
1
star
63

datadog-disk-divination-checks

Some datadog plugins I wrote to help me keep up with SMART and NVMe data
Python
1
star
64

unicode-tagger

A program to generate arbitrary unicode tag sequences
Rust
1
star
65

antifuchs.github.com

My demo page for web-based stuff
1
star
66

cargo-dev-version-test-example

Repo showing the effects of dev versions in cargo workspaces
Rust
1
star