UNB/ CS/ David Bremner/ teaching/ cs2613/ assignments/ CS2613 Assignment 3

What to hand in, and how to hand it in

Background

This assignment is to write several functions to extract information from some JSON files. Conceptually this is very similar to the second part of L06, except that here you are working in JavaScript rather than Racket. The specifics of working with JSON in JavaScript are covered in L09.

Marking

Test Data

let fs = require('fs');

function read_json_file(filename) {
    let contents = fs.readFileSync(filename);

    return JSON.parse(contents);
}
exports.read_json_file=read_json_file;

Question 1: match function

Write an match function. This method takes a JavaScript object representing a mail message, and a second object defining header fields that must match match.

Make a module message.js that passes at least the following tests (the tests should be saved as spec/message.spec.js; refer to L09 for an introduction to jasmine):

let read_json_file = require("../read_json_file.js").read_json_file;
let message = require("../message.js");

let testMsg = {"headers": {"Subject" : "lunch", "Date" : "now"}};
let otherMsg = {"headers": {"Subject" : "dinner", "Date" : "now"}};

describe("match",
         function() {
             it("message matches itself",
                function () {
                    expect(message.match(testMsg,testMsg.headers)).toEqual(true);
                });
             it("message does not match if field changes",
                function () {
                    expect(message.match(testMsg,otherMsg.headers)).toEqual(false);
                });
             it("match subset of fields",
                function () {
                    expect(message.match(testMsg,{"Subject": "lunch"})).toEqual(true);
                });

Question 2: extracting message bodies.

Depending on the MIME structure of the given email, the message body is represented differently in the resulting JSON. Your task in this part is to reverse engineer those (2) representations and provide uniform output of the body. The JSON structure looks complicated, and in general it can be (as MIME messages can be complicated). To explore the JSON structure, you can view the JSON file in Firefox.

In this sample data there are only two cases, tested below. It is possible to extract the body text with a relatively small amount of code.

Write a function and export it as message.body so that (at least) the following tests pass:

describe("message body",
         function () {
             it("unsigned message",
                function () {
                    let message_objects=read_json_file("example1.json").flat(Infinity);
                    let msg = message_objects.filter((m) => message.match(m,{ "From": "Aron Griffis <agriffis@n01se.net>"}))[0];
                    expect(msg).not.toEqual(null);
                    expect(message.body(msg)).toEqual(`Just subscribed, I'd like to catch up on the previous postings,
but the archive link seems to be bogus?

Thanks,
Aron

`);
                });
             it("signed message",
                function () {
                    let message_objects=read_json_file("example2.json").flat(Infinity);
                    let msg = message_objects.filter((m) => message.match(m,{"From": "md@Linux.IT (Marco d'Itri)"}))[0];

                    expect(msg).not.toEqual(null);
                    expect(message.body(msg)).toEqual(`On Sep 09, Sean Whitton <spwhitton@spwhitton.name> wrote:

> 1. Is the 'should not' for the /etc/default practice too strong?  I
No, because it cannot be supported in a sane way by systemd units.
It should even be "must not".

-- 
ciao,
Marco
`);
                });
               
         });

Output messages as strings.

Like Java, JavaScript objects have a toString method that can be overridden to give a more useful output. We will talk about classes and inheritence in the lab, but for now we just write a simple function and export it as message.string, so that at least the following tests pass. Note that you need to match the given output order of headers, and add a blank line between the body and the headers (but only if the body is actually present).

let fullHeaderMsg ={"headers": {
    "Subject": "[notmuch] archive",
    "From": "Aron Griffis <agriffis@n01se.net>",
    "To": "notmuch <notmuch@notmuchmail.org>",
    "Date": "Tue, 17 Nov 2009 18:21:38 -0500"
}};

describe("toString",
    function () {
        it("works with no body",
            function () {
                expect(message.string(testMsg)).toEqual(`Date: now
Subject: lunch
`);
            });

        it("full set of headers",
            function() {
                expect(message.string(fullHeaderMsg)).toEqual(`From: Aron Griffis <agriffis@n01se.net>
Date: Tue, 17 Nov 2009 18:21:38 -0500
Subject: [notmuch] archive
To: notmuch <notmuch@notmuchmail.org>
`);
            });
    });

describe("toString real data",
    function () {
        it("unsigned message",
            function () {
                let message_objects=read_json_file("example1.json").flat(Infinity);
                let msg = message_objects.filter((m) => message.match(m,{ "From": "Aron Griffis <agriffis@n01se.net>"}))[0];
                expect(msg).not.toEqual(null);
                expect(message.string(msg)).toEqual(`From: Aron Griffis <agriffis@n01se.net>
Date: Tue, 17 Nov 2009 18:21:38 -0500
Subject: [notmuch] archive
To: notmuch <notmuch@notmuchmail.org>

Just subscribed, I'd like to catch up on the previous postings,
but the archive link seems to be bogus?

Thanks,
Aron

`);
            });
             
        it("signed message",
            function () {
                let message_objects=read_json_file("example2.json").flat(Infinity);
                let msg = message_objects.filter((m) => message.match(m,{"From": "md@Linux.IT (Marco d'Itri)"}))[0];

                expect(msg).not.toEqual(null);
                expect(message.string(msg)).toEqual(`From: md@Linux.IT (Marco d'Itri)
Date: Sun, 10 Sep 2017 09:48:44 +0200
Subject: Bug#601455: Steps towards a patch to document disabling a daemon upon installation
To: debian-policy@lists.debian.org

On Sep 09, Sean Whitton <spwhitton@spwhitton.name> wrote:

> 1. Is the 'should not' for the /etc/default practice too strong?  I
No, because it cannot be supported in a sane way by systemd units.
It should even be "must not".

-- 
ciao,
Marco
`);});
    });