awdeorio / mailmerge

A simple, command line mail merge tool.
MIT License
142 stars 41 forks source link

JSONL input #109

Open nickolay opened 4 years ago

nickolay commented 4 years ago

mailmerge currently reads CSV files as data source.

For more complex templates, for instance containing one or more tables, a more appropriate format seems to be JSON, or, more specifically, json lines, which can be generated by some databases natively (see e.g. FOR JSON AUTO in MS SQL)

I have preliminary implementation in my branch: https://github.com/nickolay/mailmerge/commit/02efaf27e7204098467cd7438001fc66bb76d6d0

awdeorio commented 4 years ago

I hadn't thought of this before. Maybe you could post a motivating example here, with a small template and a very small database? I'm having trouble understanding the problem with tables you mention above.

nickolay commented 4 years ago

Oops, sorry! I mean a template like this:

FROM: noreply@example.com
TO: {{to_address}}
Subject: "Foo" changes to review
Content-Type: text/html

<html>
<head><meta http-equiv=content-type content="text/html; charset=utf-8"></head>
 <body>
Hello {{name}}!

The following changes to Foo might interest you:

<table><tr>
    <th>ID</th>
    <th>Name (old)</th>
    <th>Name (new)</th>
</tr>
{% for row in values %}
<tr>
    <td>{{row["id"]}}</td>
    <td>{{row["name_old"]}}</td>
    <td {{' style="background-color:#FFD966"' if row["name_old"] != row["name_new"] else '#' }}>{{row["name_new"]}}</td>
</tr>
{% endfor %}
</table>

...with a data source as follows we'll have two e-mails generated, each containing a two-row table:

{"to_address": "nickolay1@example.com", "name": "Nickolay1", "values": [{"id":5, "name_old": "Foo", "name_new": "Bar"}, {"id": 7, "name_old": "Baz", "name_new": "Baz" }]}
{"to_address": "nickolay2@example.com", "name": "Nickolay2", "values": [{"id":9, "name_old": "Qux", "name_new": "Bar"}, {"id": 7, "name_old": "Baz", "name_new": "Baz" }]}

With a CSV datasource the input to the template can only be a fixed number of text parameters (one for each CSV column). So I have to either provide the table's prerendered HTML in the CSV or use a more complex format, hence the JSON(L) idea.

awdeorio commented 4 years ago

I can see this being helpful in a case where different recipients will have different numbers of values filled in. A table, like you said, is a good motivating example.

Testing would be important. Here are some things off the top of my head.