diff options
Diffstat (limited to 'comm/mailnews/compose/test/unit/test_sendMailAddressIDN.js')
-rw-r--r-- | comm/mailnews/compose/test/unit/test_sendMailAddressIDN.js | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/comm/mailnews/compose/test/unit/test_sendMailAddressIDN.js b/comm/mailnews/compose/test/unit/test_sendMailAddressIDN.js new file mode 100644 index 0000000000..56ab77c303 --- /dev/null +++ b/comm/mailnews/compose/test/unit/test_sendMailAddressIDN.js @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/** + * Tests sending messages to addresses with non-ASCII characters. + */ +/* import-globals-from ../../../test/resources/alertTestUtils.js */ +load("../../../resources/alertTestUtils.js"); + +var test = null; +var server; +var finished = false; + +var sentFolder; + +var kSender = "from@foo.invalid"; +var kToASCII = "to@foo.invalid"; +var kToValid = "to@v\u00E4lid.foo.invalid"; +var kToValidACE = "to@xn--vlid-loa.foo.invalid"; +var kToInvalid = "b\u00F8rken.to@invalid.foo.invalid"; +var kToInvalidWithoutDomain = "b\u00F8rken.to"; +var NS_ERROR_ILLEGAL_LOCALPART = 0x80553139; + +// for alertTestUtils.js +let resolveAlert; +function alertPS(parent, aDialogText, aText) { + var composeProps = Services.strings.createBundle( + "chrome://messenger/locale/messengercompose/composeMsgs.properties" + ); + var expectedAlertMessage = + composeProps.GetStringFromName("sendFailed") + + "\n" + + composeProps + .GetStringFromName("errorIllegalLocalPart2") + // Without the domain, we currently don't display any name in the + // message part. + .replace("%s", test == kToInvalidWithoutDomain ? "" : test); + + // we should only get here for the kToInvalid test case + Assert.equal(aText, expectedAlertMessage); + resolveAlert(); +} + +// message listener implementations +function MsgSendListener(aRecipient, originalData) { + this.rcpt = aRecipient; + this.originalData = originalData; +} + +/** + * @implements {nsIMsgSendListener} + * @implements {nsIMsgCopyServiceListener} + */ +MsgSendListener.prototype = { + // nsIMsgSendListener + onStartSending(aMsgID, aMsgSize) {}, + onProgress(aMsgID, aProgress, aProgressMax) {}, + onStatus(aMsgID, aMsg) {}, + onStopSending(aMsgID, aStatus, aMsg, aReturnFile) { + try { + if (test == kToValid || test == kToASCII) { + Assert.equal(aStatus, 0); + do_check_transaction(server.playTransaction(), [ + "EHLO test", + "MAIL FROM:<" + + kSender + + "> BODY=8BITMIME SIZE=" + + this.originalData.length, + "RCPT TO:<" + this.rcpt + ">", + "DATA", + ]); + // Compare data file to what the server received + Assert.equal(this.originalData, server._daemon.post); + } else { + Assert.equal(aStatus, NS_ERROR_ILLEGAL_LOCALPART); + do_check_transaction(server.playTransaction(), ["EHLO test"]); + // Local address (before the @) has non-ascii char(s) or the @ is + // missing from the address. An alert is triggered after the EHLO is + // sent. Nothing else occurs so we "finish" the test to avoid + // NS_ERROR_ABORT test failure due to timeout waiting for the send + // (which doesn't occurs) to complete. + } + } catch (e) { + do_throw(e); + } finally { + server.stop(); + var thread = gThreadManager.currentThread; + while (thread.hasPendingEvents()) { + thread.processNextEvent(false); + } + do_test_finished(); + } + }, + onGetDraftFolderURI(aMsgID, aFolderURI) {}, + onSendNotPerformed(aMsgID, aStatus) {}, + onTransportSecurityError(msgID, status, secInfo, location) {}, + + // nsIMsgCopyServiceListener + OnStartCopy() {}, + OnProgress(aProgress, aProgressMax) {}, + SetMessageKey(aKey) {}, + GetMessageId(aMessageId) {}, + OnStopCopy(aStatus) { + Assert.equal(aStatus, 0); + try { + // Now do a comparison of what is in the sent mail folder + let msgData = mailTestUtils.loadMessageToString( + sentFolder, + mailTestUtils.firstMsgHdr(sentFolder) + ); + // Skip the headers etc that mailnews adds + var pos = msgData.indexOf("From:"); + Assert.notEqual(pos, -1); + msgData = msgData.substr(pos); + Assert.equal(this.originalData, msgData); + } catch (e) { + do_throw(e); + } finally { + finished = true; + } + }, + + // QueryInterface + QueryInterface: ChromeUtils.generateQI([ + "nsIMsgSendListener", + "nsIMsgCopyServiceListener", + ]), +}; + +async function doSendTest(aRecipient, aRecipientExpected, waitForPrompt) { + info(`Testing send to ${aRecipient} will get sent to ${aRecipientExpected}`); + let promiseAlertReceived = new Promise(resolve => { + resolveAlert = resolve; + }); + test = aRecipient; + server = setupServerDaemon(); + server.start(); + var smtpServer = getBasicSmtpServer(server.port); + var identity = getSmtpIdentity(kSender, smtpServer); + Assert.equal(identity.doFcc, true); + + // Random test file with data we don't actually care about. ;-) + var testFile = do_get_file("data/message1.eml"); + var originalData = await IOUtils.readUTF8(testFile.path); + + // Handle the server in a try/catch/finally loop so that we always will stop + // the server if something fails. + try { + do_test_pending(); + var compFields = Cc[ + "@mozilla.org/messengercompose/composefields;1" + ].createInstance(Ci.nsIMsgCompFields); + compFields.from = identity.email; + compFields.to = aRecipient; + + var msgSend = Cc["@mozilla.org/messengercompose/send;1"].createInstance( + Ci.nsIMsgSend + ); + msgSend.sendMessageFile( + identity, + "", + compFields, + testFile, + false, + false, + Ci.nsIMsgSend.nsMsgDeliverNow, + null, + new MsgSendListener(aRecipientExpected, originalData), + null, + null + ); + + server.performTest(); + do_timeout(10000, function () { + if (!finished) { + do_throw("Notifications of message send/copy not received"); + } + }); + if (waitForPrompt) { + await promiseAlertReceived; + } + } catch (e) { + Assert.ok(false, "Send fail: " + e); + } finally { + server.stop(); + var thread = gThreadManager.currentThread; + while (thread.hasPendingEvents()) { + thread.processNextEvent(true); + } + } +} + +add_setup(function () { + registerAlertTestUtils(); + + // Ensure we have at least one mail account + localAccountUtils.loadLocalMailAccount(); + MailServices.accounts.setSpecialFolders(); + sentFolder = localAccountUtils.rootFolder.createLocalSubfolder("Sent"); +}); + +add_task(async function plainASCIIRecipient() { + // Test 1: + // Plain ASCII recipient address. + await doSendTest(kToASCII, kToASCII, false); +}); + +add_task(async function domainContainsNonAscii() { + // Test 2: + // The recipient's domain part contains a non-ASCII character, hence the + // address needs to be converted to ACE before sending. + // The old code would just strip the non-ASCII character and try to send + // the message to the remaining - wrong! - address. + // The new code will translate the domain part to ACE for the SMTP + // transaction (only), i.e. the To: header will stay as stated by the sender. + await doSendTest(kToValid, kToValidACE, false); +}); + +add_task(async function localContainsNonAscii() { + // Test 3: + // The recipient's local part contains a non-ASCII character, which is not + // allowed with unextended SMTP. + // The old code would just strip the invalid character and try to send the + // message to the remaining - wrong! - address. + // The new code will present an informational message box and deny sending. + await doSendTest(kToInvalid, kToInvalid, true); +}); + +add_task(async function invalidCharNoAt() { + // Test 4: + // Bug 856506. invalid char without '@' causes crash. + await doSendTest(kToInvalidWithoutDomain, kToInvalidWithoutDomain, true); +}); |