Fixed issue# 1790 - On reply of an email, the recipient will not be set if sender header contains invalid email addresses.
This commit is contained in:
parent
6f08071c3d
commit
a0c04ed190
3 changed files with 419 additions and 169 deletions
|
@ -890,6 +890,29 @@ class App.Utils
|
||||||
text = text.replace(/http(s|):\/\/[-A-Za-z0-9+&@#\/%?=~_\|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]/img, placeholder)
|
text = text.replace(/http(s|):\/\/[-A-Za-z0-9+&@#\/%?=~_\|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]/img, placeholder)
|
||||||
text.length
|
text.length
|
||||||
|
|
||||||
|
@parseAddressListLocal: (line) ->
|
||||||
|
recipients = emailAddresses.parseAddressList(line)
|
||||||
|
result = []
|
||||||
|
if !_.isEmpty(recipients)
|
||||||
|
for recipient in recipients
|
||||||
|
if recipient && recipient.address
|
||||||
|
result.push recipient.address
|
||||||
|
return result
|
||||||
|
|
||||||
|
# workaround for email-addresses.js issue with this kind of
|
||||||
|
# mail headers "From: invalid sender, realname <sender@example.com>"
|
||||||
|
# email-addresses.js is returning null because it can't parse the
|
||||||
|
# whole header
|
||||||
|
if _.isEmpty(recipients) && line.match('@')
|
||||||
|
recipients = line.split(',')
|
||||||
|
re = /(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/
|
||||||
|
for recipient in recipients
|
||||||
|
if recipient && recipient.match('@')
|
||||||
|
localResult = recipient.match(re)
|
||||||
|
if localResult && localResult[0]
|
||||||
|
result.push localResult[0]
|
||||||
|
result
|
||||||
|
|
||||||
@getRecipientArticle: (ticket, article, article_created_by, type, email_addresses = [], all) ->
|
@getRecipientArticle: (ticket, article, article_created_by, type, email_addresses = [], all) ->
|
||||||
|
|
||||||
# empty form
|
# empty form
|
||||||
|
@ -938,16 +961,18 @@ class App.Utils
|
||||||
# check if article sender is local
|
# check if article sender is local
|
||||||
senderIsLocal = false
|
senderIsLocal = false
|
||||||
if !_.isEmpty(article.from)
|
if !_.isEmpty(article.from)
|
||||||
senders = emailAddresses.parseAddressList(article.from)
|
senders = App.Utils.parseAddressListLocal(article.from)
|
||||||
if senders && senders[0] && senders[0].address
|
if senders
|
||||||
senderIsLocal = isLocalAddress(senders[0].address)
|
for sender in senders
|
||||||
|
if sender && sender.address && sender.address.match('@')
|
||||||
|
senderIsLocal = isLocalAddress(sender.address)
|
||||||
|
|
||||||
# check if article recipient is local
|
# check if article recipient is local
|
||||||
recipientIsLocal = false
|
recipientIsLocal = false
|
||||||
if !_.isEmpty(article.to)
|
if !_.isEmpty(article.to)
|
||||||
recipients = emailAddresses.parseAddressList(article.to)
|
recipients = App.Utils.parseAddressListLocal(article.to)
|
||||||
if recipients && recipients[0] && recipients[0].address
|
if recipients && recipients[0]
|
||||||
recipientIsLocal = isLocalAddress(recipients[0].address)
|
recipientIsLocal = isLocalAddress(recipients[0])
|
||||||
|
|
||||||
# sender is local
|
# sender is local
|
||||||
if senderIsLocal
|
if senderIsLocal
|
||||||
|
@ -971,14 +996,14 @@ class App.Utils
|
||||||
|
|
||||||
# filter for uniq recipients
|
# filter for uniq recipients
|
||||||
recipientAddresses = {}
|
recipientAddresses = {}
|
||||||
|
|
||||||
addAddresses = (addressLine, line) ->
|
addAddresses = (addressLine, line) ->
|
||||||
lineNew = ''
|
lineNew = ''
|
||||||
recipients = emailAddresses.parseAddressList(addressLine)
|
recipients = App.Utils.parseAddressListLocal(addressLine)
|
||||||
|
|
||||||
if !_.isEmpty(recipients)
|
if !_.isEmpty(recipients)
|
||||||
for recipient in recipients
|
for recipient in recipients
|
||||||
if !_.isEmpty(recipient.address)
|
if !_.isEmpty(recipient)
|
||||||
localRecipientAddress = recipient.address.toString().toLowerCase()
|
localRecipientAddress = recipient.toString().toLowerCase()
|
||||||
|
|
||||||
# check if address is not local
|
# check if address is not local
|
||||||
if !isLocalAddress(localRecipientAddress)
|
if !isLocalAddress(localRecipientAddress)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
// email-addresses.js - RFC 5322 email address parser
|
// email-addresses.js - RFC 5322 email address parser
|
||||||
// v 2.0.1
|
// v 3.0.1
|
||||||
//
|
//
|
||||||
// http://tools.ietf.org/html/rfc5322
|
// http://tools.ietf.org/html/rfc5322
|
||||||
//
|
//
|
||||||
|
@ -186,27 +186,7 @@ function parse5322(opts) {
|
||||||
// "First Last" -> "First Last"
|
// "First Last" -> "First Last"
|
||||||
// "First Last" -> "First Last"
|
// "First Last" -> "First Last"
|
||||||
function collapseWhitespace(s) {
|
function collapseWhitespace(s) {
|
||||||
function isWhitespace(c) {
|
return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, '');
|
||||||
return c === ' ' ||
|
|
||||||
c === '\t' ||
|
|
||||||
c === '\r' ||
|
|
||||||
c === '\n';
|
|
||||||
}
|
|
||||||
var i, str;
|
|
||||||
str = "";
|
|
||||||
for (i = 0; i < s.length; i += 1) {
|
|
||||||
if (!isWhitespace(s[i]) || !isWhitespace(s[i + 1])) {
|
|
||||||
str += s[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isWhitespace(str[0])) {
|
|
||||||
str = str.substring(1);
|
|
||||||
}
|
|
||||||
if (isWhitespace(str[str.length - 1])) {
|
|
||||||
str = str.substring(0, str.length - 1);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UTF-8 pseudo-production (RFC 6532)
|
// UTF-8 pseudo-production (RFC 6532)
|
||||||
|
@ -597,10 +577,14 @@ function parse5322(opts) {
|
||||||
return wrap('domain', function domainCheckTLD() {
|
return wrap('domain', function domainCheckTLD() {
|
||||||
var result = or(obsDomain, dotAtom, domainLiteral)();
|
var result = or(obsDomain, dotAtom, domainLiteral)();
|
||||||
if (opts.rejectTLD) {
|
if (opts.rejectTLD) {
|
||||||
if (result.semantic.indexOf('.') < 0) {
|
if (result && result.semantic && result.semantic.indexOf('.') < 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// strip all whitespace from domains
|
||||||
|
if (result) {
|
||||||
|
result.semantic = result.semantic.replace(/\s+/g, '');
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
|
@ -612,6 +596,36 @@ function parse5322(opts) {
|
||||||
)());
|
)());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3.6.2 Originator Fields
|
||||||
|
// Below we only parse the field body, not the name of the field
|
||||||
|
// like "From:", "Sender:", or "Reply-To:". Other libraries that
|
||||||
|
// parse email headers can parse those and defer to these productions
|
||||||
|
// for the "RFC 5322" part.
|
||||||
|
|
||||||
|
// RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields
|
||||||
|
// from = "From:" (mailbox-list / address-list) CRLF
|
||||||
|
function fromSpec() {
|
||||||
|
return wrap('from', or(
|
||||||
|
mailboxList,
|
||||||
|
addressList
|
||||||
|
)());
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields
|
||||||
|
// sender = "Sender:" (mailbox / address) CRLF
|
||||||
|
function senderSpec() {
|
||||||
|
return wrap('sender', or(
|
||||||
|
mailbox,
|
||||||
|
address
|
||||||
|
)());
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields
|
||||||
|
// reply-to = "Reply-To:" address-list CRLF
|
||||||
|
function replyToSpec() {
|
||||||
|
return wrap('reply-to', addressList());
|
||||||
|
}
|
||||||
|
|
||||||
// 4.1. Miscellaneous Obsolete Tokens
|
// 4.1. Miscellaneous Obsolete Tokens
|
||||||
|
|
||||||
// obs-NO-WS-CTL = %d1-8 / ; US-ASCII control
|
// obs-NO-WS-CTL = %d1-8 / ; US-ASCII control
|
||||||
|
@ -766,92 +780,186 @@ function parse5322(opts) {
|
||||||
// ast analysis
|
// ast analysis
|
||||||
|
|
||||||
function findNode(name, root) {
|
function findNode(name, root) {
|
||||||
var i, queue, node;
|
var i, stack, node;
|
||||||
if (root === null || root === undefined) { return null; }
|
if (root === null || root === undefined) { return null; }
|
||||||
queue = [root];
|
stack = [root];
|
||||||
while (queue.length > 0) {
|
while (stack.length > 0) {
|
||||||
node = queue.shift();
|
node = stack.pop();
|
||||||
if (node.name === name) {
|
if (node.name === name) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
for (i = 0; i < node.children.length; i += 1) {
|
for (i = node.children.length - 1; i >= 0; i -= 1) {
|
||||||
queue.push(node.children[i]);
|
stack.push(node.children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findAllNodes(name, root) {
|
function findAllNodes(name, root) {
|
||||||
var i, queue, node, result;
|
var i, stack, node, result;
|
||||||
if (root === null || root === undefined) { return null; }
|
if (root === null || root === undefined) { return null; }
|
||||||
queue = [root];
|
stack = [root];
|
||||||
result = [];
|
result = [];
|
||||||
while (queue.length > 0) {
|
while (stack.length > 0) {
|
||||||
node = queue.shift();
|
node = stack.pop();
|
||||||
if (node.name === name) {
|
if (node.name === name) {
|
||||||
result.push(node);
|
result.push(node);
|
||||||
}
|
}
|
||||||
for (i = 0; i < node.children.length; i += 1) {
|
for (i = node.children.length - 1; i >= 0; i -= 1) {
|
||||||
queue.push(node.children[i]);
|
stack.push(node.children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findAllNodesNoChildren(names, root) {
|
||||||
|
var i, stack, node, result, namesLookup;
|
||||||
|
if (root === null || root === undefined) { return null; }
|
||||||
|
stack = [root];
|
||||||
|
result = [];
|
||||||
|
namesLookup = {};
|
||||||
|
for (i = 0; i < names.length; i += 1) {
|
||||||
|
namesLookup[names[i]] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (stack.length > 0) {
|
||||||
|
node = stack.pop();
|
||||||
|
if (node.name in namesLookup) {
|
||||||
|
result.push(node);
|
||||||
|
// don't look at children (hence findAllNodesNoChildren)
|
||||||
|
} else {
|
||||||
|
for (i = node.children.length - 1; i >= 0; i -= 1) {
|
||||||
|
stack.push(node.children[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function giveResult(ast) {
|
function giveResult(ast) {
|
||||||
function grabSemantic(n) {
|
var addresses, groupsAndMailboxes, i, groupOrMailbox, result;
|
||||||
return n !== null ? n.semantic : null;
|
|
||||||
}
|
|
||||||
var i, ret, addresses, addr, name, aspec, local, domain;
|
|
||||||
if (ast === null) {
|
if (ast === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ret = { ast: ast };
|
addresses = [];
|
||||||
addresses = findAllNodes('address', ast);
|
|
||||||
ret.addresses = [];
|
|
||||||
for (i = 0; i < addresses.length; i += 1) {
|
|
||||||
addr = addresses[i];
|
|
||||||
name = findNode('display-name', addr);
|
|
||||||
aspec = findNode('addr-spec', addr);
|
|
||||||
local = findNode('local-part', aspec);
|
|
||||||
domain = findNode('domain', aspec);
|
|
||||||
ret.addresses.push({
|
|
||||||
node: addr,
|
|
||||||
parts: {
|
|
||||||
name: name,
|
|
||||||
address: aspec,
|
|
||||||
local: local,
|
|
||||||
domain: domain
|
|
||||||
},
|
|
||||||
name: grabSemantic(name),
|
|
||||||
address: grabSemantic(aspec),
|
|
||||||
local: grabSemantic(local),
|
|
||||||
domain: grabSemantic(domain)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.simple) {
|
// An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'.
|
||||||
ret = ret.addresses;
|
groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast);
|
||||||
for (i = 0; i < ret.length; i += 1) {
|
for (i = 0; i < groupsAndMailboxes.length; i += 1) {
|
||||||
delete ret[i].node;
|
groupOrMailbox = groupsAndMailboxes[i];
|
||||||
|
if (groupOrMailbox.name === 'group') {
|
||||||
|
addresses.push(giveResultGroup(groupOrMailbox));
|
||||||
|
} else if (groupOrMailbox.name === 'mailbox') {
|
||||||
|
addresses.push(giveResultMailbox(groupOrMailbox));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
result = {
|
||||||
|
ast: ast,
|
||||||
|
addresses: addresses,
|
||||||
|
};
|
||||||
|
if (opts.simple) {
|
||||||
|
result = simplifyResult(result);
|
||||||
|
}
|
||||||
|
if (opts.oneResult) {
|
||||||
|
return oneResult(result);
|
||||||
|
}
|
||||||
|
if (opts.simple) {
|
||||||
|
return result && result.addresses;
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function giveResultGroup(group) {
|
||||||
|
var i;
|
||||||
|
var groupName = findNode('display-name', group);
|
||||||
|
var groupResultMailboxes = [];
|
||||||
|
var mailboxes = findAllNodesNoChildren(['mailbox'], group);
|
||||||
|
for (i = 0; i < mailboxes.length; i += 1) {
|
||||||
|
groupResultMailboxes.push(giveResultMailbox(mailboxes[i]));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
node: group,
|
||||||
|
parts: {
|
||||||
|
name: groupName,
|
||||||
|
},
|
||||||
|
type: group.name, // 'group'
|
||||||
|
name: grabSemantic(groupName),
|
||||||
|
addresses: groupResultMailboxes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function giveResultMailbox(mailbox) {
|
||||||
|
var name = findNode('display-name', mailbox);
|
||||||
|
var aspec = findNode('addr-spec', mailbox);
|
||||||
|
var comments = findAllNodes('cfws', mailbox);
|
||||||
|
|
||||||
|
var local = findNode('local-part', aspec);
|
||||||
|
var domain = findNode('domain', aspec);
|
||||||
|
return {
|
||||||
|
node: mailbox,
|
||||||
|
parts: {
|
||||||
|
name: name,
|
||||||
|
address: aspec,
|
||||||
|
local: local,
|
||||||
|
domain: domain,
|
||||||
|
comments: comments
|
||||||
|
},
|
||||||
|
type: mailbox.name, // 'mailbox'
|
||||||
|
name: grabSemantic(name),
|
||||||
|
address: grabSemantic(aspec),
|
||||||
|
local: grabSemantic(local),
|
||||||
|
domain: grabSemantic(domain),
|
||||||
|
groupName: grabSemantic(mailbox.groupName),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function grabSemantic(n) {
|
||||||
|
return n !== null && n !== undefined ? n.semantic : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function simplifyResult(result) {
|
||||||
|
var i;
|
||||||
|
if (result && result.addresses) {
|
||||||
|
for (i = 0; i < result.addresses.length; i += 1) {
|
||||||
|
delete result.addresses[i].node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function oneResult(result) {
|
||||||
|
if (!result) { return null; }
|
||||||
|
if (!opts.partial && result.addresses.length > 1) { return null; }
|
||||||
|
return result.addresses && result.addresses[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|
||||||
var parseString, pos, len, parsed;
|
var parseString, pos, len, parsed, startProduction;
|
||||||
|
|
||||||
opts = handleOpts(opts, {});
|
opts = handleOpts(opts, {});
|
||||||
if (opts === null) { return null; }
|
if (opts === null) { return null; }
|
||||||
|
|
||||||
parseString = opts.input;
|
parseString = opts.input;
|
||||||
|
|
||||||
|
startProduction = {
|
||||||
|
'address': address,
|
||||||
|
'address-list': addressList,
|
||||||
|
'angle-addr': angleAddr,
|
||||||
|
'from': fromSpec,
|
||||||
|
'group': group,
|
||||||
|
'mailbox': mailbox,
|
||||||
|
'mailbox-list': mailboxList,
|
||||||
|
'reply-to': replyToSpec,
|
||||||
|
'sender': senderSpec,
|
||||||
|
}[opts.startAt] || addressList;
|
||||||
|
|
||||||
if (!opts.strict) {
|
if (!opts.strict) {
|
||||||
initialize();
|
initialize();
|
||||||
opts.strict = true;
|
opts.strict = true;
|
||||||
parsed = addressList(parseString);
|
parsed = startProduction(parseString);
|
||||||
if (opts.partial || !inStr()) {
|
if (opts.partial || !inStr()) {
|
||||||
return giveResult(parsed);
|
return giveResult(parsed);
|
||||||
}
|
}
|
||||||
|
@ -859,46 +967,51 @@ function parse5322(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
parsed = addressList(parseString);
|
parsed = startProduction(parseString);
|
||||||
if (!opts.partial && inStr()) { return null; }
|
if (!opts.partial && inStr()) { return null; }
|
||||||
return giveResult(parsed);
|
return giveResult(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseOneAddressSimple(opts) {
|
function parseOneAddressSimple(opts) {
|
||||||
var result;
|
return parse5322(handleOpts(opts, {
|
||||||
|
oneResult: true,
|
||||||
opts = handleOpts(opts, {
|
|
||||||
rfc6532: true,
|
rfc6532: true,
|
||||||
simple: true
|
simple: true,
|
||||||
});
|
startAt: 'address-list',
|
||||||
if (opts === null) { return null; }
|
}));
|
||||||
|
|
||||||
result = parse5322(opts);
|
|
||||||
|
|
||||||
if ((!result) ||
|
|
||||||
(!opts.partial &&
|
|
||||||
(opts.simple && result.length > 1) ||
|
|
||||||
(!opts.simple && result.addresses.length > 1))) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return opts.simple ?
|
|
||||||
result && result[0] :
|
|
||||||
result && result.addresses && result.addresses[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseAddressListSimple(opts) {
|
function parseAddressListSimple(opts) {
|
||||||
var result;
|
return parse5322(handleOpts(opts, {
|
||||||
|
|
||||||
opts = handleOpts(opts, {
|
|
||||||
rfc6532: true,
|
rfc6532: true,
|
||||||
simple: true
|
simple: true,
|
||||||
});
|
startAt: 'address-list',
|
||||||
if (opts === null) { return null; }
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
result = parse5322(opts);
|
function parseFromSimple(opts) {
|
||||||
|
return parse5322(handleOpts(opts, {
|
||||||
|
rfc6532: true,
|
||||||
|
simple: true,
|
||||||
|
startAt: 'from',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return opts.simple ? result : result.addresses;
|
function parseSenderSimple(opts) {
|
||||||
|
return parse5322(handleOpts(opts, {
|
||||||
|
oneResult: true,
|
||||||
|
rfc6532: true,
|
||||||
|
simple: true,
|
||||||
|
startAt: 'sender',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseReplyToSimple(opts) {
|
||||||
|
return parse5322(handleOpts(opts, {
|
||||||
|
rfc6532: true,
|
||||||
|
simple: true,
|
||||||
|
startAt: 'reply-to',
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleOpts(opts, defs) {
|
function handleOpts(opts, defs) {
|
||||||
|
@ -926,24 +1039,28 @@ function handleOpts(opts, defs) {
|
||||||
if (!defs) { return null; }
|
if (!defs) { return null; }
|
||||||
|
|
||||||
defaults = {
|
defaults = {
|
||||||
rfc6532: false,
|
oneResult: false,
|
||||||
partial: false,
|
partial: false,
|
||||||
|
rejectTLD: false,
|
||||||
|
rfc6532: false,
|
||||||
simple: false,
|
simple: false,
|
||||||
|
startAt: 'address-list',
|
||||||
strict: false,
|
strict: false,
|
||||||
rejectTLD: false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (o in defaults) {
|
for (o in defaults) {
|
||||||
if (isNullUndef(opts[o])) {
|
if (isNullUndef(opts[o])) {
|
||||||
opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o];
|
opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o];
|
||||||
}
|
}
|
||||||
opts[o] = !!opts[o];
|
|
||||||
}
|
}
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse5322.parseOneAddress = parseOneAddressSimple;
|
parse5322.parseOneAddress = parseOneAddressSimple;
|
||||||
parse5322.parseAddressList = parseAddressListSimple;
|
parse5322.parseAddressList = parseAddressListSimple;
|
||||||
|
parse5322.parseFrom = parseFromSimple;
|
||||||
|
parse5322.parseSender = parseSenderSimple;
|
||||||
|
parse5322.parseReplyTo = parseReplyToSimple;
|
||||||
|
|
||||||
// in Zammad context, go back to non CommonJS
|
// in Zammad context, go back to non CommonJS
|
||||||
// if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
// if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
||||||
|
|
|
@ -1982,34 +1982,106 @@ test('check getRecipientArticle format', function() {
|
||||||
lastname: 'lastname',
|
lastname: 'lastname',
|
||||||
email: 'customer@example.com',
|
email: 'customer@example.com',
|
||||||
}
|
}
|
||||||
agent = {
|
|
||||||
login: 'login',
|
|
||||||
firstname: 'firstname',
|
|
||||||
lastname: 'lastname',
|
|
||||||
email: 'agent@example.com',
|
|
||||||
}
|
|
||||||
ticket = {
|
ticket = {
|
||||||
customer: customer,
|
customer: customer,
|
||||||
}
|
}
|
||||||
article = {
|
article = {
|
||||||
message_id: 'message_id7',
|
message_id: 'message_id7',
|
||||||
created_by: agent,
|
|
||||||
type: {
|
type: {
|
||||||
name: 'email',
|
name: 'email',
|
||||||
},
|
},
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Agent',
|
name: 'Customer',
|
||||||
},
|
},
|
||||||
from: 'customer2@example.com',
|
from: 'some other invalid part, ' + customer.email,
|
||||||
to: 'customer@example.com',
|
to: 'some group',
|
||||||
|
created_by: {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'article_created_by@example.com',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer2@example.com',
|
to: 'customer@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id7',
|
in_reply_to: 'message_id7',
|
||||||
}
|
}
|
||||||
verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
|
verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
|
||||||
|
console.log(verify)
|
||||||
|
deepEqual(verify, result)
|
||||||
|
|
||||||
|
customer = {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'customer@example.com',
|
||||||
|
}
|
||||||
|
ticket = {
|
||||||
|
customer: customer,
|
||||||
|
}
|
||||||
|
article = {
|
||||||
|
message_id: 'message_id7.1',
|
||||||
|
type: {
|
||||||
|
name: 'email',
|
||||||
|
},
|
||||||
|
sender: {
|
||||||
|
name: 'Customer',
|
||||||
|
},
|
||||||
|
from: 'some other invalid part, Some Realname ' + customer.email,
|
||||||
|
to: 'some group',
|
||||||
|
created_by: {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'article_created_by@example.com',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = {
|
||||||
|
to: 'customer@example.com',
|
||||||
|
cc: '',
|
||||||
|
body: '',
|
||||||
|
in_reply_to: 'message_id7.1',
|
||||||
|
}
|
||||||
|
verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
|
||||||
|
console.log(verify)
|
||||||
|
deepEqual(verify, result)
|
||||||
|
|
||||||
|
customer = {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'customer@example.com',
|
||||||
|
}
|
||||||
|
ticket = {
|
||||||
|
customer: customer,
|
||||||
|
}
|
||||||
|
article = {
|
||||||
|
message_id: 'message_id7.2',
|
||||||
|
type: {
|
||||||
|
name: 'email',
|
||||||
|
},
|
||||||
|
sender: {
|
||||||
|
name: 'Customer',
|
||||||
|
},
|
||||||
|
from: 'some other invalid part, Some Realname ' + customer.email + ' , abc',
|
||||||
|
to: 'some group',
|
||||||
|
created_by: {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'article_created_by@example.com',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = {
|
||||||
|
to: 'customer@example.com',
|
||||||
|
cc: '',
|
||||||
|
body: '',
|
||||||
|
in_reply_to: 'message_id7.2',
|
||||||
|
}
|
||||||
|
verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
|
||||||
|
console.log(verify)
|
||||||
deepEqual(verify, result)
|
deepEqual(verify, result)
|
||||||
|
|
||||||
customer = {
|
customer = {
|
||||||
|
@ -2036,11 +2108,11 @@ test('check getRecipientArticle format', function() {
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'agent@example.com',
|
from: 'customer2@example.com',
|
||||||
to: 'customer@example.com',
|
to: 'customer@example.com',
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer@example.com',
|
to: 'customer2@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id8',
|
in_reply_to: 'message_id8',
|
||||||
|
@ -2072,9 +2144,8 @@ test('check getRecipientArticle format', function() {
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'Agent@Example.com',
|
from: 'agent@example.com',
|
||||||
to: 'customer@example.com',
|
to: 'customer@example.com',
|
||||||
cc: 'zammad@example.com',
|
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer@example.com',
|
to: 'customer@example.com',
|
||||||
|
@ -2110,16 +2181,16 @@ test('check getRecipientArticle format', function() {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'Agent@Example.com',
|
from: 'Agent@Example.com',
|
||||||
to: 'customer@example.com, agent@example.com',
|
to: 'customer@example.com',
|
||||||
cc: 'zammad@example.com',
|
cc: 'zammad@example.com',
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer@example.com, agent@example.com',
|
to: 'customer@example.com',
|
||||||
cc: 'zammad@example.com',
|
cc: '',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id10',
|
in_reply_to: 'message_id10',
|
||||||
}
|
}
|
||||||
verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, [], true)
|
verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
|
||||||
deepEqual(verify, result)
|
deepEqual(verify, result)
|
||||||
|
|
||||||
customer = {
|
customer = {
|
||||||
|
@ -2147,8 +2218,8 @@ test('check getRecipientArticle format', function() {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'Agent@Example.com',
|
from: 'Agent@Example.com',
|
||||||
to: 'customeR@EXAMPLE.com, agent@example.com',
|
to: 'customer@example.com, agent@example.com',
|
||||||
cc: 'zammad@example.com, customer@example.com',
|
cc: 'zammad@example.com',
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer@example.com, agent@example.com',
|
to: 'customer@example.com, agent@example.com',
|
||||||
|
@ -2156,7 +2227,7 @@ test('check getRecipientArticle format', function() {
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id11',
|
in_reply_to: 'message_id11',
|
||||||
}
|
}
|
||||||
verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, [], true)
|
verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, [], true)
|
||||||
deepEqual(verify, result)
|
deepEqual(verify, result)
|
||||||
|
|
||||||
customer = {
|
customer = {
|
||||||
|
@ -2184,24 +2255,16 @@ test('check getRecipientArticle format', function() {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'Agent@Example.com',
|
from: 'Agent@Example.com',
|
||||||
to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
|
to: 'customeR@EXAMPLE.com, agent@example.com',
|
||||||
cc: 'zammad@example.com, customer2@example.com',
|
cc: 'zammad@example.com, customer@example.com',
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer@example.com, agent@example.com',
|
to: 'customer@example.com, agent@example.com',
|
||||||
cc: 'customer2@example.com',
|
cc: 'zammad@example.com',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id12',
|
in_reply_to: 'message_id12',
|
||||||
}
|
}
|
||||||
email_addresses = [
|
verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, [], true)
|
||||||
{
|
|
||||||
email: 'zammad@example.com',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
email: 'zammad2@example.com',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
|
|
||||||
deepEqual(verify, result)
|
deepEqual(verify, result)
|
||||||
|
|
||||||
customer = {
|
customer = {
|
||||||
|
@ -2214,7 +2277,7 @@ test('check getRecipientArticle format', function() {
|
||||||
login: 'login',
|
login: 'login',
|
||||||
firstname: 'firstname',
|
firstname: 'firstname',
|
||||||
lastname: 'lastname',
|
lastname: 'lastname',
|
||||||
email: 'AGENT@example.com',
|
email: 'agent@example.com',
|
||||||
}
|
}
|
||||||
ticket = {
|
ticket = {
|
||||||
customer: customer,
|
customer: customer,
|
||||||
|
@ -2253,21 +2316,27 @@ test('check getRecipientArticle format', function() {
|
||||||
login: 'login',
|
login: 'login',
|
||||||
firstname: 'firstname',
|
firstname: 'firstname',
|
||||||
lastname: 'lastname',
|
lastname: 'lastname',
|
||||||
email: 'zammad@example.com',
|
email: 'customer@example.com',
|
||||||
|
}
|
||||||
|
agent = {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'AGENT@example.com',
|
||||||
}
|
}
|
||||||
ticket = {
|
ticket = {
|
||||||
customer: customer,
|
customer: customer,
|
||||||
}
|
}
|
||||||
article = {
|
article = {
|
||||||
message_id: 'message_id14',
|
message_id: 'message_id14',
|
||||||
created_by: customer,
|
created_by: agent,
|
||||||
type: {
|
type: {
|
||||||
name: 'email',
|
name: 'email',
|
||||||
},
|
},
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'zammad@EXAMPLE.com',
|
from: 'Agent@Example.com',
|
||||||
to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
|
to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
|
||||||
cc: 'zammad@example.com, customer2@example.com',
|
cc: 'zammad@example.com, customer2@example.com',
|
||||||
}
|
}
|
||||||
|
@ -2292,7 +2361,7 @@ test('check getRecipientArticle format', function() {
|
||||||
login: 'login',
|
login: 'login',
|
||||||
firstname: 'firstname',
|
firstname: 'firstname',
|
||||||
lastname: 'lastname',
|
lastname: 'lastname',
|
||||||
email: 'customer@example.com',
|
email: 'zammad@example.com',
|
||||||
}
|
}
|
||||||
ticket = {
|
ticket = {
|
||||||
customer: customer,
|
customer: customer,
|
||||||
|
@ -2306,13 +2375,13 @@ test('check getRecipientArticle format', function() {
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'customer@example.com',
|
from: 'zammad@EXAMPLE.com',
|
||||||
to: 'customer1@example.com, customer2@example.com, zammad@example.com',
|
to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
|
||||||
cc: '',
|
cc: 'zammad@example.com, customer2@example.com',
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer1@example.com, customer2@example.com, customer@example.com',
|
to: 'customer@example.com, agent@example.com',
|
||||||
cc: '',
|
cc: 'customer2@example.com',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id15',
|
in_reply_to: 'message_id15',
|
||||||
}
|
}
|
||||||
|
@ -2346,11 +2415,11 @@ test('check getRecipientArticle format', function() {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'customer@example.com',
|
from: 'customer@example.com',
|
||||||
to: 'customer1@example.com, customer2@example.com, zammad@example.com, customer2+2@example.com',
|
to: 'customer1@example.com, customer2@example.com, zammad@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer1@example.com, customer2@example.com, customer2+2@example.com, customer@example.com',
|
to: 'customer1@example.com, customer2@example.com, customer@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id16',
|
in_reply_to: 'message_id16',
|
||||||
|
@ -2372,30 +2441,24 @@ test('check getRecipientArticle format', function() {
|
||||||
lastname: 'lastname',
|
lastname: 'lastname',
|
||||||
email: 'customer@example.com',
|
email: 'customer@example.com',
|
||||||
}
|
}
|
||||||
agent = {
|
|
||||||
login: 'login',
|
|
||||||
firstname: 'firstname',
|
|
||||||
lastname: 'lastname',
|
|
||||||
email: 'zammad@example.com',
|
|
||||||
}
|
|
||||||
ticket = {
|
ticket = {
|
||||||
customer: customer,
|
customer: customer,
|
||||||
}
|
}
|
||||||
article = {
|
article = {
|
||||||
message_id: 'message_id17',
|
message_id: 'message_id17',
|
||||||
created_by: agent,
|
created_by: customer,
|
||||||
type: {
|
type: {
|
||||||
name: 'email',
|
name: 'email',
|
||||||
},
|
},
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
from: 'zammad@example.com',
|
from: 'customer@example.com',
|
||||||
to: 'customer@example.com',
|
to: 'customer1@example.com, customer2@example.com, zammad@example.com, customer2+2@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
}
|
}
|
||||||
result = {
|
result = {
|
||||||
to: 'customer@example.com',
|
to: 'customer1@example.com, customer2@example.com, customer2+2@example.com, customer@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id17',
|
in_reply_to: 'message_id17',
|
||||||
|
@ -2435,6 +2498,51 @@ test('check getRecipientArticle format', function() {
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Agent',
|
name: 'Agent',
|
||||||
},
|
},
|
||||||
|
from: 'zammad@example.com',
|
||||||
|
to: 'customer@example.com',
|
||||||
|
cc: '',
|
||||||
|
}
|
||||||
|
result = {
|
||||||
|
to: 'customer@example.com',
|
||||||
|
cc: '',
|
||||||
|
body: '',
|
||||||
|
in_reply_to: 'message_id18',
|
||||||
|
}
|
||||||
|
email_addresses = [
|
||||||
|
{
|
||||||
|
email: 'zammad@example.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email: 'zammad2@example.com',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
|
||||||
|
deepEqual(verify, result)
|
||||||
|
|
||||||
|
customer = {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'customer@example.com',
|
||||||
|
}
|
||||||
|
agent = {
|
||||||
|
login: 'login',
|
||||||
|
firstname: 'firstname',
|
||||||
|
lastname: 'lastname',
|
||||||
|
email: 'zammad@example.com',
|
||||||
|
}
|
||||||
|
ticket = {
|
||||||
|
customer: customer,
|
||||||
|
}
|
||||||
|
article = {
|
||||||
|
message_id: 'message_id19',
|
||||||
|
created_by: agent,
|
||||||
|
type: {
|
||||||
|
name: 'email',
|
||||||
|
},
|
||||||
|
sender: {
|
||||||
|
name: 'Agent',
|
||||||
|
},
|
||||||
from: 'Sender <zammad@example.com>',
|
from: 'Sender <zammad@example.com>',
|
||||||
to: 'Customer <customer@example.com>',
|
to: 'Customer <customer@example.com>',
|
||||||
cc: '',
|
cc: '',
|
||||||
|
@ -2443,7 +2551,7 @@ test('check getRecipientArticle format', function() {
|
||||||
to: 'customer@example.com',
|
to: 'customer@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id18',
|
in_reply_to: 'message_id19',
|
||||||
}
|
}
|
||||||
email_addresses = [
|
email_addresses = [
|
||||||
{
|
{
|
||||||
|
@ -2466,7 +2574,7 @@ test('check getRecipientArticle format', function() {
|
||||||
customer: agent,
|
customer: agent,
|
||||||
}
|
}
|
||||||
article = {
|
article = {
|
||||||
message_id: 'message_id19',
|
message_id: 'message_id20',
|
||||||
created_by: agent,
|
created_by: agent,
|
||||||
type: {
|
type: {
|
||||||
name: 'email',
|
name: 'email',
|
||||||
|
@ -2482,7 +2590,7 @@ test('check getRecipientArticle format', function() {
|
||||||
to: 'agent@example.com',
|
to: 'agent@example.com',
|
||||||
cc: '',
|
cc: '',
|
||||||
body: '',
|
body: '',
|
||||||
in_reply_to: 'message_id19',
|
in_reply_to: 'message_id20',
|
||||||
}
|
}
|
||||||
email_addresses = [
|
email_addresses = [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue