This repository has been archived by the owner on Jan 23, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 83
/
smtp-server.js
130 lines (109 loc) · 4.76 KB
/
smtp-server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'use strict';
var config = require('config');
var utilities = require('./lib/app-utilities.js');
var debug = require('debug')('mailsac-smtp');
var sanitize = require('sanitizer').sanitize;
var htmlToText = require('html-to-text');
var async = require('async');
module.exports = function smtpFactory(mongoose, smtp, run_port, hooks) {
var Message = mongoose.model('Message');
function onMessageReceived(connection, dataReadyCallback) {
debug('incoming message');
function cleanupMessage(parsedMessage) {
debug('cleanup message');
debug('checking encryption of', connection.inbox);
parsedMessage.originalInbox = connection.inbox+'';
if (connection.inbox.slice(0, 6) === 'inbox-') {
connection.inbox = utilities.decryptInbox(connection.inbox);
debug('inbox was encrypted', connection.inbox);
} else {
debug('inbox was not encrypted', connection.inbox);
}
parsedMessage.inbox = connection.inbox.toLowerCase();
parsedMessage.domain = connection.inbox.split('@')[1];
parsedMessage.encryptedInbox = utilities.encryptInbox(parsedMessage.inbox);
debug('inbox', parsedMessage.inbox);
debug('encryptedInbox', parsedMessage.encryptedInbox);
// parse html to text if no text
if (!parsedMessage.text && parsedMessage.html) {
debug('using html for text because text is missing');
parsedMessage.text = htmlToText.fromString(parsedMessage.html, {
wordwrap: 130
});
}
// parse text to html if no html
var htmlizedText = '<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head><body><div>'
+ (parsedMessage.text || '').replace(/(?:\r\n|\r|\n)/g, '<br />')
+ '</div></body></html>';
parsedMessage.raw = connection.messageText;
parsedMessage.received = new Date();
// body is the sanitized html that is OK to display without warning
if (!parsedMessage.html) {
debug('using htmlizedText', htmlizedText);
parsedMessage.html = htmlizedText;
parsedMessage.body = sanitize(htmlizedText);
} else {
parsedMessage.body = sanitize(parsedMessage.html);
}
debug('text', parsedMessage.text);
return parsedMessage;
}
utilities.parseRawMessage(connection.messageText, function afterParseMessage(err, parsedMessage) {
if (err) {
debug('PARSE FAIL', err.message, err.stack);
return callback(new Error("Unable to parse raw mail"));
}
debug('message was parsed');
new Message(cleanupMessage(parsedMessage)).save(onCreateNewMessage);
function onCreateNewMessage(err, item) {
if (err) {
debug('SAVE EMAIL FAIL', err.message, err.stack, '\n', parsedMessage);
return dataReadyCallback(new Error("Invalid email format"));
}
debug('message was saved', item._id);
dataReadyCallback(null, "O"); // O is the queue id to be advertised to the client
if (hooks.afterCreateMessage && hooks.afterCreateMessage.length) {
hooks.afterCreateMessage.forEach(function (hook) {
hook(item, parsedMessage);
});
}
}
});
};
// Binding everything
if (!smtp || !run_port) {
return;
}
smtp.on("validateRecipient", function (connection, email, callback) {
var emailValidated = utilities.ValidateEmail(email);
if (!emailValidated) {
debug('Invalid email addr', email);
return callback(new Error("Invalid email addr"));
}
connection.full_email = email;
connection.inbox = emailValidated;
callback(false);
});
smtp.on("startData", function (connection) {
connection.messageText = '';
});
// TODO: implement max size
smtp.on("data", function (connection, chunk) {
connection.messageText += chunk;
});
smtp.on("error", function (connection) {
debug("Error from:", connection.from, 'to:', connection.to);
});
/**
* client is finished passing e-mail data,
* callback returns the queue id to the client
*/
smtp.on("dataReady", onMessageReceived);
smtp.listen(run_port, function (err) {
if (err) {
debug('Error starting SMTP', run_port, err);
return;
}
debug('SMTP server listening', 'port', run_port);
});
};