def test_004_flagsclear(self):
        flagsclear = {
            "event": "FlagsClear",
            "flagNames": "\Seen",
            "messages": 3,
            "modseq": 47,
            "pid": 489,
            "service": "imap",
            "timestamp": "2014-10-20T13:03:31.348+02:00",
            "uidnext": 7,
            "uidset": "4",
            "uri": "imap://[email protected]@kolab.example.org/INBOX;UIDVALIDITY=1411487701",
            "user": "******",
            "vnd.cmu.midset": [ "<*****@*****.**>" ],
            "vnd.cmu.sessionId": "kolab.example.org-489-1413803011-1",
            "vnd.cmu.unseenMessages": 1
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(flagsclear))

        # query by message-ID
        events = self.query_log([('message_id','=','<*****@*****.**>')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertEqual(event['uidset'], '4')
        self.assertEqual(event['flag_names'], '\Seen')
        self.assertEqual(event['unseen_messages'], 1)
        self.assertTrue(event.has_key('user_id'))
        self.assertTrue(event.has_key('folder_id'))
    def test_003_messageread(self):
        messageread = {
            "event": "MessageRead",
            "messages": 3,
            "modseq": 64,
            "pid": 802,
            "service": "imap",
            "timestamp": "2014-10-20T13:04:09.077+02:00",
            "uidnext": 7,
            "uidset": "4",
            "uri": "imap://[email protected]@kolab.example.org/INBOX;UIDVALIDITY=1411487701",
            "user": "******",
            "vnd.cmu.midset": [ "<*****@*****.**>" ],
            "vnd.cmu.sessionId": "kolab.example.org-802-1413803049-1",
            "vnd.cmu.unseenMessages": 0
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(messageread))

        # query by message-ID
        events = self.query_log([('message_id','=','<*****@*****.**>')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertEqual(event['uidset'], '4')
        self.assertTrue(event.has_key('user_id'))
        self.assertTrue(event.has_key('folder_id'))
    def test_002_messageappend(self):
        messageappend = {
            "event": "MessageAppend",
            "flagNames": "\seen",
            "messageSize": 555,
            "messages": 6,
            "modseq": 12,
            "pid": 2222,
            "service": "imap",
            "timestamp": "2014-10-20T13:33:27.062+02:00",
            "uidnext": 9,
            "uidset": "8",
            "uri": "imap://[email protected]@kolab.example.org/Sent;UIDVALIDITY=1411487701/;UID=8",
            "user": "******",
            "vnd.cmu.envelope": "(\"Mon, 20 Oct 2014 13:33:26 +0200\" \"MessageNew event test\" ((\"=?UTF-8?Q?Br=C3=BCederli=2C_Thomas?=\" NIL \"john.doe\" \"example.org\")) ((\"=?UTF-8?Q?Br=C3=BCederli=2C_Thomas?=\" NIL \"john.doe\" \"example.org\")) ((\"=?UTF-8?Q?Br=C3=BCederli=2C_Thomas?=\" NIL \"john.doe\" \"example.org\")) ((\"Doe, John\" NIL \"john.doe\" \"example.org\")) NIL NIL NIL \"<*****@*****.**>\")",
            "vnd.cmu.midset": [ "<*****@*****.**>" ],
            "vnd.cmu.sessionId": "kolab.example.org-2222-1413804806-1",
            "vnd.cmu.unseenMessages": 0,
            "folder_id": "76b8cd8f85bb435d17fe28d576db64a7",
            "folder_uniqueid": "f356a1a9-f897-454f-9ada-5646fe4c4117",
            "messageHeaders": {
                "8": {
                    "Content-Transfer-Encoding": "7bit",
                    "Content-Type": "text/plain",
                    "Date": "2014-10-20T11:31:11Z",
                    "From": [ "Br\u00fcederli, Thomas <*****@*****.**>" ],
                    "MIME-Version": "1.0",
                    "Message-ID": "<*****@*****.**>",
                    "Subject": "MessageNew event test",
                    "To": [ "Doe, John <*****@*****.**>" ],
                    "User-Agent": "Kolab 3.1/Roundcube 1.1-git",
                    "X-Sender": "*****@*****.**"
                }
            },
            "messageContent": {
                "8": "MIME-Version: 1.0\r\nContent-Type: text/plain; charset=US-ASCII;\r\n format=flowed\r\nContent-Transfer-Encoding: 7bit\r\nDate: Mon, 20 Oct 2014 13:31:11 +0200\r\nFrom: =?UTF-8?Q?Br=C3=BCederli=2C_Thomas?= <*****@*****.**>\r\nTo: \"Doe, John\" <*****@*****.**>\r\nSubject: MessageNew event test\r\nMessage-ID: <*****@*****.**>\r\nX-Sender: [email protected]\r\nUser-Agent: Kolab 3.1/Roundcube 1.1-git\r\n\r\nThis message should trigger the MessageNew event for john.doe...\r\n...and MessageAppend to /Sent for the sender."
            }
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(messageappend))

        events = self.query_log([('event','=','MessageAppend')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertTrue(event.has_key('user_id'))
        self.assertIsInstance(event['headers'], dict)
        self.assertEqual(len(event['headers']['To']), 1)
        self.assertEqual(event['headers']['Content-Type'], 'text/plain')
        self.assertTrue(event['headers']['Message-ID'] in event['message_id'])
    def test_001_changelog(self):
        # we assume "messageHeaders" and "messageContent" payload already being collected
        messageappend = {
            "event": "MessageAppend",
            "messageSize": 2932,
            "messages": 2,
            "modseq": 107,
            "pid": 1248,
            "service": "imap",
            "timestamp": "2014-10-20T13:10:59.516+02:00",
            "uidnext": 38,
            "uidset": "37",
            "uri": "imap://[email protected]@kolab.example.org/Calendar;UIDVALIDITY=1411487702/;UID=37",
            "user": "******",
            "vnd.cmu.envelope": "(\"Mon, 20 Oct 2014 13:10:59 +0200\" \"253E800C973E9FB99D174669001DB19B-FCBB6C4091F28CA0\" ((NIL NIL \"john.doe\" \"example.org\")) ((NIL NIL \"john.doe\" \"example.org\")) ((NIL NIL \"john.doe\" \"example.org\")) ((NIL NIL \"john.doe\" \"example.org\")) NIL NIL NIL NIL)",
            "vnd.cmu.midset": [ "NIL" ],
            "vnd.cmu.sessionId": "kolab.example.org-1248-1413803459-1",
            "vnd.cmu.unseenMessages": 2,
            "messageHeaders": {
                "37": {
                    "Content-Type": "multipart/mixed",
                    "Date": "2014-10-20T11:23:40Z",
                    "From": [ " <*****@*****.**>" ],
                    "MIME-Version": "1.0",
                    "Subject": "253E800C973E9FB99D174669001DB19B-FCBB6C4091F28CA0",
                    "To": [ " <*****@*****.**>" ],
                    "User-Agent": "Kolab 3.1/Roundcube 1.1-git",
                    "X-Kolab-Mime-Version": "3.0",
                    "X-Kolab-Type": "application/x-vnd.kolab.event"
                }
            },
            "messageContent": {
                "37": "MIME-Version: 1.0\r\nContent-Type: multipart/mixed;\r\n boundary=\"=_46bc539ab7a6c0a8bd4d2ddbf553df00\"\r\nFrom: [email protected]\r\nTo: [email protected]\r\nDate: Mon, 20 Oct 2014 13:23:40 +0200\r\nX-Kolab-Type: application/x-vnd.kolab.event\r\nX-Kolab-Mime-Version: 3.0\r\nSubject: 253E800C973E9FB99D174669001DB19B-FCBB6C4091F28CA0\r\nUser-Agent: Kolab 3.1/Roundcube 1.1-git\r\n\r\n--=_46bc539ab7a6c0a8bd4d2ddbf553df00\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/plain; charset=ISO-8859-1\r\n\r\nThis is a Kolab Groupware object....\r\n\r\n--=_46bc539ab7a6c0a8bd4d2ddbf553df00\r\nContent-Transfer-Encoding: 8bit\r\nContent-Type: application/calendar+xml; charset=UTF-8;\r\n name=kolab.xml\r\nContent-Disposition: attachment;\r\n filename=kolab.xml;\r\n size=1954\r\n\r\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\r\n<icalendar xmlns=\"urn:ietf:params:xml:ns:icalendar-2.0\">\r\n\r\n  <vcalendar>\r\n    <properties>\r\n      <prodid>\r\n        <text>Roundcube-libkolab-1.1 Libkolabxml-1.1</text>\r\n      </prodid>\r\n      <version>\r\n        <text>2.0</text>\r\n      </version>\r\n      <x-kolab-version>\r\n        <text>3.1.0</text>\r\n      </x-kolab-version>\r\n    </properties>\r\n    <components>\r\n      <vevent>\r\n        <properties>\r\n          <uid>\r\n            <text>253E800C973E9FB99D174669001DB19B-FCBB6C4091F28CA0</text>\r\n          </uid>\r\n          <created>\r\n            <date-time>2014-09-23T23:31:23Z</date-time>\r\n          </created>\r\n          <dtstamp>\r\n            <date-time>2014-10-20T11:23:40Z</date-time>\r\n          </dtstamp>\r\n          <sequence>\r\n            <integer>28</integer>\r\n          </sequence>\r\n          <class>\r\n            <text>PUBLIC</text>\r\n          </class>\r\n          <dtstart>\r\n            <parameters>\r\n              <tzid>\r\n                <text>/kolab.org/Europe/Berlin</text>\r\n              </tzid>\r\n            </parameters>\r\n            <date-time>2014-10-20T14:00:00</date-time>\r\n          </dtstart>\r\n          <dtend>\r\n            <parameters>\r\n              <tzid>\r\n                <text>/kolab.org/Europe/Berlin</text>\r\n              </tzid>\r\n            </parameters>\r\n            <date-time>2014-10-20T16:00:00</date-time>\r\n          </dtend>\r\n          <summary>\r\n            <text>Today</text>\r\n          </summary>\r\n          <description>\r\n            <text>(new revision)</text>\r\n          </description>\r\n          <organizer>\r\n            <parameters>\r\n              <cn>\r\n                <text>Br\u00fcederli, Thomas</text>\r\n              </cn>\r\n            </parameters>\r\n            <cal-address>mailto:%3Cthomas.bruederli%40example.org%3E</cal-address>\r\n          </organizer>\r\n        </properties>\r\n      </vevent>\r\n    </components>\r\n  </vcalendar>\r\n\r\n</icalendar>\r\n\r\n--=_46bc539ab7a6c0a8bd4d2ddbf553df00--\r\n"
            }
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(messageappend))

        # query by subject (i.e. object UUID)
        events = self.query_log([('headers.Subject','=','253E800C973E9FB99D174669001DB19B-FCBB6C4091F28CA0')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertIsInstance(event['headers'], dict)
        self.assertEqual(event['headers']['X-Kolab-Mime-Version'], '3.0')
        self.assertEqual(event['headers']['X-Kolab-Type'], 'application/x-vnd.kolab.event')

        self.assertTrue(event.has_key('user_id'))
        self.assertTrue(event.has_key('revision'))
    def test_005_messagetrash(self):
        messagetrash = {
            "event": "MessageTrash",
            "messages": 2,
            "modseq": 104,
            "pid": 1248,
            "service": "imap",
            "timestamp": "2014-10-20T13:10:59.546+02:00",
            "uidnext": 38,
            "uidset": "36",
            "uri": "imap://[email protected]@kolab.example.org/Calendar;UIDVALIDITY=1411487702",
            "user": "******",
            "vnd.cmu.midset": [ "NIL" ],
            "vnd.cmu.sessionId": "kolab.example.org-1248-1413803459-1",
            "vnd.cmu.unseenMessages": 2,
            "messageHeaders": {
                "36": {
                    "Content-Type": "multipart/mixed",
                    "Date": "2014-10-20T11:23:40Z",
                    "From": [ " <*****@*****.**>" ],
                    "MIME-Version": "1.0",
                    "Subject": "253E800C973E9FB99D174669001DB19B-FCBB6C4091F28CA0",
                    "To": [ " <*****@*****.**>" ],
                    "User-Agent": "Kolab 3.1/Roundcube 1.1-git",
                    "X-Kolab-Mime-Version": "3.0",
                    "X-Kolab-Type": "application/x-vnd.kolab.event"
                }
            }
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(messagetrash))

        events = self.query_log([('event','=','MessageTrash')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertTrue(event['headers']['Subject'] in messagetrash['messageHeaders']['36']['Subject'])
        self.assertEqual(len(event['message_id']), 0)
    def test_mailboxcreate(self):
        dealer = BonnieDealer()

        notification = {
            'event': 'MailboxCreate',
            'user': '******',
            'uri': 'imap://[email protected]@kolab.example.org/Calendar;UIDVALIDITY=12345'
        }

        dealer.run(json.dumps(notification))

        events = self.query_log([('event','=','MailboxCreate')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertTrue(event.has_key('folder_id'))
        self.assertTrue(event.has_key('folder_uniqueid'))
        self.assertTrue(event.has_key('user_id'))

        # check objects/folder entry
        folder = self.storage_get(event['folder_id'], index='objects', doctype='folder')

        self.assertIsInstance(folder, dict)
        self.assertEqual(folder['uniqueid'], event['folder_uniqueid'])
        self.assertEqual(folder['name'], 'Calendar')
        self.assertEqual(folder['type'], 'event')
        self.assertEqual(folder['owner'], '*****@*****.**')

        self.assertIsInstance(folder['metadata'], dict)
        self.assertIsInstance(folder['acl'], dict)
        self.assertTrue(folder['acl'].has_key(event['user_id']))
        self.assertTrue(folder['acl'][event['user_id']].startswith('lrswi'))

        # check objects/user entry
        user = self.storage_get(event['user_id'], index='objects', doctype='user')

        self.assertIsInstance(user, dict)
        self.assertEqual(user['user'], notification['user'])
        self.assertEqual(user['cn'], 'John Doe')
    def test_run(self):
        dealer = BonnieDealer()
        dealer.run(json.dumps({ 'event':'Login', 'user':'******' }))
        self.assertIn('Login', BonnieDealerOutput.output_calls)

        # don't trigger blacklisted events
        BonnieDealerOutput.output_calls = []
        dealer.run(json.dumps({ 'event':'Login', 'user':'******' }))
        self.assertEqual(len(BonnieDealerOutput.output_calls), 0)

        dealer.run(json.dumps({ 'event':'MessageAppend', 'user':'******' }))
        self.assertEqual(len(BonnieDealerOutput.output_calls), 1)
        self.assertIn('MessageAppend', BonnieDealerOutput.output_calls)
    def test_001_login(self):
        login = {
            'event': 'Login',
            'user': '******',
            'vnd.cmu.sessionId': 'kolab-sess-test-12345',
            'clientIP': '::1',
            'serverDomain': 'example.org',
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(login))

        events = self.query_log([('event','=','Login')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertTrue(event.has_key('user_id'))
        self.assertTrue(event['session_id'], login['vnd.cmu.sessionId'])
        self.assertEqual(event['@version'], bonnie.API_VERSION)

        del dealer
        time.sleep(1)

        logout = {
            'event': 'Logout',
            'user': '******',
            'vnd.cmu.sessionId': 'kolab-sess-test-12345',
            'clientIP': '::1'
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(logout))

        events = self.query_log([('event','=','Login'), ('logout_time','=','*')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertTrue(event.has_key('logout_time'))
        self.assertTrue(event.has_key('duration'))

        # check objects/users entry
        user = self.storage_get(event['user_id'], index='objects', doctype='user')

        self.assertIsInstance(user, dict)
        self.assertEqual(user['user'], login['user'])
        self.assertEqual(user['cn'], 'John Doe')
    def test_001_messagenew(self):
        # we assume "messageHeaders" and "messageContent" payload already being collected
        messagenew = {
            "event": "MessageNew",
            "messageSize": 976,
            "messages": 6,
            "modseq": 20,
            "pid": 2340,
            "service": "lmtpunix",
            "timestamp": "2014-10-20T13:34:14.966+02:00",
            "uidnext": 7,
            "uidset": "6",
            "uri": "imap://[email protected]@kolab.example.org/INBOX;UIDVALIDITY=1411487714/;UID=6",
            "user": "******",
            "vnd.cmu.midset": [ "<*****@*****.**>" ],
            "vnd.cmu.sessionId": "kolab.example.org-2340-1413804854-1",
            "vnd.cmu.unseenMessages": 3,
            "messageHeaders": {
                "6": {
                    "Content-Transfer-Encoding": "7bit",
                    "Content-Type": "text/plain",
                    "Date": "2014-10-20T11:32:41Z",
                    "From": [ "Br\u00fcederli, Thomas <*****@*****.**>" ],
                    "MIME-Version": "1.0",
                    "Message-ID": "<*****@*****.**>",
                    "Received": "from kolab.example.org ([unix socket])\r\n\t by kolab.example.org (Cyrus git2.5+0-Kolab-2.5-67.el6.kolab_3.4) with LMTPA;\r\n\t Mon, 20 Oct 2014 13:34:14 +0200",
                    "Return-Path": "<*****@*****.**>",
                    "Subject": "MessageNew event test",
                    "To": [ "Doe, John <*****@*****.**>" ],
                    "X-Sender": "*****@*****.**",
                    "X-Sieve": "CMU Sieve 2.4",
                    "X-Spam-Flag": "NO",
                    "X-Spam-Level": "",
                    "X-Spam-Score": "-0.002",
                    "X-Spam-Status": "No, score=-0.002 tagged_above=-10 required=6.2\r\n\ttests=[NO_RECEIVED=-0.001, NO_RELAYS=-0.001] autolearn=ham",
                    "X-Virus-Scanned": "amavisd-new at example.org"
                }
            },
            "messageContent": {
                "6": "Return-Path: <*****@*****.**>\r\nReceived: from kolab.example.org ([unix socket])\r\n\t by kolab.example.org (Cyrus git2.5+0-Kolab-2.5-67.el6.kolab_3.4) with LMTPA;\r\n\t Mon, 20 Oct 2014 13:34:14 +0200\r\nX-Sieve: CMU Sieve 2.4\r\nX-Virus-Scanned: amavisd-new at example.org\r\nX-Spam-Flag: NO\r\nX-Spam-Score: -0.002\r\nX-Spam-Level: \r\nX-Spam-Status: No, score=-0.002 tagged_above=-10 required=6.2\r\n\ttests=[NO_RECEIVED=-0.001, NO_RELAYS=-0.001] autolearn=ham\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=US-ASCII;\r\n format=flowed\r\nContent-Transfer-Encoding: 7bit\r\nDate: Mon, 20 Oct 2014 13:32:41 +0200\r\nFrom: =?UTF-8?Q?Br=C3=BCederli=2C_Thomas?= <*****@*****.**>\r\nTo: \"Doe, John\" <*****@*****.**>\r\nSubject: MessageNew event test\r\nMessage-ID: <*****@*****.**>\r\nX-Sender: [email protected]\r\n\r\nThis message should trigger the MessageNew event for john.doe...\r\n...and MessageAppend to /Sent for the sender.\r\n"
            }
        }

        dealer = BonnieDealer()
        dealer.run(json.dumps(messagenew))

        events = self.query_log([('event','=','MessageNew')])
        self.assertEqual(len(events), 1)

        event = events[0]
        self.assertEqual(event['uidset'], '6')
        self.assertEqual(event['service'], 'lmtpunix')
        self.assertEqual(event['session_id'], messagenew['vnd.cmu.sessionId'])
        self.assertEqual(event['@timestamp'], '2014-10-20T11:34:14.966000Z')
        self.assertEqual(len(event['message_id']), 1)

        self.assertIsInstance(event['headers'], dict)
        self.assertTrue(event['headers']['Message-ID'] in event['message_id'])
        self.assertTrue(event['headers']['Subject'] in messagenew['messageHeaders']['6']['Subject'])

        # check if message payload is parsable
        message = message_from_string(event['message'].encode('utf8','replace'))
        self.assertEqual(message['Subject'], event['headers']['Subject'])

        # check objects/folder entry
        self.assertTrue(event.has_key('folder_id'))
        folder = self.storage_get(event['folder_id'], index='objects', doctype='folder')

        self.assertIsInstance(folder, dict)
        self.assertEqual(folder['uniqueid'], event['folder_uniqueid'])
        self.assertEqual(folder['name'], 'INBOX')
        self.assertEqual(folder['owner'], '*****@*****.**')

        # check objects/user entry
        self.assertTrue(event.has_key('user_id'))
        user = self.storage_get(event['user_id'], index='objects', doctype='user')

        self.assertIsInstance(user, dict)
        self.assertEqual(user['user'], messagenew['user'])
Exemple #10
0
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import json
import os
import sys

from bonnie.dealer import BonnieDealer

if __name__ == "__main__":
    notification = sys.stdin.read().strip()

    dealer = BonnieDealer()
    dealer.run(notification)

#    newpid = os.fork()
#
#    if newpid == 0:
#        dealer = BonnieDealer()
#        dealer.run(notification)