@timshel_npm/maildev
Version:
SMTP Server with async API and Web Interface for viewing and testing emails during development
192 lines (164 loc) • 5.91 kB
JavaScript
/* global angular, app, prompt */
/**
* Email item Controller -- The UI for the email pane
*/
app.controller("ItemCtrl", [
"$scope",
"$rootScope",
"$routeParams",
"$location",
"Email",
"$http",
"$cookies",
function ($scope, $rootScope, $routeParams, $location, Email, $http, $cookies) {
// Get the item data by route parameter
const getItem = function () {
Email.get(
{ id: $routeParams.itemId },
function (email) {
$scope.item = new Email(email);
if ($scope.item.html) {
$scope.item.iframeUrl = "email/" + $scope.item.id + "/html";
prepIframe();
$scope.panelVisibility = "html";
} else {
$scope.htmlView = "disabled";
$scope.panelVisibility = "plain";
}
},
function () {
console.error("404: Email not found");
$location.path("/");
},
);
};
// Get email source
const getSource = function () {
if (typeof $scope.rawEmail === "undefined") {
$scope.rawEmail = "email/" + $scope.item.id + "/source";
}
};
// Prepares the iframe for interaction
const prepIframe = function () {
// Wait for iframe to load
setTimeout(function () {
const [iframe] = document.getElementsByTagName("iframe");
const [head] = iframe.contentDocument.getElementsByTagName("head");
const baseEl = iframe.contentDocument.createElement("base");
// Append <base target="_blank" /> to <head> in the iframe so all links open in new window
baseEl.setAttribute("target", "_blank");
if (head) head.appendChild(baseEl);
replaceMediaQueries(iframe);
fixIframeHeight(iframe);
addHideDropdownHandler(iframe.contentDocument.getElementsByTagName("body")[0]);
}, 500);
};
// Updates the iframe height so it matches it's content
// This prevents the iframe from having scrollbars
const fixIframeHeight = function (iframe) {
const body = iframe.contentDocument.getElementsByTagName("body")[0];
const newHeight = body.scrollHeight;
iframe.height = newHeight;
};
// Updates all media query rules to use 'width' instead of device width
const replaceMediaQueries = function (iframe) {
angular.forEach(iframe.contentDocument.styleSheets, function (styleSheet) {
angular.forEach(styleSheet.cssRules, function (rule) {
if (rule.media && rule.media.mediaText) {
// TODO -- Add future warning if email doesn't use '[max|min]-device-width' media queries
rule.media.mediaText = rule.media.mediaText.replace("device-width", "width");
}
});
});
};
// NOTE: This is kind of a hack to get these dropdowns working. Should be revisited in the future
// Toggle a dropdown open/closed by toggling a class on the trigger itself
$scope.toggleDropdown = function ($event, dropdownName) {
$event.stopPropagation();
$scope.dropdownOpen = dropdownName === $scope.dropdownOpen ? "" : dropdownName;
};
function hideDropdown(e) {
$scope.$apply(function () {
$scope.dropdownOpen = "";
});
}
function addHideDropdownHandler(element) {
angular.element(element).off("click", hideDropdown).on("click", hideDropdown);
}
addHideDropdownHandler(window);
function validateEmail(email) {
const 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,}))$/;
return re.test(email);
}
// Toggle what format is viewable
$scope.show = function (type) {
if ((type === "html" || type === "attachments") && !$scope.item[type]) {
return;
}
if (type === "source") getSource();
$scope.panelVisibility = type;
};
// Sends a DELETE request to the server
$scope.delete = function (item) {
Email.delete({ id: item.id });
};
// Updates iframe to have a width of newSize, i.e. '320px'
$scope.resize = function (newSize) {
const [iframe] = document.getElementsByTagName("iframe");
iframe.style.width = newSize || "100%";
fixIframeHeight();
$scope.iframeSize = newSize;
};
// Relay email to
$scope.relayTo = function (item) {
const lastRelayTo = $cookies.relayTo;
const relayTo = prompt("Please enter email address to relay", lastRelayTo);
if (relayTo) {
if (validateEmail(relayTo)) {
$scope.relay(item, relayTo);
$cookies.relayTo = relayTo;
} else {
window.alert("The specified email address is not correct.");
}
}
};
// Relay email
$scope.relay = function (item, relayTo) {
if (!$rootScope.config.isOutgoingEnabled) {
window.alert(
"Relay feature has not been configured.\n" + "Run maildev --help for configuration info.",
);
return;
}
if (
window.confirm(
"Are you sure you want to REALLY SEND email to " +
(relayTo ||
item.to
.map(function (to) {
return to.address;
})
.join()) +
" through " +
$rootScope.config.outgoingHost +
"?",
)
) {
$http({
method: "POST",
url: "email/" + item.id + "/relay" + (relayTo ? "/" + relayTo : ""),
})
.success(function (data, status) {
console.log("Relay result: ", data, status);
window.alert("Relay successful");
})
.error(function (data) {
window.alert("Relay failed: " + data.error);
});
}
};
// Initialize the view by getting the email
getItem();
},
]);