2022-07-02 Paying my bills with Emacs

I use Emacs to pay my bills. Literally. I mean, I use it in my day job, obviously, but it’s not what I’m talking about today.

In Poland, the most often used way to pay bills like electicity, phone, internet etc. is via bank transfers. To make a transfer you need to type at least the account number of the person or company you transfer money to, the description of the transaction and (obviously) the amount you need to pay. To simplify things, I defined a few recurring recipients in my bank system so that I only need to choose the recipient and type in the invoice number (as the description) and the amount.

Still, this is a bit cumbersome. And this is where Emacs can come in.

See, the way I know the invoice number and the amount is that I receive an email with that information. I can then meticulously copy them into the form on the bank website. So, I decided to make this process at least a bit more streamlined. This required solving two issues. The first one is extracting the necessary data from the email. Nowaday the go-to solution for such things are probably neural networks or some other AI. I decided to keep things simple and use the old and tried evil;-) AI called “regular expressions”. Since there are just a few templates of the emails I get, it’s not difficult to write a regex working with these few teamplates.

The second problem is making it easy to copy the two pieces of data – the amount and the invoice number – to the web form. If only we had two system clipboards instead of one! But wait, we do – X Window has the famous “primary selection”, completely independent of the clipboard! So, my solution is basically putting the amount in the primary selection (yanked with the middle mouse button) and the invoice number in the clipboard (yanked with C-v). And that’s it! Here’s the code (as an example, I left the regex for only one email template and translated it into English).

(defun prepare-bank-transfer-data ()
  "Prepare bank transfer data based on current buffer.
This command should be called when viewing an email with payment
    (let ((amount
	     (goto-char (point-min))
	     (re-search-forward "amount due:?\\s-+\\([0-9.,]+\\)")
	     (match-string 1)))
	     (goto-char (point-min))
	     (re-search-forward "invoice number:?\\s-+\\([a-z0-9/_-]+\\)")
	     (match-string 1))))
      (message "amount: (middle click) %s, invoice number (C-v): %s" amount invoice-number)
      (gui-set-selection 'PRIMARY amount)
      (gui-set-selection 'CLIPBOARD invoice-number))))

CategoryEnglish, CategoryBlog, CategoryEmacs