Node.js如何从邮件中获取smime.p7s并提取发件人、组织名称及验证签名?
解决方案
原因说明
imap 包的 attributes 对象仅会识别显式标记为独立附件的普通文件,S/MIME 签名的 smime.p7s 属于邮件嵌套多部分(MIME)结构的内嵌部分,不会被 imap 直接解析到属性列表中,你在正文中看到的边界分隔内容就是未拆分的原始 MIME 结构。
实现步骤
1. 解析完整邮件MIME结构
使用专门的邮件解析库 mailparser 搭配 imap 读取完整邮件原始内容,自动拆分所有附件(包括S/MIME签名文件)。
首先安装依赖:
npm install imap mailparser
示例代码:
const Imap = require('imap'); const { simpleParser } = require('mailparser'); const imap = new Imap({ user: '你的邮箱账号', password: '你的邮箱密码', host: 'IMAP服务器地址', port: 993, tls: true }); imap.once('ready', () => { imap.openBox('INBOX', false, (err, box) => { // 搜索目标邮件,示例为拉取最新1封邮件 imap.search(['ALL', ['UID', box.uidnext - 1]], (err, results) => { const f = imap.fetch(results, { bodies: '', struct: true }); f.on('message', (msg) => { msg.on('body', (stream) => { // 直接将原始邮件流传入解析器 simpleParser(stream, (err, parsed) => { // 筛选S/MIME签名附件 const smimeSign = parsed.attachments.find(att => att.contentType === 'application/pkcs7-signature' ); if (smimeSign) { // smimeSign.content 就是p7s签名文件的Buffer内容 handleSignature(smimeSign.content); } }); }); }); }); }); }); imap.connect();
2. 解析签名、提取信息并验证有效性
使用 node-forge 库处理p7s签名内容,提取发件人、组织信息并校验签名有效性。
安装依赖:
npm install node-forge
示例代码:
const forge = require('node-forge'); function handleSignature(p7sBuffer) { // 转换Buffer为forge可识别格式 const p7Asn1 = forge.asn1.fromDer(p7sBuffer.toString('binary')); const pkcs7 = forge.pkcs7.messageFromAsn1(p7Asn1); // 提取签名者证书信息 const signCert = pkcs7.certificates[0]; const subjectAttrs = signCert.subject.attributes; // 提取发件人名称、所属组织 const senderName = subjectAttrs.find(item => item.name === 'commonName')?.value; const orgName = subjectAttrs.find(item => item.name === 'organizationName')?.value; // 验证签名有效性(验证邮件未被篡改、签名和证书匹配) const signValid = pkcs7.verify(); console.log('发件人名称:', senderName); console.log('所属组织:', orgName); console.log('签名是否有效:', signValid); }
补充说明
- 如果需要校验证书的信任链,可将信任的根CA证书导入到forge的证书存储中,避免信任不可信的自签名证书
- 如果是加密S/MIME邮件,需要额外导入收件人私钥解密后才能进行后续校验
- 该需求完全可以实现,不需要依赖外部服务
内容的提问来源于stack exchange,提问作者Stanislav
相关产品推荐
相关产品推荐

