用Nodejs搭建简单smtp服务器

用Nodejs搭建简单smtp服务器

最近在公司用node写了一个小程序,搭建一个简单的smtp服务器,用来接收邮件,然后根据邮件的收件人地址,再把内容分发到他rtx、手机短信和外网邮箱上。本来这个功能有个用python写的例子,全部代码不过80行。感叹python这门语言确实精练,而且第三方模块和参考资料比node要多,只需简单的import smtpd模块就可以轻松搞定了,对于MIME解析也只需要import email这个模块。

但是python做不到对email流的精准控制(可能是我不懂怎么弄,py高手别喷啊),而且最近一直在搞node,所以打算用node来实现整个工作流程,顺便也测试下1.0版本的rrestjs框架。

要完成作业,我们面临以下问题: 1、如何用node建立一个smtp服务器,监听25端口 2、如何对MIME流做解析,变成我们想要的subject,text,from,to等我们需要的东西 3、如何把邮件转发外网邮箱

问题1、 在谷歌了一阵子之后,我打算使用substack写的node-smtp-protocol模块,这哥们上次在hujs上见过,长头发很腼腆的一个男孩,他写的模块应该挺靠谱,再说万一有什么问题也方便联系的上他。 github地址:https://github.com/substack/node-smtp-protocol 例子挺简单:

var smtp = require('smtp-protocol');
var server = smtp.createServer(function (req) {
   req.on('greeting', function (to, ack) {
   ack.accept();
  });
  req.on('from', function (to, ack) {
   ack.accept();
  });
  req.on('to', function (to, ack) {
   filter(to, ack);//过滤smtp请求    
  });
  req.on('message', function (stream, ack) {
   serial(stream, ack, req.to);
  });
 });
 server.listen(25);
 console.log('starting mail server listen port 25.')

这样我们就建立起来了一个smtp服务器了,我们监听了greeting,from,to和message事件,代码中的ack.accept代表返回状态码250,表示成功,而message则表示客户端开发发送email的body流。 如果在message之前的阶段你想阻拦这次回话,只需要调用 ack.reject()方法拦截掉即可。

搭建起来之后,我只需要用telnet ip 25命令连接上node smtp服务器,测试截屏如下:

enter image description here

