node-red-nodes/social/email/61-email.html
wooferguy de40c4b817 XOAUTH2 IMAP
Minor UI changes. Exposing only XOAuth2. Picks up raw access token from input message specified.

Only works for IMAP
Token formatted by node for Exchange and GMail, won't work on other providers.
Only works on trigger, not timer

TODO:
Add POP XOAUTH2 capability
Add SMTP XOAUTH2 capability
Add option to pass SASL XAOUTH2 token rather than raw OAUTH2 token
2023-02-09 14:58:25 +13:00

530 lines
24 KiB
HTML

<script type="text/html" data-template-name="e-mail">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-envelope"></i> <span data-i18n="email.label.to"></span></label>
<input type="text" id="node-input-name" placeholder="email@address.com">
</div>
<!-- <div class="form-row">
<label for="node-input-pin"><i class="fa fa-asterisk"></i> Service</label>
<select type="text" id="node-input-pin" style="width: 150px;">
<option value="-" disabled> </option>
<option value="DynectEmail">DynectEmail</option>
<option value="Gmail">Gmail</option>
<option value="hot.ee">hot.ee</option>
<option value="Hotmail">Hotmail</option>
<option value="iCloud">iCloud</option>
<option value="mail.ee">mail.ee</option>
<option value="Mail.Ru">Mail.Ru</option>
<option value="Mailgun">Mailgun</option>
<option value="Mailjet">Mailjet</option>
<option value="Mandrill">Mandrill</option>
<option value="Postmark">Postmark</option>
<option value="QQ">QQ</option>
<option value="QQex">QQex</option>
<option value="SendGrid">SendGrid</option>
<option value="SendCloud">SendCloud</option>
<option value="SES">SES</option>
<option value="Yahoo">Yahoo</option>
<option value="yandex">yandex</option>
<option value="Zoho">Zoho</option>
</select>
</div> -->
<div class="form-row">
<label for="node-input-server"><i class="fa fa-globe"></i> <span data-i18n="email.label.server"></span></label>
<input type="text" id="node-input-server" placeholder="smtp.gmail.com">
</div>
<div class="form-row">
<label for="node-input-port"><i class="fa fa-random"></i> <span data-i18n="email.label.port"></span></label>
<input type="text" id="node-input-port" placeholder="465" style="width:100px">
<label style="width:40px"> </label>
<input type="checkbox" id="node-input-secure" style="display:inline-block; width:20px; vertical-align:baseline;">
<span data-i18n="email.label.useSecureConnection"></span>
</div>
<div class="form-row">
<label for="node-input-userid"><i class="fa fa-user"></i> <span data-i18n="email.label.userid"></span></label>
<input type="text" id="node-input-userid">
</div>
<div class="form-row">
<label for="node-input-password"><i class="fa fa-lock"></i> <span data-i18n="email.label.password"></span></label>
<input type="password" id="node-input-password">
</div>
<br/>
<div class="form-row">
<label for="node-input-useTLS"><i class="fa fa-lock"></i> <span data-i18n="email.label.useTLS"></label>
<input type="checkbox" id="node-input-tls" style="display:inline-block; width:20px; vertical-align:baseline;">
<span data-i18n="email.label.rejectUnauthorised"></span>
</div>
<div class="form-row">
<label for="node-input-dname"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-dname" data-i18n="[placeholder]node-red:common.label.name">
</div>
<div class="form-tips" id="node-tip"><span data-i18n="[html]email.tip.cred"></span></div>
</script>
<script type="text/javascript">
(function() {
RED.nodes.registerType('e-mail',{
category: 'social-output',
color:"#c7e9c0",
defaults: {
server: {value:"smtp.gmail.com",required:true},
port: {value:"465",required:true},
secure: {value: true},
tls: {value: true},
name: {value:""},
dname: {value:""}
},
credentials: {
userid: {type:"text"},
password: {type: "password"},
global: { type:"boolean"}
},
inputs:1,
outputs:0,
icon: "envelope.png",
align: "right",
paletteLabel: function() {
return this._("email.email");
},
label: function() {
return this.dname||this.name||this._("email.email");
},
labelStyle: function() {
return (this.dname)?"node_label_italic":"";
},
oneditprepare: function() {
if (this.credentials.global) {
$('#node-tip').show();
} else {
$('#node-tip').hide();
}
}
});
})();
</script>
<script type="text/html" data-template-name="e-mail in">
<div class="form-row">
<label for="node-input-fetch"><i class="fa fa-hourglass-half"></i> <span data-i18n="email.label.getmail"></span></label>
<select type="text" id="node-input-fetch" style="width:130px;">
<option value="auto" data-i18n="email.label.auto"></option>
<option value="trigger" data-i18n="email.label.trigger"></option>
</select>
<span id="node-repeatTime">
<span style="margin-left:20px;" data-i18n="email.label.repeat"></span>
<input type="text" id="node-input-repeat" style="width:80px"> <span data-i18n="email.label.seconds">seconds</span>
</span>
</div>
<div class="form-row">
<label for="node-input-protocol"><i class="fa fa-envelope"></i> <span data-i18n="email.label.protocol"></span></label>
<select type="text" id="node-input-protocol">
<option value="IMAP">IMAP</option>
<option value="POP3">POP3</option>
</select>
</div>
<div class="form-row">
<label for="node-input-useSSL"><i class="fa fa-lock"></i> <span data-i18n="email.label.useSSL"></span></label>
<input type="checkbox" id="node-input-useSSL" style="width: auto;">
</div>
<div class="form-row">
<label for="node-input-autotls"><i class="fa fa-lock"></i> <span data-i18n="email.label.autotls"></label>
<select type="text" id="node-input-autotls" style="width: 150px;">
<option value="never" data-i18n="email.label.never"></option>
<option value="required" data-i18n="email.label.required"></option>
<option value="always" data-i18n="email.label.always"></option>
</select>
</div>
<div class="form-row">
<label for="node-input-server"><i class="fa fa-globe"></i> <span data-i18n="email.label.server"></span></label>
<input type="text" id="node-input-server" placeholder="imap.gmail.com">
</div>
<div class="form-row">
<label for="node-input-port"><i class="fa fa-random"></i> <span data-i18n="email.label.port"></span></label>
<input type="text" id="node-input-port" placeholder="993">
</div>
<div class="form-row">
<label for="node-input-authtype"><i class="fa fa-tasks"></i> <span data-i18n="email.label.authtype"></span></label>
<select type="text" id="node-input-authtype">
<option value="BASIC">Basic</option>
<option value="XOAUTH2">XOAuth2</option>
</select>
</div>
<div class="form-row node-input-userid">
<label for="node-input-userid"><i class="fa fa-user"></i> <span data-i18n="email.label.userid"></span></label>
<input type="text" id="node-input-userid">
</div>
<div class="form-row node-input-password">
<label for="node-input-password"><i class="fa fa-lock"></i> <span data-i18n="email.label.password"></span></label>
<input type="password" id="node-input-password">
</div>
<div class="form-row node-input-token" style="display: none;">
<label for="node-input-token"><i class="fa fa-lock"></i> <span data-i18n="email.label.token"></span></label>
<input type="text" id="node-input-token" placeholder="oauth2Response.access_token">
</div>
<div class="form-row node-input-box">
<label for="node-input-box"><i class="fa fa-inbox"></i> <span data-i18n="email.label.folder"></span></label>
<input type="text" id="node-input-box">
</div>
<div class="form-row node-input-disposition">
<label for="node-input-disposition"><i class="fa fa-trash"></i> <span data-i18n="email.label.disposition"></span></label>
<select type="text" id="node-input-disposition">
<option value="None" selected="selected" data-i18n="email.label.none"></option>
<option value="Read" data-i18n="email.label.read"></option>
<option value="Delete" data-i18n="email.label.delete"></option>
</select>
</div>
<div class="form-row">
<label for="node-input-criteria"><i class="fa fa-search"></i> <span data-i18n="email.label.criteria"></span></label>
<select type="text" id="node-input-criteria">
<option value="ALL" data-i18n="email.label.all"></option>
<option value="ANSWERED" data-i18n="email.label.answered"></option>
<option value="FLAGGED" data-i18n="email.label.flagged"></option>
<option value="SEEN" data-i18n="email.label.seen"></option>
<option value="UNANSWERED" data-i18n="email.label.unanswered"></option>
<option value="UNFLAGGED" data-i18n="email.label.unflagged"></option>
<option value="UNSEEN" selected="selected" data-i18n="email.label.unseen"></option>
<option value="_msg_" data-i18n="email.label.criteriaFromMsg"></option>
<!--
<option value="DELETED" data-i18n="email.label.delete"></option>
<option value="DRAFT" data-i18n="email.label.none"></option>
<option value="NEW" data-i18n="email.label.delete"></option>
<option value="UNDELETED" data-i18n="email.label.read"></option>
<option value="UNDRAFT" data-i18n="email.label.delete"></option>
<option value="RECENT" data-i18n="email.label.read"></option>
<option value="OLD" data-i18n="email.label.delete"></option>
-->
</select>
</div>
<br/>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
<script>
var checkPorts = function() {
var currentPort = $("#node-input-port").val();
if (currentPort === "143" || currentPort === "993" || currentPort === "110" || currentPort == "995") {
if ($("#node-input-useSSL").prop("checked") === true) {
$("#node-input-port").val($("#node-input-protocol").val() === "IMAP"?"993":"995");
} else {
$("#node-input-port").val($("#node-input-protocol").val() === "IMAP"?"143":"110");
}
}
};
$("#node-input-useSSL").change(function(x, y) {
// console.log("useSSL: x="+ JSON.stringify(x) + ", y=" + y);
// console.log("Value: " + $("#node-input-useSSL").prop("checked"));
checkPorts();
});
$("#node-input-protocol").change(function() {
var protocol = $("#node-input-protocol").val();
if (protocol === "IMAP") {
$(".node-input-autotls").show();
$(".node-input-box").show();
$(".node-input-disposition").show();
$(".node-input-criteria").show();
} else {
$(".node-input-autotls").hide();
$(".node-input-box").hide();
$(".node-input-disposition").hide();
$(".node-input-criteria").hide();
}
checkPorts();
});
$("#node-input-authtype").change(function() {
var protocol = $("#node-input-authtype").val();
if (protocol === "BASIC") {
$(".node-input-password").show();
$(".node-input-token").hide();
} else {
$(".node-input-password").hide();
$(".node-input-token").show();
}
});
</script>
</script>
<script type="text/javascript">
(function() {
RED.nodes.registerType('e-mail in',{
category: 'social-input',
color:"#c7e9c0",
defaults: {
name: {value:""},
protocol: {value: "IMAP", required:true}, // Which protocol to use to connect to the mail server ("IMAP" or "POP3")
server: {value:"imap.gmail.com",required:true},
useSSL: {value: true},
autotls: {value: "never"},
port: {value:"993",required:true},
authtype: {value: "BASIC"},
token: {value: "oauth2Response.access_token"},
box: {value:"INBOX"}, // For IMAP, The mailbox to process
disposition: { value: "Read" }, // For IMAP, the disposition of the read email
criteria: {value: "UNSEEN"},
repeat: {value:"300",required:true},
fetch: {value:"auto"},
inputs: {value:0}
},
credentials: {
userid: {type:"text"},
password: {type: "password"},
global: { type:"boolean"}
},
inputs: 0,
outputs: 1,
icon: "envelope.png",
paletteLabel: function() {
return this._("email.email");
},
label: function() {
return this.name||this._("email.email");
},
labelStyle: function() {
return (this.name)?"node_label_italic":"";
},
oneditprepare: function() {
var that = this;
if (this.credentials.global) {
$('#node-tip').show();
} else {
$('#node-tip').hide();
}
if (typeof this.box === 'undefined') {
$("#node-input-box").val("INBOX");
this.box = "INBOX";
}
if (typeof this.criteria === 'undefined') {
$("#node-input-criteria").val("UNSEEN");
this.criteria = "UNSEEN";
}
if (typeof this.autotls === 'undefined') {
$("#node-input-autotls").val("never");
this.autotls = "never";
}
if ($("#node-input-fetch").val() === null) { $("#node-input-fetch").val("auto"); }
$("#node-input-fetch").change(function() {
if ($("#node-input-fetch").val() === "trigger") {
$('#node-repeatTime').hide();
that.inputs = 1;
}
else {
$('#node-repeatTime').show();
that.inputs = 0;
}
});
$("#node-input-criteria").change(function() {
if ($("#node-input-criteria").val() === "_msg_") {
$("#node-input-fetch").val("trigger");
$("#node-input-fetch").change();
}
});
$("#node-input-token").typedInput({
type:'msg',
types:['msg']
});
}
});
})();
</script>
<script type="text/html" data-template-name="e-mail mta">
<div class="form-row">
<label for="node-input-port"><i class="fa fa-random"></i> <span data-i18n="email.label.port"></span></label>
<input type="text" id="node-input-port" style="width:100px">
<label style="width:40px"> </label>
<input type="checkbox" id="node-input-secure" style="display:inline-block; width:20px; vertical-align:baseline;">
<span data-i18n="email.label.enableSecure"></span>
</div>
<div class="form-row">
<label for="node-input-starttls"><i class="fa fa-lock"></i> <span data-i18n="email.label.enableStarttls"></span></label>
<input type="checkbox" id="node-input-starttls" style="display:inline-block; width:20px; vertical-align:baseline;">
<span data-i18n="email.label.starttlsUpgrade"></span>
</div>
<div class="form-row" id="certRow">
<label for="node-input-certFile"><i class="fa fa-file"></i>
<span data-i18n="email.label.certFile"></span></label>
<input type="text" id="node-input-certFile" placeholder="server.crt" style="width:100%">
</div>
<div class="form-row" id="keyRow">
<label for="node-input-keyFile"><i class="fa fa-key"></i>
<span data-i18n="email.label.keyFile"></span></label>
<input type="text" id="node-input-keyFile" placeholder="private.key" style="width:100%">
</div>
<div class="form-row">
<label for="node-input-auth"><i class="fa fa-user"></i> <span data-i18n="email.label.users"></span></label>
<input type="checkbox" id="node-input-auth" style="display:inline-block; width:20px; vertical-align:baseline;">
<span data-i18n="email.label.auth"></span>
</div>
<div class="form-row node-input-email-users-container-row" style="margin-bottom: 0px;">
<div id="node-input-email-users-container-div" style="box-sizing: border-box; border-radius: 5px;
height: 200px; padding: 5px; border: 1px solid #ccc; overflow-y:scroll;">
<ol id="node-input-email-users-container" style="list-style-type:none; margin: 0;"></ol>
</div>
</div>
<div class="form-row">
<a href="#" class="editor-button editor-button-small" id="node-input-email-users-add" style="margin-top: 4px;">
<i class="fa fa-plus"></i>
<span data-i18n="email.label.addButton"></span>
</a>
</div>
<div class="form-row">
<label for="node-input-expert"><i class="fa fa-cog"></i> <span data-i18n="email.label.expert"></span></label>
<input type="text" id="node-input-expert">
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
<div class="form-tips" id="node-tip"><span data-i18n="[html]email.tip.mta"></span></div>
</script>
<script type="text/javascript">
RED.nodes.registerType('e-mail mta', {
category: 'social',
color: "#c7e9c0",
defaults: {
name: { value: "" },
port: { value: "1025", required: true, validate: RED.validators.number() },
secure: { value: false },
starttls: { value: false },
certFile: { value: "" },
keyFile: { value: "" },
users: { value: [] },
auth: { value: false },
expert: { value: '{"logger":false}' }
},
inputs: 0,
outputs: 1,
icon: "envelope.png",
paletteLabel: function () { return this._("email.email") + " MTA" },
label: function () {
return this.name || this._("email.email") + " MTA";
},
labelStyle: function () {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function () {
let node = this;
// Certificate settings
$("#node-input-secure").change(secVisibility);
$("#node-input-starttls").change(secVisibility);
function secVisibility() {
if ($("#node-input-secure").is(":checked") || $("#node-input-starttls").is(":checked")) {
$("#certRow").show();
$("#keyRow").show();
} else {
$("#certRow").hide();
$("#keyRow").hide();
}
}
// User Management
let cacheItemCount = 0;
if (node.users && node.users.length > 0) {
cacheItemCount = node.users.length;
node.users.forEach(function (element, index, array) {
generateUserEntry(element, index);
});
}
function generateUserEntry(user, id) {
let container = $("<li/>", {
style: "background: #fefefe; margin:0; padding:8px 0px; border-bottom: 1px solid #ccc;"
});
let row = $('<div id="row' + id + '"/>').appendTo(container);
$('<i style="color: #eee; cursor: move;" class="node-input-email-users-handle fa fa-bars"></i>').appendTo(row);
let userField = $("<input/>", {
id: "node-input-email-users-name" + id,
class: "userName",
type: "text",
style: "margin-left:5px;width:100px;",
placeholder: "name"
}).appendTo(row);
let passwordField = $("<input/>", {
id: "node-input-email-users-password" + id,
class: "userPassword",
type: "password",
style: "margin: 0 auto;width:50%;min-width:20px;margin-left:5px",
placeholder: "password"
}).appendTo(row);
userField.val(user.name);
passwordField.val(user.password);
let finalspan = $("<span/>", {
style: "float: right;margin-right: 10px;"
}).appendTo(row);
let removeUserButton = $("<a/>", {
href: "#",
id: "node-button-user-remove" + id,
class: "editor-button editor-button-small",
style: "margin-top: 7px; margin-left: 5px;"
}).appendTo(finalspan);
$("<i/>", { class: "fa fa-remove" }).appendTo(removeUserButton);
removeUserButton.click(function () {
container.css({ background: "#fee" });
container.fadeOut(300, function () {
$(this).remove();
});
});
$("#node-input-email-users-container").append(container);
}
$("#node-input-email-users-container").sortable({
axis: "y",
handle: ".node-input-email-users-handle",
cursor: "move"
});
$("#node-input-email-users-container .node-input-email-users-handle").disableSelection();
$("#node-input-email-users-add").click(function () {
if (!cacheItemCount || cacheItemCount < 0) {
cacheItemCount = 0;
}
generateUserEntry({ name: "", password: "" }, cacheItemCount++);
$("#node-input-email-users-container-div").scrollTop(
$("#node-input-email-users-container-div").get(0).scrollHeight
);
});
$("#node-input-auth").change(function () {
if ($("#node-input-auth").is(":checked")) {
$("#node-input-email-users-add").show();
$("#node-input-email-users-container-div").show();
} else {
$("#node-input-email-users-add").hide();
$("#node-input-email-users-container-div").hide();
}
});
// Expert settings
$("#node-input-expert").typedInput({
type: "json",
types: ["json"]
})
},
oneditsave: function () {
let node = this;
let cacheUsers = $("#node-input-email-users-container").children();
node.users = [];
cacheUsers.each(function () {
node.users.push({
name: $(this)
.find(".userName")
.val(),
password: $(this)
.find(".userPassword")
.val()
});
});
}
});
</script>