This is just some static backup of the original site, don't expect every link to work!

source: chrome/content/v_identity/vI_smartIdentity.js @ c0fe7f

lite_0.1multiEditng_0.6ng_0.6_helpng_0.8ng_0.9
Last change on this file since c0fe7f was c0fe7f, checked in by rene <rene@…>, 13 years ago

additional debug-output

  • Property mode set to 100644
File size: 20.6 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2    This program is free software; you can redistribute it and/or modify
3    it under the terms of the GNU General Public License as published by
4    the Free Software Foundation; either version 2 of the License, or
5    (at your option) any later version.
6
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
15
16    The Original Code is the Virtual Identity Extension.
17
18    The Initial Developer of the Original Code is Rene Ejury.
19    Portions created by the Initial Developer are Copyright (C) 2007
20    the Initial Developer. All Rights Reserved.
21
22    Contributor(s):
23 * ***** END LICENSE BLOCK ***** */
24
25var vI_smartIdentity = {
26    messenger : Components.classes["@mozilla.org/messenger;1"].createInstance()
27        .QueryInterface(Components.interfaces.nsIMessenger),
28       
29    smartIdentity_BaseIdentity : null,
30
31    clean : function() {
32        vI_smartIdentity.smartIdentity_BaseIdentity = null;
33    },
34   
35    // After Loading the MessageComposeDialog, check if smartIdentity is needed
36    init : function() {
37        var type = gMsgCompose.type;
38        var msgComposeType = Components.interfaces.nsIMsgCompType;
39        vI_notificationBar.dump("## vI_smartIdentity: msgComposeType = " + type + "\n");
40           
41        switch (type) {
42            case msgComposeType.ForwardAsAttachment:
43            case msgComposeType.ForwardInline:
44            case msgComposeType.Reply:
45            case msgComposeType.ReplyAll:
46            case msgComposeType.ReplyToGroup: // reply to a newsgroup, would possibly be stopped later
47            case msgComposeType.ReplyToSender:
48            case msgComposeType.ReplyToSenderAndGroup: // reply to a newsgroup, would possibly be stopped later
49            case msgComposeType.ReplyWithTemplate:
50                vI_smartIdentity.Reply(); break;
51            case msgComposeType.Draft:
52            case msgComposeType.Template:
53                vI_smartIdentity.Draft(); break;
54            case msgComposeType.New:
55            case msgComposeType.NewsPost:
56            case msgComposeType.MailToUrl:
57                vI_smartIdentity.NewMail(); break;
58            }
59    },
60       
61    // this function adds a timestamp to the current sender
62    __autoTimestamp : function() {
63        vI_notificationBar.dump("## vI_smartIdentity: __autoTimestamp()\n");
64        if (document.getElementById("msgIdentity_clone").vid) {
65            vI_notificationBar.dump("## vI_smartIdentity: Virtual Identity in use, aborting\n");
66            return;
67        }
68
69        var current_email = getCurrentIdentity().email;
70        vI_notificationBar.dump("## vI_smartIdentity: current email: " + current_email + "\n");
71       
72        var dateobj = new Date();
73        var new_email = current_email.replace(/@/g, parseInt(dateobj.getTime()/1000)+"@");
74        vI_notificationBar.dump("## vI_smartIdentity: new email: " + new_email + "\n");
75
76        vI_notificationBar.setNote(vI.elements.strings.getString("vident.smartIdentity.vIUsage") + ".",
77                    "smart_reply_notification");
78
79        document.getElementById("msgIdentity_clone").email = new_email;
80    },
81   
82    NewMail : function() {
83        var storageIdentities = new identityCollection();
84        vI_storage.getVIdentityFromAllRecipients(storageIdentities);
85       
86        if (storageIdentities.number > 0) vI_smartIdentity.__smartIdentitySelection(storageIdentities, false)
87        else if (vI.preferences.getBoolPref("autoTimestamp")) vI_smartIdentity.__autoTimestamp();   
88    },
89   
90    ReplyOnSent : function(hdr) {
91        vI_notificationBar.dump("## vI_smartIdentity: ReplyOnSent() (rules like SmartDraft)\n");
92       
93        var allIdentities = new identityCollection();
94
95        vI_smartIdentity.__SmartDraftOrReplyOnSent(hdr, allIdentities);
96        var storageIdentities = new identityCollection();
97        vI_storage.getVIdentityFromAllRecipients(storageIdentities);
98       
99        allIdentities.mergeWithoutDuplicates(storageIdentities);
100           
101        if (allIdentities.number > 0) vI_smartIdentity.__smartIdentitySelection(allIdentities, true);
102
103    },
104
105    Draft : function() {
106        vI_notificationBar.dump("## vI_smartIdentity: Draft()\n");
107       
108        var allIdentities = new identityCollection();
109
110        var draftHdr = vI_smartIdentity.messenger.
111            messageServiceFromURI(gMsgCompose.originalMsgURI).messageURIToMsgHdr(gMsgCompose.originalMsgURI);
112        // fails with seamonkey 1.1.11, so just try to read to draft id
113        try { draftHdr = vI_smartIdentity.messenger.
114            messageServiceFromURI(gMsgCompose.compFields.draftId).messageURIToMsgHdr(gMsgCompose.compFields.draftId);
115        } catch (ex) { };
116
117        vI_smartIdentity.__SmartDraftOrReplyOnSent(draftHdr, allIdentities);
118        var storageIdentities = new identityCollection();
119        vI_storage.getVIdentityFromAllRecipients(storageIdentities);
120       
121        allIdentities.mergeWithoutDuplicates(storageIdentities);
122           
123        if (allIdentities.number > 0) vI_smartIdentity.__smartIdentitySelection(allIdentities, true);
124    },
125   
126    __parseHeadersWithArray: function(hdr, allIdentities) {
127        var emails = {}; var fullNames = {}; var combinedNames = {};
128        var number = vI.headerParser.parseHeadersWithArray(hdr, emails, fullNames, combinedNames);
129        for (var index = 0; index < number; index++) {
130            var newIdentity = new identityData(emails.value[index], fullNames.value[index],
131                null, NO_SMTP_TAG, null, null);
132            allIdentities.addWithoutDuplicates(newIdentity);
133        }
134    },
135
136    // this function checks if we have a draft-case and Smart-Draft should replace the Identity
137    __SmartDraftOrReplyOnSent : function(hdr, allIdentities) {
138        if (!vI.preferences.getBoolPref("smart_draft"))
139            { vI_notificationBar.dump("## vI_smartIdentity: SmartDraft deactivated\n"); return; }
140
141        vI_notificationBar.dump("## vI_smartIdentity: __SmartDraftOrReplyOnSent()\n");
142
143        if (hdr) {
144            vI_smartIdentity.__parseHeadersWithArray(hdr.author, allIdentities)
145            vI_notificationBar.dump("## vI_smartIdentity: sender '" + allIdentities.identityDataCollection[0].combinedName + "'\n");
146        }
147        else vI_notificationBar.dump("## vI_smartIdentity: __SmartDraftOrReplyOnSent: No Header found, shouldn't happen\n");
148    },
149   
150    __filterAddresses : function(smartIdentities) {
151        var returnIdentities = new identityCollection();
152       
153        var filterList  =
154            vI.unicodeConverter.ConvertToUnicode(vI.preferences.getCharPref("smart_reply_filter")).split(/\n/)
155        if (filterList.length == 0) filterList[0] == ""
156       
157        for (var i = 0; i < filterList.length; i++) {
158            const filterType = { None : 0, RegExp : 1, StrCmp : 2 }
159            var recentfilterType; var skipRegExp = false;
160            if (filterList.length <= 1 && filterList[0] == "")
161                { vI_notificationBar.dump("## vI_smartIdentity: no filters configured\n"); recentfilterType = filterType.None; }
162            else if (/^\/(.*)\/$/.exec(filterList[i]))
163                { vI_notificationBar.dump("## vI_smartIdentity: filter emails with RegExp '"
164                    + filterList[i].replace(/\\/g,"\\\\") + "'\n"); recentfilterType = filterType.RegExp; }
165            else    { vI_notificationBar.dump("## vI_smartIdentity: filter emails, compare with '"
166                    + filterList[i] + "'\n"); recentfilterType = filterType.StrCmp; }
167            for (var j = 0; j < smartIdentities.number; j++) { // check if recent email-address (pre-choosen identity) is found in
168            // copied and adapted from correctIdentity, thank you for the RegExp-idea!
169                var add_addr = false;
170                switch (recentfilterType) {
171                    case filterType.None:
172                        add_addr = true; break;
173                    case filterType.RegExp:
174                        if (skipRegExp) break;
175                        try {   /^\/(.*)\/$/.exec(filterList[i]);
176                            add_addr =  (smartIdentities.identityDataCollection[j].email.match(new RegExp(RegExp.$1,"i")))
177                        }
178                        catch(vErr) {
179                            vI_notificationBar.addNote(
180                                vI.elements.strings.getString("vident.smartIdentity.ignoreRegExp") +
181                                +filterList[i].replace(/\\/g,"\\\\") + " .",
182                                "smart_reply_notification");
183                                skipRegExp = true; }
184                        break;
185                    case filterType.StrCmp:
186                        add_addr = ( smartIdentities.identityDataCollection[j].email.toLowerCase().indexOf(filterList[i].toLowerCase()) != -1)
187                        break;
188                }
189                if (add_addr)   returnIdentities.addWithoutDuplicates(smartIdentities.identityDataCollection[j])
190            }
191        }
192        smartIdentities.takeOver(returnIdentities);
193    },
194   
195    __smartReplyCollectAddresses : function(hdr, allIdentities) {
196        // add emails from selected headers (stored by vI_getHeader.xul/js)
197        var reply_headers = vI.unicodeConverter.ConvertToUnicode(vI.preferences.getCharPref("smart_reply_headers")).split(/\n/)
198                   
199        for (var index = 0; index < reply_headers.length; index++) {
200            // ------------- prepare fields to read the stored header ----------------
201            var replyHeader_splitted = reply_headers[index].split(/:/)
202            // use first part (all before ':') as the header name
203            var replyHeaderName = replyHeader_splitted[0].toLowerCase()
204            // check second or third part for any number
205            var replyHeaderNumber = parseInt(replyHeader_splitted[1])
206            if (isNaN(replyHeaderNumber)) replyHeaderNumber = parseInt(replyHeader_splitted[2])
207            // check if Fullnames should be erased
208            var replyHeaderEmptyFullNames = ((replyHeader_splitted[1] && replyHeader_splitted[1].match(/@/)) ||
209                            (replyHeader_splitted[2] && replyHeader_splitted[2].match(/@/)))
210           
211            // create header name to find the value
212            var replyHeaderNameToRead = replyHeaderName
213            if (!isNaN(replyHeaderNumber)) replyHeaderNameToRead += ":" + replyHeaderNumber
214           
215            // if mailing-list ignore to-header (usually the mailing list address)
216            if (replyHeaderNameToRead == "to" && hdr.getStringProperty("vI_list-id")) {
217                vI_notificationBar.dump("## vI_smartIdentity: header 'list-id' found (mailinglist), skipping header 'to'\n");
218                continue;
219            }
220           
221            // ------------- read the stored header -------------------------------
222            var value = vI.unicodeConverter.ConvertToUnicode(hdr.getStringProperty("vI_" + replyHeaderNameToRead))
223            vI_notificationBar.dump("## vI_smartIdentity: reading header '" +
224                replyHeaderNameToRead + "': '" + value + "'\n");
225           
226            // ------------- parse address-string to get a field of single email-addresses
227            var splitted = new identityCollection();
228            vI_smartIdentity.__parseHeadersWithArray(value, splitted);
229           
230            // move found addresses step by step to allIdentities, and change values if requested
231            for (var i = 0; i < splitted.number; i++) {
232                // if there is no email than it makes no sense to use it as a sender
233                if (!splitted.identityDataCollection[i].email.match(/^.*@.*$/)) {
234                    vI_notificationBar.dump("## vI_smartIdentity:   skipping '" +
235                    splitted.identityDataCollection[i].email + "', no email\n")
236                    continue;
237                }
238
239                if (replyHeaderEmptyFullNames) splitted.identityDataCollection[i].fullName = ""
240
241                allIdentities.addWithoutDuplicates(splitted.identityDataCollection[i]);
242
243                vI_notificationBar.dump("## vI_smartIdentity:   found '" +
244                    splitted.identityDataCollection[i].combinedName + "'\n")
245            }
246        }
247    },
248   
249    Reply : function() {
250        var hdr = vI_smartIdentity.messenger.
251            messageServiceFromURI(gMsgCompose.originalMsgURI).messageURIToMsgHdr(gMsgCompose.originalMsgURI);
252
253        vI_notificationBar.dump("## vI_smartIdentity: Reply()\n");
254
255        if (hdr && !gMsgCompose.compFields.newsgroups) {
256        //  RFC 2821 (http://www.ietf.org/rfc/rfc2821.txt) says:
257        //  "4.4 Trace Information
258        //  When an SMTP server receives a message for delivery or further
259        //  processing, it MUST insert trace ("time stamp" or "Received")
260        //  information at the beginning of the message content, as discussed in
261        //  section 4.1.1.4."
262        //  so it should be always possible to decide if Reply or Draft based on received headers
263        //  hidden option smart_detectByReceivedHeader will act as a switch for not RFC-compliant servers
264            // RFC-compliant
265            if (vI.preferences.getBoolPref("smart_detectByReceivedHeader")) {
266                if (!hdr.getStringProperty("vI_received")) { // mail was not received
267                    vI_notificationBar.dump("## vI_smartIdentity: reply on non-received (sent?) mail. Using SmartDraft. \n");
268                    vI_smartIdentity.ReplyOnSent(hdr);
269                    return;
270                }
271            }
272            // not RFC-compliant
273            else {
274                const MSG_FOLDER_FLAG_INBOX = 0x1000
275                const MSG_FOLDER_FLAG_SENTMAIL = 0x0200;
276
277                if (hdr && (hdr.folder.flags & MSG_FOLDER_FLAG_SENTMAIL)) {
278                    vI_notificationBar.dump("## vI_smartIdentity: reply from Sent folder.");
279                    if (hdr.folder.flags & MSG_FOLDER_FLAG_INBOX)
280                        vI_notificationBar.dump(" Folder is INBOX, assuming Reply-Case. \n");
281                    else {
282                        vI_notificationBar.dump(" Using SmartDraft. \n");
283                        vI_smartIdentity.ReplyOnSent(hdr);
284                        return;
285                    }
286                }
287            }
288        }
289           
290        var storageIdentities = new identityCollection();
291        vI_storage.getVIdentityFromAllRecipients(storageIdentities);
292       
293        var smartIdentities = new identityCollection();
294        if (storageIdentities.number == 0 || !vI.preferences.getBoolPref("idSelection_storage_ignore_smart_reply"))
295            vI_smartIdentity.__SmartReply(hdr, smartIdentities);
296        else vI_notificationBar.dump("## vI_smartIdentity: SmartReply skipped, Identities in Storage found.\n");
297
298        // merge SmartReply-Identities and Storage-Identites
299        if (vI.preferences.getBoolPref("idSelection_storage_prefer_smart_reply"))
300            { smartIdentities.mergeWithoutDuplicates(storageIdentities); var allIdentities = smartIdentities; }
301        else
302            { storageIdentities.mergeWithoutDuplicates(smartIdentities); var allIdentities = storageIdentities; }
303       
304        vI_notificationBar.dump("## vI_smartIdentity: merged SmartReply & Storage, " + allIdentities.number + " address(es) left\n")
305       
306        if (allIdentities.number > 0) vI_smartIdentity.__smartIdentitySelection(allIdentities, false);
307    },
308   
309    // this function checks if we have a reply-case and Smart-Reply should replace the Identity
310    __SmartReply : function(hdr, smartIdentities) {
311        if (!vI.preferences.getBoolPref("smart_reply"))
312            { vI_notificationBar.dump("## vI_smartIdentity: SmartReply deactivated\n"); return; }
313        if (gMsgCompose.compFields.newsgroups && !vI.preferences.getBoolPref("smart_reply_for_newsgroups")) {
314            vI_notificationBar.dump("## vI_smartIdentity: SmartReply, answering to a newsgroup, aborting\n");
315            return;
316        }
317
318        vI_notificationBar.dump("## vI_smartIdentity: __SmartReply()\n");
319        vI_notificationBar.dump("## vI_smartIdentity: ----------------------------------------------------------\n")
320        if (hdr) {
321            /* first step: collect addresses */
322            vI_smartIdentity.__smartReplyCollectAddresses(hdr, smartIdentities);
323            vI_notificationBar.dump("## vI_smartIdentity: " + smartIdentities.number + " address(es) after parsing, before filtering\n")
324           
325            /* second step: filter (and sort) addresses */
326            vI_smartIdentity.__filterAddresses(smartIdentities);
327           
328            vI_notificationBar.dump("## vI_smartIdentity: filtering done, " + smartIdentities.number + " address(es) left\n")
329           
330            /* set default FullName */
331            var smart_reply_defaultFullName = vI.unicodeConverter.ConvertToUnicode(vI.preferences.getCharPref("smart_reply_defaultFullName"))
332            if (smart_reply_defaultFullName != "") {
333                for (var index = 0; index < smartIdentities.number; index++) {
334                    if (smartIdentities.identityDataCollection[index].fullName == "") {
335                        smartIdentities.identityDataCollection[index].fullName = smart_reply_defaultFullName
336                        vI_notificationBar.dump("## vI_smartIdentity: added default FullName '" + 
337                            smart_reply_defaultFullName + "' to '" + smartIdentities.identityDataCollection[index].email + "'\n")
338                    }
339                }
340            }   
341
342            /* smart_reply_ignoreFullName: compare email with other Identities          */
343            /* if match replace FullName with existing one, keep identity in list by now        */
344            /* will not be added to the menu but probably choosen with __smartIdentitySelection     */
345            if (vI.preferences.getBoolPref("smart_reply_ignoreFullName")) {
346                vI_notificationBar.dump("## vI_smartIdentity: compare with existing Identities (ignoring FullNames).\n")
347           
348                for (var index = 0; index < smartIdentities.number; index++) {
349                    var idKey = smartIdentities.identityDataCollection[index].isExistingIdentity(true);
350                    if (idKey) {
351                        var newFullName = gAccountManager.getIdentity(idKey).fullName;
352                        smartIdentities.identityDataCollection[index].fullName = newFullName;
353                        vI_notificationBar.dump("## vI_smartIdentity: replaced Fullname of '" + smartIdentities.identityDataCollection[index].email + "' with '" + newFullName + "' \n");
354                    }
355                }
356            }
357        }
358        else vI_notificationBar.dump("## vI_smartIdentity: SmartReply skipped. No Header-information found.\n");
359       
360        vI_notificationBar.dump("## vI_smartIdentity: ----------------------------------------------------------\n")
361    },
362   
363    __smartIdentitySelection : function(allIdentities, autocreate) {
364        document.getElementById("msgIdentity_clone").addIdentitiesToCloneMenu(allIdentities);
365
366        /* compare with existing Identities                                     */
367        for (var index = 0; index < allIdentities.number; index++) {
368            if (allIdentities.identityDataCollection[index].isExistingIdentity(true)) {
369                // if 'preferExisting' than select it and return
370                if (vI.preferences.getBoolPref("idSelection_preferExisting")) {
371                    vI_notificationBar.dump("## vI_smartIdentity: found existing Identity, use without interaction.\n");
372                    vI_smartIdentity.changeIdentityToSmartIdentity(allIdentities, index);
373                    return;
374                }
375                // else reorder list of Identities to prefer it on autoselect
376                vI_notificationBar.dump("## vI_smartIdentity: found existing Identity, prefer this one.\n");
377                var firstIdentity = allIdentities.identityDataCollection[index];
378                for (var i = index; index > 0; index--) {
379                    allIdentities.identityDataCollection[index] = allIdentities.identityDataCollection[index-1];
380                }
381                allIdentities.identityDataCollection[0] = firstIdentity;
382                break;
383            }
384        }
385       
386        if (!autocreate && vI.preferences.getBoolPref("idSelection_ask") && 
387            ((allIdentities.number == 1 && vI.preferences.getBoolPref("idSelection_ask_always"))
388                || allIdentities.number > 1)) {
389            for (var index = 0; index < allIdentities.number; index++) {
390                vI_notificationBar.dump("## vI_smartIdentityReplyDialog index=" + index + ": '" + allIdentities.identityDataCollection[index].combinedName + "' "
391                    + "(" + allIdentities.identityDataCollection[index].id.value + "," + allIdentities.identityDataCollection[index].smtp.value + ")\n");
392            }
393            window.openDialog("chrome://v_identity/content/vI_smartReplyDialog.xul",0, // give the Dialog a unique id
394                    "chrome, dialog, modal, alwaysRaised, resizable=yes",
395                     allIdentities,
396                    /* callback: */ vI_smartIdentity.changeIdentityToSmartIdentity).focus();
397        }
398        else if (autocreate || vI.preferences.getBoolPref("idSelection_autocreate")) {
399            vI_smartIdentity.changeIdentityToSmartIdentity(allIdentities, 0);
400        }   
401    },
402   
403    changeIdentityToSmartIdentity : function(allIdentities, selectedValue) {
404        vI_notificationBar.dump("## changeIdentityToSmartIdentity selectedValue=" + selectedValue + ": '" + allIdentities.identityDataCollection[selectedValue].combinedName + "' "
405            + "(" + allIdentities.identityDataCollection[selectedValue].id.value + "," + allIdentities.identityDataCollection[selectedValue].smtp.value + ")\n");
406        document.getElementById("msgIdentity_clone").selectedMenuItem = allIdentities.menuItems[selectedValue];
407        if (document.getElementById("msgIdentity_clone").vid) {
408            var label=vI.elements.strings.getString("vident.smartIdentity.vIUsage");
409            if (allIdentities.number > 1) label += " "
410                + vI.elements.strings.getString("vident.smartIdentity.moreThanOne");
411            vI_notificationBar.addNote(label + ".", "smart_reply_notification");
412        }
413        vI_smartIdentity.__removeSmartIdentityFromRecipients(allIdentities, selectedValue);
414    },
415   
416    __removeSmartIdentityFromRecipients : function(allIdentities, index) {
417        var skip_bcc = false;
418       
419        if (getCurrentIdentity().doBcc) {
420            var bcc_addresses = new identityCollection();
421            vI_smartIdentity.__parseHeadersWithArray(getCurrentIdentity().doBccList, bcc_addresses);
422           
423            for (var i = 0; i < bcc_addresses.number; i++) {
424                if (allIdentities.identityDataCollection[index].email == bcc_addresses.identityDataCollection[i].email) {
425                    skip_bcc = true; break;
426                }
427            }
428        }
429       
430        for (var row = 1; row <= top.MAX_RECIPIENTS; row ++) {
431            var popup = awGetPopupElement(row);
432            var input = awGetInputElement(row);
433            var recipientType = popup.selectedItem.getAttribute("value");
434            // if the entry is not a recipient, just continue
435            if (recipientType == "addr_reply" || recipientType == "addr_followup") continue;
436            // check if the entry is used as a BCC selected in account settings
437            if (recipientType == "addr_bcc" && skip_bcc) continue;
438            // check if entry is matching senders address, if so, remove it
439            if (input.value == allIdentities.identityDataCollection[index].email ||
440                input.value == allIdentities.identityDataCollection[index].combinedName) {
441                    awSetInputAndPopupValue(input, "", popup, "addr_to", -1);
442                    awCleanupRows()
443                    vI_notificationBar.addNote(" " +
444                        vI.elements.strings.getString("vident.smartIdentity.remRecipient"),
445                        "smart_reply_notification");
446                    break;
447            }
448        }
449    }
450}
Note: See TracBrowser for help on using the repository browser.