Bug 1439868 - Move email/scheduling related functions into calEmailUtils.jsm and calItipUtils.jsm - automatic changes email. r=MakeMyDay
authorPhilipp Kewisch <mozilla@kewis.ch>
Wed, 21 Feb 2018 07:35:35 +0100
changeset 31374 c496bccd43b0c2b33e64a8cde2323ccb2a9fbc89
parent 31373 6324de6a59c5eb3155902084341513013dce9ca0
child 31375 8c53d1a42b1da035c3bcfe5addd9d1db82fb5e7c
push id383
push userclokep@gmail.com
push dateMon, 07 May 2018 21:52:48 +0000
reviewersMakeMyDay
bugs1439868
Bug 1439868 - Move email/scheduling related functions into calEmailUtils.jsm and calItipUtils.jsm - automatic changes email. r=MakeMyDay MozReview-Commit-ID: If8I5zSBlax
calendar/base/content/calendar-dnd-listener.js
calendar/base/content/calendar-task-view.js
calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
calendar/base/content/dialogs/calendar-summary-dialog.js
calendar/base/modules/calItipUtils.jsm
calendar/base/modules/calProviderUtils.jsm
calendar/base/src/calAttendee.js
calendar/base/src/calDefaultACLManager.js
calendar/itip/calItipEmailTransport.js
calendar/lightning/content/lightning-item-iframe.js
calendar/lightning/modules/ltnInvitationUtils.jsm
calendar/test/unit/test_bug1199942.js
calendar/test/unit/test_bug1204255.js
calendar/test/unit/test_calutils.js
calendar/test/unit/test_utils.js
--- a/calendar/base/content/calendar-dnd-listener.js
+++ b/calendar/base/content/calendar-dnd-listener.js
@@ -416,19 +416,19 @@ calMailButtonDNDObserver.prototype = {
      * Gets called in case we're dropping an array of items
      * on the 'mail mode'-button.
      *
      * @param aItems        An array of items to handle.
      */
     onDropItems: function(aItems) {
         if (aItems && aItems.length > 0) {
             let item = aItems[0];
-            let recipients = cal.getRecipientList(item.getAttendees({}));
+            let recipients = cal.email.createRecipientList(item.getAttendees({}));
             let identity = item.calendar.getProperty("imip.identity");
-            cal.sendMailTo(recipients, item.title, item.getProperty("DESCRIPTION"), identity);
+            cal.email.sendTo(recipients, item.title, item.getProperty("DESCRIPTION"), identity);
         }
     },
 
     /**
      * calMailButtonDNDObserver::onDropMessage
      *
      * Gets called in case we're dropping a message
      * on the 'mail mode'-button.
--- a/calendar/base/content/calendar-task-view.js
+++ b/calendar/base/content/calendar-task-view.js
@@ -216,20 +216,20 @@ function taskViewUpdate(aFilter) {
  *
  * XXX We already have a function with this name in the event dialog. Either
  * consolidate or make name more clear.
  */
 function sendMailToOrganizer() {
     let item = document.getElementById("calendar-task-tree").currentTask;
     if (item != null) {
         let organizer = item.organizer;
-        let email = cal.getAttendeeEmail(organizer, true);
+        let email = cal.email.getAttendeeEmail(organizer, true);
         let emailSubject = cal.calGetString("calendar-event-dialog", "emailSubjectReply", [item.title]);
         let identity = item.calendar.getProperty("imip.identity");
-        cal.sendMailTo(email, emailSubject, null, identity);
+        cal.email.sendTo(email, emailSubject, null, identity);
     }
 }
 
 /**
  * Handler function to observe changing of the calendar display deck. Updates
  * the task tree if the task view was selected.
  *
  * TODO Consolidate this function and anything connected, its still from times
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
@@ -228,17 +228,17 @@
             }
 
             if (!aAttendee) {
                 aAttendee = this.createAttendee();
             }
 
             // construct the display string from common name and/or email address.
             let commonName = aAttendee.commonName || "";
-            let inputValue = cal.removeMailTo(aAttendee.id || "");
+            let inputValue = cal.email.removeMailTo(aAttendee.id || "");
             if (commonName.length) {
                 // Make the commonName appear in quotes if it contains a
                 // character that could confuse the header parser
                 if (commonName.search(/[,;<>@]/) != -1) {
                     commonName = '"' + commonName + '"';
                 }
                 inputValue = inputValue.length ? commonName + " <" + inputValue + ">" : commonName;
             }
@@ -390,17 +390,17 @@
                 // is required in case the user entered comma-separated attendees in one field and
                 // then clicked OK without switching to the next line.
                 let parsedInput = MailServices.headerParser.makeFromDisplayAddress(inputField.value);
                 let j = 0;
                 let addAttendee = function(aAddress) {
                     if (j > 0) {
                         attendee = attendee.clone();
                     }
-                    attendee.id = cal.prependMailTo(aAddress.email);
+                    attendee.id = cal.email.prependMailTo(aAddress.email);
                     if (aAddress.name.length > 0) {
                         // we remove any double quotes within CN due to bug 1209399
                         attendee.commonName = aAddress.name.replace(/(?:[\\]"|")/, "");
                     }
                     attendees.push(attendee);
                     j++;
                 };
                 parsedInput.forEach(addAttendee);
@@ -427,17 +427,17 @@
                 // attendee.role = this.getRoleElement(i).getAttribute("role");
                 attendee.participationStatus = this.getStatusElement(i).getAttribute("status");
                 // Organizers do not have a CUTYPE
                 attendee.userType = null;
 
                 // break the list of potentially many attendees back into individual names
                 let parsedInput = MailServices.headerParser.makeFromDisplayAddress(inputField.value);
                 if (parsedInput[0].email > 0) {
-                    attendee.id = cal.prependMailTo(parsedInput[0].email);
+                    attendee.id = cal.email.prependMailTo(parsedInput[0].email);
                 }
                 if (parsedInput[0].name.length > 0) {
                     attendee.commonName = parsedInput[0].name;
                 }
 
                 if (attendee.isOrganizer) {
                     return attendee;
                 }
@@ -622,17 +622,17 @@
         <body><![CDATA[
             let list = [];
             for (let i = 1; i <= this.mMaxAttendees; i++) {
                 // retrieve the string from the appropriate row
                 let input = this.getInputElement(i);
                 if (input && input.value) {
                     // parse the string to break this down to individual names and addresses
                     let parsedInput = MailServices.headerParser.makeFromDisplayAddress(input.value);
-                    let email = cal.prependMailTo(parsedInput[0].email);
+                    let email = cal.email.prependMailTo(parsedInput[0].email);
 
                     let isdirty = false;
                     if (input.hasAttribute("dirty")) {
                         isdirty = input.getAttribute("dirty");
                     }
                     input.removeAttribute("dirty");
                     let entry = {
                         dirty: isdirty,
--- a/calendar/base/content/dialogs/calendar-summary-dialog.js
+++ b/calendar/base/content/dialogs/calendar-summary-dialog.js
@@ -266,17 +266,17 @@ function onCancel() {
  * @param {string}  aPartStat  (optional) a partstat as per RfC5545
  */
 function reply(aResponse, aPartStat=null) {
     if (aPartStat && window.attendee) {
         let aclEntry = window.calendarItem.calendar.aclEntry;
         if (aclEntry) {
             let userAddresses = aclEntry.getUserAddresses({});
             if (userAddresses.length > 0 &&
-                !cal.attendeeMatchesAddresses(window.attendee, userAddresses)) {
+                !cal.email.attendeeMatchesAddresses(window.attendee, userAddresses)) {
                 window.attendee.setProperty("SENT-BY", "mailto:" + userAddresses[0]);
             }
         }
         window.attendee.participationStatus = aPartStat;
         updateToolbar();
     }
     saveAndClose(aResponse);
 }
@@ -436,20 +436,20 @@ function browseDocument() {
 /**
  * Extracts the item's organizer and opens a compose window to send the
  * organizer an email.
  */
 function sendMailToOrganizer() {
     let args = window.arguments[0];
     let item = args.calendarEvent;
     let organizer = item.organizer;
-    let email = cal.getAttendeeEmail(organizer, true);
+    let email = cal.email.getAttendeeEmail(organizer, true);
     let emailSubject = cal.calGetString("calendar-event-dialog", "emailSubjectReply", [item.title]);
     let identity = item.calendar.getProperty("imip.identity");
-    cal.sendMailTo(email, emailSubject, null, identity);
+    cal.email.sendTo(email, emailSubject, null, identity);
 }
 
 /**
  * Opens an attachment
  *
  * @param {AUTF8String}  aAttachmentId   The hashId of the attachment to open
  */
 function openAttachment(aAttachmentId) {
--- a/calendar/base/modules/calItipUtils.jsm
+++ b/calendar/base/modules/calItipUtils.jsm
@@ -789,17 +789,17 @@ var calitip = {
         let invitedAttendee = calitip.isInvitation(aItem) && calitip.getInvitedAttendee(aItem);
         if (invitedAttendee) { // actually is an invitation copy, fix attendee list to send REPLY
             /* We check if the attendee id matches one of of the
              * userAddresses. If they aren't equal, it means that
              * someone is accepting invitations on behalf of an other user. */
             if (aItem.calendar.aclEntry) {
                 let userAddresses = aItem.calendar.aclEntry.getUserAddresses({});
                 if (userAddresses.length > 0 &&
-                    !cal.attendeeMatchesAddresses(invitedAttendee, userAddresses)) {
+                    !cal.email.attendeeMatchesAddresses(invitedAttendee, userAddresses)) {
                     invitedAttendee = invitedAttendee.clone();
                     invitedAttendee.setProperty("SENT-BY", "mailto:" + userAddresses[0]);
                 }
             }
 
             if (aItem.organizer) {
                 let origInvitedAttendee = (aOriginalItem && aOriginalItem.getAttendeeById(invitedAttendee.id));
 
@@ -1212,17 +1212,17 @@ var calitip = {
      */
     getAttendeesBySender: function(aAttendees, aEmailAddress) {
         let attendees = [];
         // we extract the email address to make it work also for a raw header value
         let compFields = Components.classes["@mozilla.org/messengercompose/composefields;1"]
                                    .createInstance(Components.interfaces.nsIMsgCompFields);
         let addresses = compFields.splitRecipients(aEmailAddress, true, {});
         if (addresses.length == 1) {
-            let searchFor = cal.prependMailTo(addresses[0]);
+            let searchFor = cal.email.prependMailTo(addresses[0]);
             aAttendees.forEach(aAttendee => {
                 if ([aAttendee.id, aAttendee.getProperty("SENT-BY")].includes(searchFor)) {
                     attendees.push(aAttendee);
                 }
             });
         } else {
             cal.WARN("No unique email address for lookup!");
         }
--- a/calendar/base/modules/calProviderUtils.jsm
+++ b/calendar/base/modules/calProviderUtils.jsm
@@ -272,17 +272,17 @@ cal.getEmailIdentityOfCalendar = functio
             outAccount.value = foundIdentity ? foundAccount : null;
         }
         return foundIdentity;
     } else {
         if (key.length == 0) { // i.e. "None"
             return null;
         }
         let identity = null;
-        cal.calIterateEmailIdentities((identity_, account) => {
+        cal.email.iterateIdentities((identity_, account) => {
             if (identity_.key == key) {
                 identity = identity_;
                 if (outAccount) {
                     outAccount.value = account;
                 }
             }
             return (identity_.key != key);
         });
--- a/calendar/base/src/calAttendee.js
+++ b/calendar/base/src/calAttendee.js
@@ -176,17 +176,17 @@ calAttendee.prototype = {
     mId: null,
     get id() {
         return this.mId;
     },
     set id(aId) {
         this.modify();
         // RFC 1738 para 2.1 says we should be using lowercase mailto: urls
         // we enforce prepending the mailto prefix for email type ids as migration code bug 1199942
-        return (this.mId = (aId ? cal.prependMailTo(aId) : null));
+        return (this.mId = (aId ? cal.email.prependMailTo(aId) : null));
     },
 
     toString: function() {
         const emailRE = new RegExp("^mailto:", "i");
         let stringRep = (this.id || "").replace(emailRE, "");
         let commonName = this.commonName;
 
         if (commonName) {
--- a/calendar/base/src/calDefaultACLManager.js
+++ b/calendar/base/src/calDefaultACLManager.js
@@ -69,17 +69,17 @@ calDefaultCalendarACLEntry.prototype = {
 
     hasAccessControl: false,
     userIsOwner: true,
     userCanAddItems: true,
     userCanDeleteItems: true,
 
     _getIdentities: function(aCount) {
         let identities = [];
-        cal.calIterateEmailIdentities(id => identities.push(id));
+        cal.email.iterateIdentities(id => identities.push(id));
         aCount.value = identities.length;
         return identities;
     },
 
     getUserAddresses: function(aCount) {
         let identities = this.getUserIdentities(aCount);
         let addresses = identities.map(id => id.email);
         return addresses;
--- a/calendar/itip/calItipEmailTransport.js
+++ b/calendar/itip/calItipEmailTransport.js
@@ -126,17 +126,17 @@ calItipEmailTransport.prototype = {
                     "lightning"
                 );
                 break;
             }
             case "REPLY": {
                 // Get my participation status
                 let att = cal.getInvitedAttendee(item, aItipItem.targetCalendar);
                 if (!att && aItipItem.identity) {
-                    att = item.getAttendeeById(cal.prependMailTo(aItipItem.identity));
+                    att = item.getAttendeeById(cal.email.prependMailTo(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;
@@ -259,17 +259,17 @@ calItipEmailTransport.prototype = {
             }
             // falls through intended
             case Ci.calIItipItem.AUTO: {
                 // don't show log message in case of falling through
                 if (aItipItem.autoResponse == Ci.calIItipItem.AUTO) {
                     cal.LOG("sendXpcomMail: Found AUTO autoResponse type.");
                 }
                 let cbEmail = function(aVal, aInd, aArr) {
-                    let email = cal.getAttendeeEmail(aVal, true);
+                    let email = cal.email.getAttendeeEmail(aVal, true);
                     if (!email.length) {
                         cal.LOG("sendXpcomMail: Invalid recipient for email transport: " + aVal.toString());
                     }
                     return email;
                 };
                 let toMap = aToList.map(cbEmail).filter(value => value.length);
                 if (toMap.length < aToList.length) {
                     // at least one invalid recipient, so we skip sending for this message
@@ -282,30 +282,30 @@ calItipEmailTransport.prototype = {
                 let mailFile = this._createTempImipFile(toList, aSubject, aBody, aItipItem, identity, messageId);
                 if (mailFile) {
                     // compose fields for message: from/to etc need to be specified both here and in the file
                     let composeFields = Cc["@mozilla.org/messengercompose/composefields;1"]
                                         .createInstance(Ci.nsIMsgCompFields);
                     composeFields.characterSet = "UTF-8";
                     composeFields.to = toList;
                     let mailfrom = (identity.fullName.length ? identity.fullName + " <" + identity.email + ">" : identity.email);
-                    composeFields.from = (cal.validateRecipientList(mailfrom) == mailfrom ? mailfrom : identity.email);
+                    composeFields.from = (cal.email.validateRecipientList(mailfrom) == mailfrom ? mailfrom : identity.email);
                     composeFields.replyTo = identity.replyTo;
                     composeFields.organization = identity.organization;
                     composeFields.messageId = messageId;
                     let validRecipients;
                     if (identity.doCc) {
-                        validRecipients = cal.validateRecipientList(identity.doCcList);
+                        validRecipients = cal.email.validateRecipientList(identity.doCcList);
                         if (validRecipients != "") {
                             // eslint-disable-next-line id-length
                             composeFields.cc = validRecipients;
                         }
                     }
                     if (identity.doBcc) {
-                        validRecipients = cal.validateRecipientList(identity.doBccList);
+                        validRecipients = cal.email.validateRecipientList(identity.doBccList);
                         if (validRecipients != "") {
                             composeFields.bcc = validRecipients;
                         }
                     }
 
                     // xxx todo: add send/progress UI, maybe recycle
                     //           "@mozilla.org/messengercompose/composesendlistener;1"
                     //           and/or "chrome://messenger/content/messengercompose/sendProgress.xul"
--- a/calendar/lightning/content/lightning-item-iframe.js
+++ b/calendar/lightning/content/lightning-item-iframe.js
@@ -2922,17 +2922,17 @@ function saveItem() {
 
     // We check if the organizerID is different from our
     // calendar-user-address-set. The organzerID is the owner of the calendar.
     // If it's different, that is because someone is acting on behalf of
     // the organizer.
     if (item.organizer && item.calendar.aclEntry) {
         let userAddresses = item.calendar.aclEntry.getUserAddresses({});
         if (userAddresses.length > 0 &&
-            !cal.attendeeMatchesAddresses(item.organizer, userAddresses)) {
+            !cal.email.attendeeMatchesAddresses(item.organizer, userAddresses)) {
             let organizer = item.organizer.clone();
             organizer.setProperty("SENT-BY", "mailto:" + userAddresses[0]);
             item.organizer = organizer;
         }
     }
     return item;
 }
 
@@ -3758,21 +3758,21 @@ function sendMailToUndecidedAttendees(aA
 }
 
 /**
  * Send Email to all given attendees.
  *
  * @param aAttendees    The attendees to send mail to.
  */
 function sendMailToAttendees(aAttendees) {
-    let toList = cal.getRecipientList(aAttendees);
+    let toList = cal.email.createRecipientList(aAttendees);
     let item = saveItem();
     let emailSubject = cal.calGetString("calendar-event-dialog", "emailSubjectReply", [item.title]);
     let identity = window.calendarItem.calendar.getProperty("imip.identity");
-    cal.sendMailTo(toList, emailSubject, null, identity);
+    cal.email.sendTo(toList, emailSubject, null, identity);
 }
 
 /**
  * Make sure all fields that may have calendar specific capabilities are updated
  */
 function updateCapabilities() {
     updateAttachment();
     updateConfigState({
@@ -3913,17 +3913,17 @@ function displayCounterProposal() {
                 propLabels.appendChild(propLabel);
                 propValues.appendChild(propValue);
                 idCounter++;
             }
         }
     }
 
     let attendeeId = window.counterProposal.attendee.CN ||
-                     cal.removeMailTo(window.counterProposal.attendee.id || "");
+                     cal.email.removeMailTo(window.counterProposal.attendee.id || "");
     let partStat = window.counterProposal.attendee.participationStatus;
     if (partStat == "DECLINED") {
         partStat = "counterSummaryDeclined";
     } else if (partStat == "TENTATIVE") {
         partStat = "counterSummaryTentative";
     } else if (partStat == "ACCEPTED") {
         partStat = "counterSummaryAccepted";
     } else if (partStat == "DELEGATED") {
--- a/calendar/lightning/modules/ltnInvitationUtils.jsm
+++ b/calendar/lightning/modules/ltnInvitationUtils.jsm
@@ -364,17 +364,17 @@ ltn.invitation = {
                     if (content.textContent != oldContent.textContent) {
                         _content2Child(content, "added", content.textContent);
                         _content2Child(content, "newline", null, false);
                         _content2Child(content, "removed", oldContent.textContent, false);
                     }
                 } else {
                     content = doc.getElementById(aElement + "-table");
                     oldContent = aOldDoc.getElementById(aElement + "-table");
-                    let excludeAddress = cal.removeMailTo(aIgnoreId);
+                    let excludeAddress = cal.email.removeMailTo(aIgnoreId);
                     if (content && oldContent && !content.isEqualNode(oldContent)) {
                         // extract attendees
                         let attendees = _getAttendees(doc, aElement);
                         let oldAttendees = _getAttendees(aOldDoc, aElement);
                         // decorate newly added attendees
                         for (let att of Object.keys(attendees)) {
                             if (!(att in oldAttendees)) {
                                 _content2Child(attendees[att], "added", att);
@@ -425,40 +425,40 @@ ltn.invitation = {
     /**
      * Returns the header section for an invitation email.
      * @param   {String}         aMessageId  the message id to use for that email
      * @param   {nsIMsgIdentity} aIdentity   the identity to use for that email
      * @returns {String}                     the source code of the header section of the email
      */
     getHeaderSection: function(aMessageId, aIdentity, aToList, aSubject) {
         let recipient = aIdentity.fullName + " <" + aIdentity.email + ">";
-        let from = aIdentity.fullName.length ? cal.validateRecipientList(recipient)
+        let from = aIdentity.fullName.length ? cal.email.validateRecipientList(recipient)
                                              : aIdentity.email;
         let header = "MIME-version: 1.0\r\n" +
                      (aIdentity.replyTo ? "Return-path: " +
                                           ltn.invitation.encodeMimeHeader(aIdentity.replyTo, true) +
                                           "\r\n" : "") +
                      "From: " + ltn.invitation.encodeMimeHeader(from, true) + "\r\n" +
                      (aIdentity.organization ? "Organization: " +
                                                ltn.invitation.encodeMimeHeader(aIdentity.organization) +
                                                "\r\n" : "") +
                      "Message-ID: " + aMessageId + "\r\n" +
                      "To: " + ltn.invitation.encodeMimeHeader(aToList, true) + "\r\n" +
                      "Date: " + ltn.invitation.getRfc5322FormattedDate() + "\r\n" +
                      "Subject: " + ltn.invitation
                                       .encodeMimeHeader(aSubject.replace(/(\n|\r\n)/, "|")) + "\r\n";
         let validRecipients;
         if (aIdentity.doCc) {
-            validRecipients = cal.validateRecipientList(aIdentity.doCcList);
+            validRecipients = cal.email.validateRecipientList(aIdentity.doCcList);
             if (validRecipients != "") {
                 header += "Cc: " + ltn.invitation.encodeMimeHeader(validRecipients, true) + "\r\n";
             }
         }
         if (aIdentity.doBcc) {
-            validRecipients = cal.validateRecipientList(aIdentity.doBccList);
+            validRecipients = cal.email.validateRecipientList(aIdentity.doBccList);
             if (validRecipients != "") {
                 header += "Bcc: " + ltn.invitation.encodeMimeHeader(validRecipients, true) + "\r\n";
             }
         }
         return header;
     },
 
     /**
--- a/calendar/test/unit/test_bug1199942.js
+++ b/calendar/test/unit/test_bug1199942.js
@@ -15,17 +15,17 @@ function createAttendee_test() {
                 { input: "MAILTO:user2@example.net", expected: "mailto:user2@example.net" },
                 { input: "user3@example.net", expected: "mailto:user3@example.net" },
                 { input: "urn:uuid:user4", expected: "urn:uuid:user4" }];
     let event = cal.createEvent();
     for (let test of data) {
         let attendee = cal.createAttendee();
         attendee.id = test.input;
         event.addAttendee(attendee);
-        let readAttendee = event.getAttendeeById(cal.prependMailTo(test.input));
+        let readAttendee = event.getAttendeeById(cal.email.prependMailTo(test.input));
         equal(readAttendee.id, test.expected);
     }
 }
 
 function serializeEvent_test() {
     let ics = "BEGIN:VCALENDAR\n" +
               "PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN\n" +
               "VERSION:2.0\n" +
--- a/calendar/test/unit/test_bug1204255.js
+++ b/calendar/test/unit/test_bug1204255.js
@@ -53,17 +53,17 @@ function test_newAttendee() {
     for (let test of data) {
         for (let input of test.input) {
             let attendee = cal.createAttendee();
             attendee.id = input.id;
             attendee.participationStatus = input.partstat;
             attendee.commonName = input.cname;
             event.addAttendee(attendee);
         }
-        let readAttendee = event.getAttendeeById(cal.prependMailTo(test.expected.id));
+        let readAttendee = event.getAttendeeById(cal.email.prependMailTo(test.expected.id));
         equal(readAttendee.id, test.expected.id);
         equal(readAttendee.participationStatus, test.expected.partstat, "partstat matches for " + test.expected.id);
         equal(readAttendee.commonName, test.expected.cname, "commonName matches for " + test.expected.id);
     }
 }
 
 function test_fromICS() {
     let ics = [
--- a/calendar/test/unit/test_calutils.js
+++ b/calendar/test/unit/test_calutils.js
@@ -51,17 +51,17 @@ function getAttendeeEmail_test() {
         let attendee = cal.createAttendee();
         attendee.id = test.input.id;
         if (test.input.cname) {
             attendee.commonName = test.input.cname;
         }
         if (test.input.email) {
             attendee.setProperty("EMAIL", test.input.email);
         }
-        equal(cal.getAttendeeEmail(attendee, test.input.useCn), test.expected, "(test #" + i + ")");
+        equal(cal.email.getAttendeeEmail(attendee, test.input.useCn), test.expected, "(test #" + i + ")");
     }
 }
 
 function getAttendeesBySender_test() {
     let data = [{
         input: {
             attendees: [{ id: "mailto:user1@example.net", sentBy: null },
                         { id: "mailto:user2@example.net", sentBy: null }],
@@ -165,41 +165,41 @@ function getRecipientList_test() {
         for (let att of test.input) {
             let attendee = cal.createAttendee();
             attendee.id = att.id;
             if (att.cname) {
                 attendee.commonName = att.cname;
             }
             attendees.push(attendee);
         }
-        equal(cal.getRecipientList(attendees), test.expected, "(test #" + i + ")");
+        equal(cal.email.createRecipientList(attendees), test.expected, "(test #" + i + ")");
     }
 }
 
 function prependMailTo_test() {
     let data = [{ input: "mailto:first.last@example.net", expected: "mailto:first.last@example.net" },
                 { input: "MAILTO:first.last@example.net", expected: "mailto:first.last@example.net" },
                 { input: "first.last@example.net", expected: "mailto:first.last@example.net" },
                 { input: "first.last.example.net", expected: "first.last.example.net" }];
     let i = 0;
     for (let test of data) {
         i++;
-        equal(cal.prependMailTo(test.input), test.expected, "(test #" + i + ")");
+        equal(cal.email.prependMailTo(test.input), test.expected, "(test #" + i + ")");
     }
 }
 
 function removeMailTo_test() {
     let data = [{ input: "mailto:first.last@example.net", expected: "first.last@example.net" },
                 { input: "MAILTO:first.last@example.net", expected: "first.last@example.net" },
                 { input: "first.last@example.net", expected: "first.last@example.net" },
                 { input: "first.last.example.net", expected: "first.last.example.net" }];
     let i = 0;
     for (let test of data) {
         i++;
-        equal(cal.removeMailTo(test.input), test.expected, "(test #" + i + ")");
+        equal(cal.email.removeMailTo(test.input), test.expected, "(test #" + i + ")");
     }
 }
 
 function resolveDelegation_test() {
     let data = [{
         input: {
             attendee:
                 'ATTENDEE;DELEGATED-FROM="mailto:attendee2@example.net";CN="Attendee 1":mailto:at' +
@@ -340,12 +340,12 @@ function validateRecipientList_test() {
         input: "first1 last2 <first1.last1@example.net>, last2, first2 <first2.last2@example.net>" +
                ", \"last3, first3\" <first3.last2@example.net>",
         expected: "first1 last2 <first1.last1@example.net>, \"last2, first2\" <first2.last2@examp" +
                   "le.net>, \"last3, first3\" <first3.last2@example.net>"
     }];
     let i = 0;
     for (let test of data) {
         i++;
-        equal(cal.validateRecipientList(test.input), test.expected,
+        equal(cal.email.validateRecipientList(test.input), test.expected,
               "(test #" + i + ")");
     }
 }
--- a/calendar/test/unit/test_utils.js
+++ b/calendar/test/unit/test_utils.js
@@ -55,24 +55,24 @@ function test_recentzones() {
 function test_formatcss() {
     equal(cal.view.formatStringForCSSRule(" "), "_");
     equal(cal.view.formatStringForCSSRule("ΓΌ"), "-uxfc-");
     equal(cal.view.formatStringForCSSRule("a"), "a");
 }
 
 function test_attendeeMatchesAddresses() {
     let a = cal.createAttendee("ATTENDEE:mailto:horst");
-    ok(cal.attendeeMatchesAddresses(a, ["HORST", "peter"]));
-    ok(!cal.attendeeMatchesAddresses(a, ["HORSTpeter", "peter"]));
-    ok(!cal.attendeeMatchesAddresses(a, ["peter"]));
+    ok(cal.email.attendeeMatchesAddresses(a, ["HORST", "peter"]));
+    ok(!cal.email.attendeeMatchesAddresses(a, ["HORSTpeter", "peter"]));
+    ok(!cal.email.attendeeMatchesAddresses(a, ["peter"]));
 
     a = cal.createAttendee("ATTENDEE;EMAIL=\"horst\":urn:uuid:horst");
-    ok(cal.attendeeMatchesAddresses(a, ["HORST", "peter"]));
-    ok(!cal.attendeeMatchesAddresses(a, ["HORSTpeter", "peter"]));
-    ok(!cal.attendeeMatchesAddresses(a, ["peter"]));
+    ok(cal.email.attendeeMatchesAddresses(a, ["HORST", "peter"]));
+    ok(!cal.email.attendeeMatchesAddresses(a, ["HORSTpeter", "peter"]));
+    ok(!cal.email.attendeeMatchesAddresses(a, ["peter"]));
 }
 
 function test_getDefaultStartDate() {
     function transform(nowString, refDateString) {
         now = cal.createDateTime(nowString);
         let refDate = refDateString ? cal.createDateTime(refDateString) : null;
         return cal.dtz.getDefaultStartDate(refDate);
     }