Skip to content

Instantly share code, notes, and snippets.

@cheery
Last active April 13, 2018 10:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cheery/15dccf7df4b2fa5e3c549586d51b3da2 to your computer and use it in GitHub Desktop.
Save cheery/15dccf7df4b2fa5e3c549586d51b3da2 to your computer and use it in GitHub Desktop.
I wonder what's wrong with this.
fs = require 'fs'
os = require 'os'
exports.hook_rcpt = (next, connection, params) ->
rcpt = params[0]
rcpt_to = rcpt.address().toLowerCase()
mail = this.config.get('mail.ini')
connection.loginfo("hook_rcpt running through")
if mail.accounts and mail.accounts[rcpt_to]?
to_maildir = mail.accounts[rcpt_to]
connection.loginfo("told mail goes to: " + to_maildir)
connection.relaying = false
return next(OK)
else if mail.forward and mail.forward[rcpt_to]?
params[0].address(mail.forward[rcpt_to])
connection.relaying = true
connection.loginfo("relaying mail to: " + params[0].address())
return next(OK)
else
connection.relaying = false
return next(DENY, "Mail to " + rcpt_to + " is not allowed here")
exports.hook_queue = (next, connection, params) ->
transaction = connection.transaction
mail = this.config.get('mail.ini')
connection.loginfo("hook_queue running through")
boxes = []
pending = []
done = []
for rcpt in connection.transaction.rcpt_to
rcpt_to = rcpt.address().toLowerCase()
if mail.accounts and mail.accounts[rcpt_to]?
to_maildir = mail.accounts[rcpt_to]
unless to_maildir in boxes
boxes.push(to_maildir)
looper = (args...) ->
if pending.length == 0 and boxes.length == 0
return next(OK)
else if boxes.length == 0
return commit(pending.shift())
else
return receive(boxes.shift())
receive = (to_maildir) ->
maildir = [ mail.main.maildir_base, to_maildir ].join('/')
tmp_path = [ maildir, 'tmp', transaction.uuid ].join('/')
new_path = [ maildir, 'new', transaction.uuid ].join('/')
pending.push({tmp:tmp_path, dst:new_path})
ws = fs.createWriteStream(tmp_path)
ws.once 'close', () ->
looper()
transaction.message_stream.pipe(ws)
commit = (job) ->
fs.link job.tmp, job.dst, (err) ->
if err
connection.logerror("fs.link failed on #{transaction.uuid}: " + err)
fs.unlink job.tmp
clean_on_fail()
next(DENYSOFT, 'queue error')
else
fs.unlink job.tmp
fs.chmod job.dst, "600"
done.push(job)
return looper()
clean_on_fail = () ->
for job in pending
fs.unlink(job.tmp)
for job in done
fs.unlink(job.dst)
return looper()
// Generated by CoffeeScript 1.9.3
(function() {
var fs, os,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
slice = [].slice;
fs = require('fs');
os = require('os');
exports.hook_rcpt = function(next, connection, params) {
var mail, rcpt, rcpt_to, to_maildir;
rcpt = params[0];
rcpt_to = rcpt.address().toLowerCase();
mail = this.config.get('mail.ini');
connection.loginfo("hook_rcpt running through");
if (mail.accounts && (mail.accounts[rcpt_to] != null)) {
to_maildir = mail.accounts[rcpt_to];
connection.loginfo("told mail goes to: " + to_maildir);
connection.relaying = false;
return next(OK);
} else if (mail.forward && (mail.forward[rcpt_to] != null)) {
params[0].address(mail.forward[rcpt_to]);
connection.relaying = true;
connection.loginfo("relaying mail to: " + params[0].address());
return next(OK);
} else {
connection.relaying = false;
return next(DENY, "Mail to " + rcpt_to + " is not allowed here");
}
};
exports.hook_queue = function(next, connection, params) {
var boxes, clean_on_fail, commit, done, i, len, looper, mail, pending, rcpt, rcpt_to, receive, ref, to_maildir, transaction;
transaction = connection.transaction;
mail = this.config.get('mail.ini');
connection.loginfo("hook_queue running through");
boxes = [];
pending = [];
done = [];
ref = connection.transaction.rcpt_to;
for (i = 0, len = ref.length; i < len; i++) {
rcpt = ref[i];
rcpt_to = rcpt.address().toLowerCase();
if (mail.accounts && (mail.accounts[rcpt_to] != null)) {
to_maildir = mail.accounts[rcpt_to];
if (indexOf.call(boxes, to_maildir) < 0) {
boxes.push(to_maildir);
}
}
}
looper = function() {
var args;
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
if (pending.length === 0) {
return next(OK);
} else if (boxes.length === 0) {
return commit(pending.shift());
} else {
return receive(boxes.shift());
}
};
receive = function(to_maildir) {
var maildir, new_path, tmp_path, ws;
maildir = [mail.main.maildir_base, to_maildir].join('/');
tmp_path = [maildir, 'tmp', transaction.uuid].join('/');
new_path = [maildir, 'new', transaction.uuid].join('/');
pending.push({
tmp: tmp_path,
dst: new_path
});
ws = fs.createWriteStream(tmp_path);
ws.once('close', function() {
return looper();
});
return transaction.message_stream.pipe(ws);
};
commit = function(job) {
return fs.link(job.tmp, job.dst, function(err) {
if (err) {
connection.logerror(("fs.link failed on " + transaction.uuid + ": ") + err);
fs.unlink(job.tmp);
clean_on_fail();
return next(DENYSOFT, 'queue error');
} else {
fs.unlink(job.tmp);
fs.chmod(job.dst, "600");
done.push(job);
return looper();
}
});
};
clean_on_fail = function() {
var j, job, k, len1, len2, results;
for (j = 0, len1 = pending.length; j < len1; j++) {
job = pending[j];
fs.unlink(job.tmp);
}
results = [];
for (k = 0, len2 = done.length; k < len2; k++) {
job = done[k];
results.push(fs.unlink(job.dst));
}
return results;
};
return looper();
};
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment