postmailer
Version:
HTTP POST -> SMTP proxy, as Express middleware
378 lines (323 loc) • 14.2 kB
HTML
<html>
<head>
<title>POST for {{name}}</title>
<style>
body {
max-width: 800px;
margin: auto;
font-family: 'Open Sans', Tahoma;
font-size: 11pt;
color: #111;
}
h1 {
font-size: 1.5em;
margin: 0.5em 0;
text-align: center;
}
h2 {
font-size: 1.2em;
margin: 1em 0em;
}
code {
display: inline-block;
padding: 0.3em 0.3em 0.1em 0.3em;
background-color: #EEE;
border-radius: 0.3em;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
box-shadow: 0px 1px #DDD;
}
pre {
margin: 0.5em 2em;
padding: 0;
font-size: inherit;
}
pre code {
display: block;
width: 100%;
overflow: auto;
}
.cmd-option {
color: #048;
}
.cmd-value {
color: #800;
}
.cmd-value-file {
color: #482;
}
.headers, .text, .email {
width: 100%;
padding: 0.5em 0em;
background-color: #FFF;
border: none;
border-top: 1px solid #DDD;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
box-shadow: 0px 1px #DDD;
font-size: inherit;
height: 5em;
}
.send {
width: 100%;
height: 2em;
padding:0;
color: #000;
background-color: #EEE;
border: 1px solid #DDD;
border-radius: 0.3em;
font-family: inherit;
font-size: inherit;
box-shadow: 0px 1px #DDD;
cursor: pointer;
}
.send:hover {
background-color: #DDD;
}
.log {
overflow: auto;
margin-top: 1em;
margin-bottom: 2em;
}
.log-send, .log-receive {
display: block;
margin: 0.5em 0em;
white-space: pre-wrap;
max-width: 90%;
}
.log-send {
clear: both;
float: left;
background-color: #DEF;
}
.log-receive {
clear: left;
float: right;
}
.success {
background-color: #DDF8DD;
}
.error {
background-color: #F8DDDD;
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: auto;
width: auto;
padding: 1em;
text-align: center;
opacity: 0.9;
}
/* iframe layout */
.iframe-table {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-spacing: 0;
border-collapse: collapse;
font-size: inherit;
}
.iframe-table td {
padding: 0;
}
#email-row, .iframe .email {
height: 1.5em;
}
#text-row {
position: relative;
}
.iframe .text {
position: absolute;
top: 0;
left: 0;
height: 100%;
resize: none;
}
#send-row {
height: 2em;
}
.iframe .send {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.iframe .email, .iframe .text {
padding: 0.2em 0.3em;
}
</style>
</head>
<body>
<h1>POST for <span class="self-name">{{name}}</span></h1>
<p>This is an HTTP POST endpoint. Any text/document you POST to this URL will be received by the user.</p>
<p>You must provide a <code>From:</code> header (borrowed from SMTP), and can include other mail headers as well.</p>
<h2>Use with cURL:</h2>
<p>To send a plain text message:</p>
<pre><code>curl <span class="cmd-option">--data-binary</span> <span class="cmd-value">"Hello, world"</span> <span class="cmd-option">--header</span> <span class="cmd-value">"Content-Type: text/plain"</span> \
<span class="cmd-option">--header</span> <span class="cmd-value">"From: Somebody <somebody@example.com>"</span> \
<span class="cmd-argument"><span class="self-url">{{url}}</span></span></code></pre>
<p>To send an inline picture:</p>
<pre><code>curl <span class="cmd-option">--data-binary</span> <span class="cmd-value-file">@small-image.png</span> <span class="cmd-option">--header</span> <span class="cmd-value">"Content-Type: image/png"</span> \
<span class="cmd-option">--header</span> <span class="cmd-value">"From: Somebody <somebody@example.com>"</span> \
<span class="cmd-argument"><span class="self-url">{{url}}</span></span></code></pre>
<p>To send a picture (or other document) as an attachment:</p>
<pre><code>curl <span class="cmd-option">--data-binary</span> <span class="cmd-value-file">@large-image.jpg</span> <span class="cmd-option">--header</span> <span class="cmd-value">"Content-Type: image/jpeg"</span> \
<span class="cmd-option">--header</span> <span class="cmd-value">"Content-Disposition: attachment; filename=\"large-image.jpg\""</span> \
<span class="cmd-option">--header</span> <span class="cmd-value">"From: Somebody <somebody@example.com>"</span> \
<span class="cmd-argument"><span class="self-url">{{url}}</span></span></code></pre>
<script>
// Replace template values with JS so we can just use the template on its own
var selfUrl = location.href.replace(/[#?].*/, '');
var selfUrlEscaped = selfUrl.replace(/&/g, '&').replace(/</g, '<');
var backupName = selfUrl.replace(/.*:\/\//, '');
var backupNameEscaped = backupName.replace(/&/g, '&').replace(/</g, '<');
document.title = document.title.replace(/\{\{name\}\}/g, backupName);
document.body.innerHTML = document.body.innerHTML.replace(/\{\{url\}\}/g, selfUrlEscaped).replace(/\{\{name\}\}/g, backupNameEscaped);
function inIframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
function postAjaxMessage(headers, text, callback) {
var request = new XMLHttpRequest();
request.open('POST', window.location.href, true);
// headerObj is map of arrays/strings
var headerObj = headers;
if (typeof headers === 'string') {
headers = headers.split('\n');
for (var i = 0; i < headers.length; i++) {
var line = headers[i] + "";
var name = line.match(/^([a-zA-Z\-]*)\:/);
if (!name) continue;
name = name[1];
var value = line.substring(name.length + 1).replace(/^\s*/, '').replace(/\r/g, '');
headerObj[name] = (headerObj[name] || []).concat(value);
}
}
var headerText = '';
for (var name in headerObj) {
var value = headerObj[name] + "";
try {
request.setRequestHeader(name, value);
} catch (e) {
if (typeof console === 'object' && typeof console.error === 'function') {
console.error(e);
}
continue;
}
headerText += name + ': ' + value + '\n';
}
request.onreadystatechange = function () {
if (request.readyState !== 4) return;
var error = null;
if (request.status >= 300 || request.status < 200) {
error = new Error(request.status + ' ' + request.statusText);
}
callback(error, request.responseText);
};
request.send(text);
return headerText + '\n' + text;
}
if (!inIframe()) {
var h2 = document.createElement('h2');
h2.innerHTML = 'Use with AJAX:';
document.body.appendChild(h2);
var inputHeaders = document.createElement('textarea');
inputHeaders.className = 'headers';
inputHeaders.value = 'Content-Type: text/plain\nFrom: Somebody <somebody@example.com>';
document.body.appendChild(inputHeaders);
var inputText = document.createElement('textarea');
inputText.className = 'text';
inputText.value = 'Hello, world';
document.body.appendChild(inputText);
var sendButton = document.createElement('input');
sendButton.className = 'send';
sendButton.type = 'submit';
sendButton.value = "send";
document.body.appendChild(sendButton);
var logBox = document.createElement('div');
logBox.className = 'log';
document.body.appendChild(logBox);
sendButton.onclick = function () {
var receiveEntry = document.createElement('code');
receiveEntry.className='log-receive';
logBox.insertBefore(receiveEntry, logBox.childNodes[0]);
var sendEntry = document.createElement('code');
sendEntry.className='log-send';
logBox.insertBefore(sendEntry, receiveEntry);
var sentText = postAjaxMessage(inputHeaders.value, inputText.value, function (error, text) {
if (error) {
receiveEntry.className += ' error';
} else {
receiveEntry.className += ' success';
}
if (typeof text === 'string') {
receiveEntry.appendChild(document.createTextNode(text));
}
});
sendEntry.appendChild(document.createTextNode(sentText));
};
} else {
// Sorry, but I need this to work in IE, okay?
document.body.innerHTML = '<table class="iframe-table" cellpadding=0 cellspacing=0 border=0>'
+ '<tr><td id="email-row">'
+ '<input type="text" id="email-input" class="email" placeholder="name@example.com" value="">'
+ '<tr><td id="text-row">'
+ '<textarea id="text-input" class="text" placeholder="Enter your message"></textarea>'
+ '<tr><td id="send-row">'
+ '<input type="submit" id="send-input" class="send" value="send">'
+ '</table>';
document.body.className = 'iframe';
var inputEmail = document.getElementById('email-input');
var inputText = document.getElementById('text-input');
var sendButton = document.getElementById('send-input');
sendButton.onclick = function () {
if (!/@/.test(inputEmail.value) && !/\:\/\//.test(inputEmail.value)) {
inputEmail.focus();
inputEmail.className = 'email error';
return;
} else {
inputEmail.className = 'email';
}
if (!inputText.value) {
inputText.focus();
return;
};
sendButton.disabled = true;
sendButton.value = 'sending...';
var sentText = postAjaxMessage({
from: inputEmail.value,
subject: '(message form)'
}, inputText.value, function (error, text) {
sendButton.value = "send";
sendButton.disabled = false;
var overlay = document.createElement('div');
overlay.className = 'overlay';
document.body.appendChild(overlay);
setTimeout(function () {
overlay.parentNode.removeChild(overlay);
}, 5000);
if (error) {
overlay.className += ' error';
} else {
overlay.className += ' success';
inputText.value = '';
}
if (typeof text === 'string') {
try {
text = JSON.parse(text);
} catch (e) {
//
}
overlay.appendChild(document.createTextNode(text));
}
});
};
}
</script>
</body>
</html>