当中的^[[A这段无视,打错了,我们成功起来了一个smtp服务器了,当然我们可以在触发 to 或者 from 这些事件时做一下限制,只允许特定来源或者特定目标。

问题2、启动了mail服务器,但是我们对于mail的内容处理还停留在最原始的MIME格式流上,如何正确处理MIME流成为我们获取mail内容的关键问题了,很幸运,我找到了MailParser这个模块。 github地址:https://github.com/andris9/mailparser 这个模块使用起来更加简单,因为node-smtp-protocol模块提供了stream流,所以我们只需写如下代码就可以解析它:

var MailParser = require("mailparser").MailParser;
req.on('message', function (stream, ack) {
   stream.pipe(mailparser);
   mailparser.on("end", function(mail_object){
    console.log(mail_object);//这里就是解析好的mail格式
   })
   ack.accept();
  });

下面我们做一个简单例子,我们用outlook填写一份测试邮件发往node smtp服务器

enter image description here

在node smtp服务器端输出如下格式的内容

enter image description here

MailParser做的相当的不错,还根据信息中的GBK编码,转换成了utf-8,防止了乱码的产生。 这样问题2我们也圆满解决了,正确解析了MIME流的内容

问题3、似乎不是问题,就不多介绍了,使用 Nodemailer 可以很轻松的转发一封电子邮件,大家都用的很熟了。 github地址:https://github.com/andris9/Nodemailer

完成作业了,似乎用node搭建一个简单smtp服务器不比python费多少劲,但是代码量比python要多出不少。 另外需要注意,在node smtp监听了25端口之前,可能需要把sendmail服务器关闭,否则会存在端口inuse错误。


7 回复

用Node.js搭建简单SMTP服务器

最近在公司用Node.js写了一个小程序,搭建一个简单的SMTP服务器,用来接收邮件,然后根据邮件的收件人地址,再把内容分发到他们的RTX、手机短信和外网邮箱上。原本这个功能有个Python写的例子,全部代码不过80行。感叹Python这门语言确实精练,而且第三方模块和参考资料比Node.js要多,只需简单的import smtpd模块就可以轻松搞定了,对于MIME解析也只需要import email这个模块。

但是Python做不到对email流的精准控制(可能是我不懂怎么弄,Py高手别喷啊),而且最近一直在搞Node.js,所以打算用Node.js来实现整个工作流程,顺便也测试下1.0版本的Restify框架。

要完成作业,我们面临以下问题:

  1. 如何用Node.js建立一个SMTP服务器,监听25端口。
  2. 如何对MIME流进行解析,变成我们想要的subject、text、from、to等我们需要的东西。
  3. 如何把邮件转发到外网邮箱。

问题1:如何用Node.js建立一个SMTP服务器,监听25端口

在Google了一阵子之后,我打算使用Substack写的node-smtp-protocol模块。这个模块的作者是一位非常有才华的开发者,他的代码应该比较可靠。此外,万一有什么问题也可以方便联系到他。

GitHub地址:node-smtp-protocol

以下是简单的示例代码:

const smtp = require('smtp-protocol');
const server = smtp.createServer((req) => {
    req.on('greeting', (to, ack) => {
        ack.accept(); // 返回状态码250,表示成功
    });

    req.on('from', (to, ack) => {
        ack.accept();
    });

    req.on('to', (to, ack) => {
        // 过滤SMTP请求
        filter(to, ack);
    });

    req.on('message', (stream, ack) => {
        // 处理邮件内容
        stream.pipe(mailparser);
        mailparser.on('end', (mail_object) => {
            console.log(mail_object); // 解析好的邮件对象
        });
        ack.accept();
    });
});

server.listen(25);
console.log('Starting mail server listening on port 25.');

这样我们就建立起来了了一个SMTP服务器,我们监听了greeting、from、to和message事件。ack.accept()代表返回状态码250,表示成功,而message则表示客户端发送邮件的body流。如果在message之前的阶段你想阻拦这次会话,只需要调用ack.reject()方法拦截掉即可。

问题2:如何对MIME流进行解析

启动了mail服务器,但是我们对于mail的内容处理还停留在最原始的MIME格式流上。如何正确处理MIME流成为我们获取mail内容的关键问题了。很幸运,我找到了MailParser这个模块。

GitHub地址:MailParser

这个模块使用起来更加简单,因为node-smtp-protocol模块提供了stream流,所以我们只需写如下代码就可以解析它:

const MailParser = require('mailparser').MailParser;

req.on('message', (stream, ack) => {
    const mailparser = new MailParser();
    stream.pipe(mailparser);

    mailparser.on('end', (mail_object) => {
        console.log(mail_object); // 这里就是解析好的mail格式
    });

    ack.accept();
});

问题3:如何把邮件转发到外网邮箱

似乎不是问题,使用Nodemailer可以很轻松地转发一封电子邮件。大家都用得很熟了。

GitHub地址:Nodemailer

完成作业了,似乎用Node.js搭建一个简单的SMTP服务器不比Python费多少劲,但是代码量比Python要多出不少。另外需要注意,在Node SMTP监听了25端口之前,可能需要把sendmail服务器关闭,否则会存在端口inuse错误。


求封装

哈哈,封装了还不如用python了就3,4行代码

有smtp的module

mark一下,过一阵能用上。

怎么我发不出邮件,又没有报错

用Node.js搭建一个简单的SMTP服务器主要分为三步:监听25端口、解析MIME流、转发邮件。以下是基于你的需求的一个简单示例。

1. 建立SMTP服务器

首先,你需要安装smtp-protocol模块来创建SMTP服务器:

npm install smtp-protocol

然后,可以使用下面的代码来监听25端口:

const smtp = require('smtp-protocol');

const server = smtp.createServer((req) => {
  // 处理HELO/EHLO指令
  req.on('greeting', (from, ack) => {
    ack.accept();
  });

  // 处理FROM指令
  req.on('from', (from, ack) => {
    ack.accept();
  });

  // 处理TO指令
  req.on('to', (to, ack) => {
    ack.accept();
  });

  // 处理消息内容
  req.on('message', (stream, ack) => {
    const mailparser = new (require('mailparser')).MailParser();
    stream.pipe(mailparser);

    mailparser.on('end', (mail) => {
      console.log(`Received an email: ${mail.subject} from ${mail.from.text}`);
      // 在这里可以添加处理逻辑,比如转发邮件
      ack.accept();
    });
  });
});

server.listen(25, () => {
  console.log('Starting mail server on port 25.');
});

2. 解析MIME流

这里我们已经通过mailparser来解析MIME流,提取邮件主题、正文、发件人、收件人等信息。

3. 转发邮件

你可以使用nodemailer来转发邮件:

npm install nodemailer

示例代码如下:

const nodemailer = require('nodemailer');

// 创建一个简单的Nodemailer transporter对象
let transporter = nodemailer.createTransport({
  host: 'smtp.example.com',
  port: 587,
  secure: false, // true for 465, false for other ports
  auth: {
    user: 'username@example.com', // 发件人的邮箱账号
    pass: 'password' // 邮箱密码或应用专用密码
  }
});

// 在mailparser的'end'事件中转发邮件
mailparser.on('end', (mail) => {
  let mailOptions = {
    from: mail.from.text,
    to: mail.to.text,
    subject: mail.subject,
    text: mail.text
  };

  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      return console.log(error);
    }
    console.log('Message sent: %s', info.messageId);
  });
});

以上就是一个基本的Node.js SMTP服务器实现。你可以根据实际需求调整代码,并确保在生产环境中进行充分的安全性和稳定性测试。

回到顶部