Bug 1251484 - Make it configurable whether to prefix subjects of emails with event invitations. r=MakeMyDay
authorFredrik de Vibe <fdv@ifi.uio.no>
Thu, 07 Apr 2016 00:26:58 +0200
changeset 24798 a0877b96c8c96620b51670dfa0b762d60e92da08
parent 24797 d7463651287af48e0679d18e1f2ec194a04303fa
child 24799 2476dbdd1cfc947692f9b47c6f8e42715b941eae
push id1657
push userclokep@gmail.com
push dateMon, 06 Jun 2016 19:50:21 +0000
treeherdercomm-beta@9fac989284b5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMakeMyDay
bugs1251484
Bug 1251484 - Make it configurable whether to prefix subjects of emails with event invitations. r=MakeMyDay
calendar/itip/calItipEmailTransport.js
calendar/lightning/content/lightning.js
calendar/test/unit/test_imip.js
calendar/test/unit/xpcshell-shared.ini
--- a/calendar/itip/calItipEmailTransport.js
+++ b/calendar/itip/calItipEmailTransport.js
@@ -46,103 +46,143 @@ calItipEmailTransport.prototype = {
     mSenderAddress: null,
     get senderAddress() {
         return this.mSenderAddress;
     },
     set senderAddress(aValue) {
         return (this.mSenderAddress = aValue);
     },
 
-
     sendItems: function cietSI(aCount, aRecipients, aItipItem) {
         if (this.mHasXpcomMail) {
             cal.LOG("sendItems: Sending Email...");
-
-            let item = aItipItem.getItemList({})[0];
-
-            // Get ourselves some default text - when we handle organizer properly
-            // We'll need a way to configure the Common Name attribute and we should
-            // use it here rather than the email address
-
-            let summary = (item.getProperty("SUMMARY") || "");
-            let aSubject = "";
-            let aBody = "";
-            switch (aItipItem.responseMethod) {
-                case 'REQUEST':
-                    let seq = item.getProperty("SEQUENCE");
-                    let subjectKey = (seq && seq > 0 ? "itipRequestUpdatedSubject" : "itipRequestSubject");
-                    aSubject = cal.calGetString("lightning",
-                                                subjectKey,
-                                                [summary],
-                                                "lightning");
-                    aBody = cal.calGetString("lightning",
-                                             "itipRequestBody",
-                                             [item.organizer ? item.organizer.toString() : "", summary],
-                                             "lightning");
-                    break;
-                case 'CANCEL':
-                    aSubject = cal.calGetString("lightning",
-                                                "itipCancelSubject",
-                                                [summary],
-                                                "lightning");
-                    aBody = cal.calGetString("lightning",
-                                             "itipCancelBody",
-                                             [item.organizer ? item.organizer.toString() : "", summary],
-                                             "lightning");
-                    break;
-                case 'REPLY': {
-                    // Get my participation status
-                    let att = cal.getInvitedAttendee(item, aItipItem.targetCalendar);
-                    if (!att && aItipItem.identity) {
-                        att = item.getAttendeeById("mailto:" + aItipItem.identity);
-                    }
-                    if (!att) { // should not happen anymore
-                        return false;
-                    }
-
-                    // work around BUG 351589, the below just removes RSVP:
-                    aItipItem.setAttendeeStatus(att.id, att.participationStatus);
-                    let myPartStat = att.participationStatus;
-                    let name = att.toString();
-
-                    // Generate proper body from my participation status
-                    let subjectKey, bodyKey;
-                    switch (myPartStat) {
-                        case "ACCEPTED":
-                            subjectKey = "itipReplySubjectAccept";
-                            bodyKey = "itipReplyBodyAccept";
-                            break;
-                        case "TENTATIVE":
-                            subjectKey = "itipReplySubjectTentative";
-                            bodyKey = "itipReplyBodyAccept";
-                            break;
-                        case "DECLINED":
-                            subjectKey = "itipReplySubjectDecline";
-                            bodyKey = "itipReplyBodyDecline";
-                            break;
-                        default:
-                            subjectKey = "itipReplySubject";
-                            bodyKey = "itipReplyBodyAccept";
-                            break;
-                    }
-                    aSubject = cal.calGetString("lightning", subjectKey, [summary], "lightning");
-                    aBody = cal.calGetString("lightning", bodyKey, [name], "lightning");
-
-                    break;
-                }
-            }
-
-            return this._sendXpcomMail(aRecipients, aSubject, aBody, aItipItem);
+            let items = this._prepareItems(aItipItem);
+            return (items === false)
+                ? false
+                : this._sendXpcomMail(
+                    aRecipients,
+                    items.subject,
+                    items.body,
+                    aItipItem
+                );
         } else {
             // Sunbird case: Call user's default mailer on system.
             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
         }
         return false;
     },
 
+    _prepareItems: function (aItipItem) {
+        let item = aItipItem.getItemList({})[0];
+
+        // Get ourselves some default text - when we handle organizer properly
+        // We'll need a way to configure the Common Name attribute and we should
+        // use it here rather than the email address
+
+        let summary = (item.getProperty("SUMMARY") || "");
+        let subject = "";
+        let body = "";
+        switch (aItipItem.responseMethod) {
+            case "REQUEST":
+                let usePrefixes = Preferences.get(
+                    "calendar.itip.useInvitationSubjectPrefixes",
+                    true
+                );
+                if (!usePrefixes) {
+                    subject = summary;
+                } else {
+                    let seq = item.getProperty("SEQUENCE");
+                    let subjectKey = (seq && seq > 0)
+                        ? "itipRequestUpdatedSubject"
+                        : "itipRequestSubject";
+                    subject = cal.calGetString(
+                        "lightning",
+                        subjectKey,
+                        [summary],
+                        "lightning"
+                    );
+                }
+                body = cal.calGetString(
+                    "lightning",
+                    "itipRequestBody",
+                    [item.organizer ? item.organizer.toString() : "", summary],
+                    "lightning"
+                );
+                break;
+            case "CANCEL":
+                subject = cal.calGetString(
+                    "lightning",
+                    "itipCancelSubject",
+                    [summary],
+                    "lightning"
+                );
+                body = cal.calGetString(
+                    "lightning",
+                    "itipCancelBody",
+                    [item.organizer ? item.organizer.toString() : "", summary],
+                    "lightning"
+                );
+                break;
+            case "REPLY": {
+                // Get my participation status
+                let att = cal.getInvitedAttendee(item, aItipItem.targetCalendar);
+                if (!att && aItipItem.identity) {
+                    att = item.getAttendeeById("mailto:" + aItipItem.identity);
+                }
+                if (!att) { // should not happen anymore
+                    return false;
+                }
+
+                // work around BUG 351589, the below just removes RSVP:
+                aItipItem.setAttendeeStatus(att.id, att.participationStatus);
+                let myPartStat = att.participationStatus;
+                let name = att.toString();
+
+                // Generate proper body from my participation status
+                let subjectKey, bodyKey;
+                switch (myPartStat) {
+                    case "ACCEPTED":
+                        subjectKey = "itipReplySubjectAccept";
+                        bodyKey = "itipReplyBodyAccept";
+                        break;
+                    case "TENTATIVE":
+                        subjectKey = "itipReplySubjectTentative";
+                        bodyKey = "itipReplyBodyAccept";
+                        break;
+                    case "DECLINED":
+                        subjectKey = "itipReplySubjectDecline";
+                        bodyKey = "itipReplyBodyDecline";
+                        break;
+                    default:
+                        subjectKey = "itipReplySubject";
+                        bodyKey = "itipReplyBodyAccept";
+                        break;
+                }
+                subject = cal.calGetString(
+                    "lightning",
+                    subjectKey,
+                    [summary],
+                    "lightning"
+                );
+                body = cal.calGetString(
+                    "lightning",
+                    bodyKey,
+                    [name],
+                    "lightning"
+                );
+                break;
+            }
+        }
+
+        return {
+            subject: subject,
+            body: body
+        };
+    },
+
     _initEmailTransport: function cietIES() {
         this.mHasXpcomMail = true;
 
         try {
             this.mDefaultSmtpServer = MailServices.smtp.defaultServer;
             this.mDefaultAccount = MailServices.accounts.defaultAccount;
             this.mDefaultIdentity = this.mDefaultAccount.defaultIdentity;
 
--- a/calendar/lightning/content/lightning.js
+++ b/calendar/lightning/content/lightning.js
@@ -73,16 +73,19 @@ pref("calendar.itip.notify-replies", fal
 pref("calendar.itip.updateInvitationForNewAttendeesOnly", false);
 
 //whether changes in email invitation updates should be displayed
 pref("calendar.itip.displayInvitationChanges", true);
 
 //whether for delegated invitations a delegatee's replies will be send also to delegator(s)
 pref("calendar.itip.notifyDelegatorOnReply", true);
 
+// whether to prefix the subject field for email invitation invites or updates.
+pref("calendar.itip.useInvitationSubjectPrefixes", true);
+
 // whether CalDAV (experimental) scheduling is enabled or not.
 pref("calendar.caldav.sched.enabled", false);
 
 // 0=Sunday, 1=Monday, 2=Tuesday, etc.  One day we might want to move this to
 // a locale specific file.
 pref("calendar.week.start", 0);
 pref("calendar.weeks.inview", 4);
 pref("calendar.previousweeks.inview", 0);
new file mode 100644
--- /dev/null
+++ b/calendar/test/unit/test_imip.js
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Components.utils.import("resource://gre/modules/Preferences.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+var calItipEmailTransport = {};
+Services.scriptloader.loadSubScript(
+    "resource://calendar/components/calItipEmailTransport.js",
+    calItipEmailTransport);
+
+function run_test() {
+    run_next_test();
+}
+
+function itipItemForTest(title, seq) {
+    let itipItem = Components
+            .classes["@mozilla.org/calendar/itip-item;1"]
+            .createInstance(Components.interfaces.calIItipItem);
+    itipItem.init([
+        "BEGIN:VCALENDAR",
+        "METHOD:REQUEST",
+        "BEGIN:VEVENT",
+        "SUMMARY:" + title,
+        "SEQUENCE:" + (seq || 0),
+        "END:VEVENT",
+        "END:VCALENDAR"
+    ].join("\r\n"));
+    return itipItem;
+}
+
+let transport = new calItipEmailTransport.calItipEmailTransport();
+
+add_task(function test_title_in_subject() {
+    Preferences.set("calendar.itip.useInvitationSubjectPrefixes", false);
+    let items = transport._prepareItems(itipItemForTest("foo"));
+    equal(items.subject, "foo");
+});
+
+add_task(function test_title_in_summary() {
+    Preferences.set("calendar.itip.useInvitationSubjectPrefixes", true);
+    let items = transport._prepareItems(itipItemForTest("bar"));
+    equal(items.subject, "Event Invitation: bar");
+});
+
+add_task(function test_updated_title_in_subject() {
+    Preferences.set("calendar.itip.useInvitationSubjectPrefixes", false);
+    let items = transport._prepareItems(itipItemForTest("foo", 2));
+    equal(items.subject, "foo");
+});
+
+add_task(function test_updated_title_in_summary() {
+    Preferences.set("calendar.itip.useInvitationSubjectPrefixes", true);
+    let items = transport._prepareItems(itipItemForTest("bar", 2));
+    equal(items.subject, "Updated Event Invitation: bar");
+});
--- a/calendar/test/unit/xpcshell-shared.ini
+++ b/calendar/test/unit/xpcshell-shared.ini
@@ -27,16 +27,17 @@
 [test_freebusy.js]
 [test_freebusy_service.js]
 [test_gdata_provider.js]
 requesttimeoutfactor = 2
 [test_hashedarray.js]
 [test_ics.js]
 [test_ics_parser.js]
 [test_ics_service.js]
+[test_imip.js]
 [test_items.js]
 [test_ltninvitationutils.js]
 [test_providers.js]
 [test_recur.js]
 [test_relation.js]
 [test_rfc3339_parser.js]
 [test_search_service.js]
 [test_startup_service.js]