├── .gitignore ├── README.md ├── config.js ├── glservice.js ├── index.js ├── package-lock.json ├── package.json ├── startup.sh └── stop.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | output_mail.log 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | .mail_to_gitlab_issues.pid 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mail_to_gitlab_issues 2 | 3 | 模拟邮件服务器:接收邮件,将邮件内容转发至gitlab的issues 4 | >针对微信微信聊天记录中的 图片/文档/视频附件 做了布局优化(部分机型的聊天记录内容中,图片被统一放到了最下面,聊天记录中仅显示:图片1(可在附件中查看)) 5 | 6 | [抖音视频介绍](https://v.douyin.com/RCvbRhx/) 7 | 8 | ## 配置方法 9 | 1. **域名:** 添加MX记录解析,例如:`@.abc.com`(注意:MX记录只能解析到一个普通A记录,所以你需要提前添加一个A记录,然后将MX记录解析到这个A记录对应的域名上) 10 | 2. **配置文件:** 11 | 1. `mail_domain` 收件箱的后缀,例如:`abc.com` 12 | 2. `gltoken_of_frommail` 配置发件人白名单,同时配置了对应不同发件人使用不同的token对接gitlab 13 | 3. `gitlab_base_url` 配置gitlab根路径,不能以`/`结尾 14 | 4. `issues_timeout` 创建gitlab时的超时时间 15 | 3. **占用问题:** 默认情况下,大部分Linux服务器会自带一个Postfix服务占用25端口,如果使用此程序,需要先将postfix停止掉: 16 | 1. 停止postfix服务: `systemctl stop postfix` 17 | 2. 禁止postfix开机启动: `systemctl disable postfix` 18 | 4. **启动:** 19 | 1. `npm install` (首次启动前,安装依赖) 20 | 2. `./startup.sh` (因为需要监听25端口,故必须使用root用户) 21 | 5. **查看日志文件:** `tail -f ./output_mail.log` 22 | 6. **停止:** `./stop.sh` 23 | 24 | 25 | ## 技巧(2022年02月15日 新增) 26 | 在标题后面添加@xxxx,可以直接将任务分配给某人,其中的xxxx可以是fullname,也可以是username。并且最终的issues标题会自动去掉这部分 27 | > 例如标题是:“修改登录页面样式 @张三”,那么最终的issues标题为“修改登录页面样式”,并且直接将任务分配给张三 28 | 29 | ## 感谢 30 | * [substack/node-smtp-protocol](https://github.com/substack/node-smtp-protocol) 基于smtp协议的邮件服务nodejs版 31 | * [nodemailer/mailparser](https://github.com/nodemailer/mailparser) 邮件内容解析nodejs版 32 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | mail_domain: 'your_mail_domain', 3 | gltoken_of_frommail: { 4 | 'zhangsan@abc.com': 'gitlab_token' 5 | }, 6 | gitlab_base_url: 'http://xxx.xxxx.xxx', // 注意:不能以 “/” 结尾 7 | issues_timeout: 5000 8 | } 9 | -------------------------------------------------------------------------------- /glservice.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | const config = require('./config.js'); 5 | const { resolve } = require('path'); 6 | 7 | const BASE_URL = config.gitlab_base_url + "/api/v4"; 8 | 9 | var default_options = { 10 | timeout: config.issues_timeout 11 | }; 12 | 13 | function buildOptions(gitlab_token) { 14 | var options = {... default_options}; 15 | options.headers = { 'PRIVATE-TOKEN': gitlab_token } 16 | return options; 17 | } 18 | 19 | function uploadfile(proj_id, gitlab_token, file, filename, contentType) { 20 | return new Promise((resolve, reject) => { 21 | var r = request.post(`${BASE_URL}/projects/${proj_id}/uploads`, buildOptions(gitlab_token), (error, response, body) => { 22 | if (error) { 23 | reject(error); 24 | return; 25 | } 26 | resolve(JSON.parse(body)); 27 | }); 28 | var form = r.form() 29 | form.append('file', file, { 30 | filename: filename, 31 | contentType: contentType 32 | }); 33 | }); 34 | } 35 | 36 | 37 | function getAssigneeIdIfExists(gitlab_token, title) { 38 | if (title == null) { 39 | return Promise.resolve(null) 40 | } 41 | let assigneeName = title.replace(/.*@\s*(.*?)\s*$/g, '$1') 42 | if (assigneeName === title) { 43 | return Promise.resolve(null) 44 | } 45 | return new Promise((resolve, reject) => { 46 | request.get(`${BASE_URL}/users?search=${encodeURI(assigneeName)}`, buildOptions(gitlab_token), (error, response, body) => { 47 | if (error) { 48 | reject(error); 49 | return; 50 | } 51 | let resArray = JSON.parse(body).filter(item => item.state === 'active') 52 | if (resArray == null || resArray.length == 0) { 53 | resolve(null) 54 | } else { 55 | resolve(resArray[0].id) 56 | } 57 | }); 58 | }); 59 | } 60 | 61 | 62 | function commitIssues(proj_id, gitlab_token, title, content) { 63 | return new Promise((resolve, reject) => { 64 | getAssigneeIdIfExists(gitlab_token, title).then(assigneeId => { 65 | let r = request.post(`${BASE_URL}/projects/${proj_id}/issues`, buildOptions(gitlab_token), (error, response, body) => { 66 | if (error) { 67 | reject(error); 68 | return; 69 | } 70 | resolve(JSON.parse(body)); 71 | }); 72 | 73 | var form = r.form() 74 | form.append('title', title.replace(/@.*$/g, '')) 75 | form.append('description', content); 76 | if (assigneeId) { 77 | form.append('assignee_id', assigneeId) 78 | } 79 | }) 80 | }); 81 | } 82 | 83 | module.exports = { commitIssues, uploadfile }; 84 | 85 | 86 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var smtp = require('smtp-protocol'); 2 | const simpleParser = require('mailparser').simpleParser; 3 | const request = require('request'); 4 | const config = require('./config.js'); 5 | const { commitIssues, uploadfile } = require('./glservice.js'); 6 | 7 | var server = smtp.createServer(function (req) { 8 | req.on('to', function (to, ack) { 9 | var req_domain = to.split('@')[1] || config.mail_domain; 10 | if (req_domain === config.mail_domain) { 11 | ack.accept(); 12 | } else { 13 | console.log('e1:' + req_domain); 14 | ack.reject(); 15 | } 16 | }); 17 | 18 | 19 | req.on('message', function (stream, ack) { 20 | var gitlabToken = config.gltoken_of_frommail[req.from]; 21 | if(!gitlabToken) { 22 | console.log('gitlabToken is null'); 23 | ack.reject(); 24 | return; 25 | } 26 | 27 | var proj_id = req.to[0].replace(/\@.*$/g, '') 28 | if (!proj_id) { 29 | console.log('proj_id is null'); 30 | ack.reject(); 31 | return; 32 | } 33 | 34 | 35 | simpleParser(stream, {}).then(parsed => { 36 | try { 37 | 38 | var content = parsed.html || parsed.text; 39 | 40 | 41 | var uploadAllAttachments = []; 42 | 43 | for (let i = 0; i < parsed.attachments.length; i++) { 44 | const at = parsed.attachments[i]; 45 | console.log('处理附件:' + at.filename); 46 | uploadAllAttachments.push(uploadfile(proj_id, gitlabToken, at.content, at.filename, at.contentType)); 47 | } 48 | 49 | 50 | Promise.all(uploadAllAttachments).then((resArr) => { 51 | for (let i = 0; i < resArr.length; i++) { 52 | const atRes = resArr[i]; 53 | if (!atRes.markdown) { 54 | console.log(atRes); 55 | } 56 | if (content.indexOf('(可在附件中查看)') >= 0) { 57 | content = content.replace(new RegExp(`((${parsed.attachments[i].filename.replace(/\./g, '\\.')})|(${atRes.alt}))(可在附件中查看)`, "g"), atRes.markdown); 58 | } else { 59 | content = content.replace(/|\/>)/, atRes.markdown) 60 | } 61 | } 62 | 63 | commitIssues(proj_id, gitlabToken, parsed.subject, content).then(res => { 64 | console.log('\n创建成功:' + res.web_url); 65 | }) 66 | 67 | console.log('from: ' + req.from); 68 | console.log('to: ' + req.to); 69 | console.log('subject:' + parsed.subject); 70 | console.log(content); 71 | }) 72 | } catch (e) { 73 | console.log('出错了:\n' + e); 74 | } 75 | 76 | }).catch(err => { 77 | console.log(err); 78 | }); 79 | 80 | ack.accept(); 81 | }); 82 | 83 | req.on('greeting', function(a,b) { 84 | b.accept(); 85 | }); 86 | 87 | }); 88 | 89 | server.listen(25); 90 | 91 | console.log("start listening 25..."); -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mail_to_gitlab_issues", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@selderee/plugin-htmlparser2": { 8 | "version": "0.6.0", 9 | "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", 10 | "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", 11 | "requires": { 12 | "domhandler": "^4.2.0", 13 | "selderee": "^0.6.0" 14 | } 15 | }, 16 | "ajv": { 17 | "version": "6.12.6", 18 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 19 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 20 | "requires": { 21 | "fast-deep-equal": "^3.1.1", 22 | "fast-json-stable-stringify": "^2.0.0", 23 | "json-schema-traverse": "^0.4.1", 24 | "uri-js": "^4.2.2" 25 | } 26 | }, 27 | "asn1": { 28 | "version": "0.2.4", 29 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 30 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 31 | "requires": { 32 | "safer-buffer": "~2.1.0" 33 | } 34 | }, 35 | "assert-plus": { 36 | "version": "1.0.0", 37 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 38 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 39 | }, 40 | "asynckit": { 41 | "version": "0.4.0", 42 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 43 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 44 | }, 45 | "aws-sign2": { 46 | "version": "0.7.0", 47 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 48 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 49 | }, 50 | "aws4": { 51 | "version": "1.11.0", 52 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", 53 | "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" 54 | }, 55 | "bcrypt-pbkdf": { 56 | "version": "1.0.2", 57 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 58 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 59 | "requires": { 60 | "tweetnacl": "^0.14.3" 61 | } 62 | }, 63 | "caseless": { 64 | "version": "0.12.0", 65 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 66 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 67 | }, 68 | "combined-stream": { 69 | "version": "1.0.8", 70 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 71 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 72 | "requires": { 73 | "delayed-stream": "~1.0.0" 74 | } 75 | }, 76 | "commander": { 77 | "version": "2.20.3", 78 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 79 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" 80 | }, 81 | "core-util-is": { 82 | "version": "1.0.3", 83 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 84 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" 85 | }, 86 | "dashdash": { 87 | "version": "1.14.1", 88 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 89 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 90 | "requires": { 91 | "assert-plus": "^1.0.0" 92 | } 93 | }, 94 | "deepmerge": { 95 | "version": "4.2.2", 96 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 97 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" 98 | }, 99 | "delayed-stream": { 100 | "version": "1.0.0", 101 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 102 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 103 | }, 104 | "discontinuous-range": { 105 | "version": "1.0.0", 106 | "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", 107 | "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=" 108 | }, 109 | "dom-serializer": { 110 | "version": "1.3.2", 111 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", 112 | "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", 113 | "requires": { 114 | "domelementtype": "^2.0.1", 115 | "domhandler": "^4.2.0", 116 | "entities": "^2.0.0" 117 | } 118 | }, 119 | "domelementtype": { 120 | "version": "2.2.0", 121 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", 122 | "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" 123 | }, 124 | "domhandler": { 125 | "version": "4.2.2", 126 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", 127 | "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", 128 | "requires": { 129 | "domelementtype": "^2.2.0" 130 | } 131 | }, 132 | "domutils": { 133 | "version": "2.8.0", 134 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", 135 | "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", 136 | "requires": { 137 | "dom-serializer": "^1.0.1", 138 | "domelementtype": "^2.2.0", 139 | "domhandler": "^4.2.0" 140 | } 141 | }, 142 | "duplexer": { 143 | "version": "0.1.2", 144 | "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", 145 | "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" 146 | }, 147 | "ecc-jsbn": { 148 | "version": "0.1.2", 149 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 150 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 151 | "requires": { 152 | "jsbn": "~0.1.0", 153 | "safer-buffer": "^2.1.0" 154 | } 155 | }, 156 | "encoding-japanese": { 157 | "version": "1.0.30", 158 | "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-1.0.30.tgz", 159 | "integrity": "sha512-bd/DFLAoJetvv7ar/KIpE3CNO8wEuyrt9Xuw6nSMiZ+Vrz/Q21BPsMHvARL2Wz6IKHKXgb+DWZqtRg1vql9cBg==" 160 | }, 161 | "entities": { 162 | "version": "2.2.0", 163 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", 164 | "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" 165 | }, 166 | "extend": { 167 | "version": "3.0.2", 168 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 169 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 170 | }, 171 | "extsprintf": { 172 | "version": "1.3.0", 173 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 174 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 175 | }, 176 | "fast-deep-equal": { 177 | "version": "3.1.3", 178 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 179 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 180 | }, 181 | "fast-json-stable-stringify": { 182 | "version": "2.1.0", 183 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 184 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" 185 | }, 186 | "forever-agent": { 187 | "version": "0.6.1", 188 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 189 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 190 | }, 191 | "form-data": { 192 | "version": "2.3.3", 193 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 194 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 195 | "requires": { 196 | "asynckit": "^0.4.0", 197 | "combined-stream": "^1.0.6", 198 | "mime-types": "^2.1.12" 199 | } 200 | }, 201 | "getpass": { 202 | "version": "0.1.7", 203 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 204 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 205 | "requires": { 206 | "assert-plus": "^1.0.0" 207 | } 208 | }, 209 | "har-schema": { 210 | "version": "2.0.0", 211 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 212 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 213 | }, 214 | "har-validator": { 215 | "version": "5.1.5", 216 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 217 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 218 | "requires": { 219 | "ajv": "^6.12.3", 220 | "har-schema": "^2.0.0" 221 | } 222 | }, 223 | "he": { 224 | "version": "1.2.0", 225 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 226 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" 227 | }, 228 | "html-to-text": { 229 | "version": "8.0.0", 230 | "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.0.0.tgz", 231 | "integrity": "sha512-fEtul1OerF2aMEV+Wpy+Ue20tug134jOY1GIudtdqZi7D0uTudB2tVJBKfVhTL03dtqeJoF8gk8EPX9SyMEvLg==", 232 | "requires": { 233 | "@selderee/plugin-htmlparser2": "^0.6.0", 234 | "deepmerge": "^4.2.2", 235 | "he": "^1.2.0", 236 | "htmlparser2": "^6.1.0", 237 | "minimist": "^1.2.5", 238 | "selderee": "^0.6.0" 239 | } 240 | }, 241 | "htmlparser2": { 242 | "version": "6.1.0", 243 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", 244 | "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", 245 | "requires": { 246 | "domelementtype": "^2.0.1", 247 | "domhandler": "^4.0.0", 248 | "domutils": "^2.5.2", 249 | "entities": "^2.0.0" 250 | } 251 | }, 252 | "http-signature": { 253 | "version": "1.2.0", 254 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 255 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 256 | "requires": { 257 | "assert-plus": "^1.0.0", 258 | "jsprim": "^1.2.2", 259 | "sshpk": "^1.7.0" 260 | } 261 | }, 262 | "iconv-lite": { 263 | "version": "0.6.3", 264 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 265 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 266 | "requires": { 267 | "safer-buffer": ">= 2.1.2 < 3.0.0" 268 | } 269 | }, 270 | "inherits": { 271 | "version": "2.0.4", 272 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 273 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 274 | }, 275 | "is-typedarray": { 276 | "version": "1.0.0", 277 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 278 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 279 | }, 280 | "isarray": { 281 | "version": "0.0.1", 282 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 283 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 284 | }, 285 | "isstream": { 286 | "version": "0.1.2", 287 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 288 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 289 | }, 290 | "jsbn": { 291 | "version": "0.1.1", 292 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 293 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 294 | }, 295 | "json-schema": { 296 | "version": "0.2.3", 297 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 298 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 299 | }, 300 | "json-schema-traverse": { 301 | "version": "0.4.1", 302 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 303 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 304 | }, 305 | "json-stringify-safe": { 306 | "version": "5.0.1", 307 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 308 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 309 | }, 310 | "jsprim": { 311 | "version": "1.4.1", 312 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 313 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 314 | "requires": { 315 | "assert-plus": "1.0.0", 316 | "extsprintf": "1.3.0", 317 | "json-schema": "0.2.3", 318 | "verror": "1.10.0" 319 | } 320 | }, 321 | "libbase64": { 322 | "version": "1.2.1", 323 | "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.2.1.tgz", 324 | "integrity": "sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==" 325 | }, 326 | "libmime": { 327 | "version": "5.0.0", 328 | "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.0.0.tgz", 329 | "integrity": "sha512-2Bm96d5ktnE217Ib1FldvUaPAaOst6GtZrsxJCwnJgi9lnsoAKIHyU0sae8rNx6DNYbjdqqh8lv5/b9poD8qOg==", 330 | "requires": { 331 | "encoding-japanese": "1.0.30", 332 | "iconv-lite": "0.6.2", 333 | "libbase64": "1.2.1", 334 | "libqp": "1.1.0" 335 | }, 336 | "dependencies": { 337 | "iconv-lite": { 338 | "version": "0.6.2", 339 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", 340 | "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", 341 | "requires": { 342 | "safer-buffer": ">= 2.1.2 < 3.0.0" 343 | } 344 | } 345 | } 346 | }, 347 | "libqp": { 348 | "version": "1.1.0", 349 | "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", 350 | "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" 351 | }, 352 | "linkify-it": { 353 | "version": "3.0.3", 354 | "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", 355 | "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", 356 | "requires": { 357 | "uc.micro": "^1.0.1" 358 | } 359 | }, 360 | "mailparser": { 361 | "version": "3.4.0", 362 | "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.4.0.tgz", 363 | "integrity": "sha512-u2pfpLg+xr7m2FKDl+ohQhy2gMok1QZ+S9E5umS9ez5DSJWttrqSmBGswyj9F68pZMVTwbhLpBt7Kd04q/W4Vw==", 364 | "requires": { 365 | "encoding-japanese": "1.0.30", 366 | "he": "1.2.0", 367 | "html-to-text": "8.0.0", 368 | "iconv-lite": "0.6.3", 369 | "libmime": "5.0.0", 370 | "linkify-it": "3.0.3", 371 | "mailsplit": "5.3.1", 372 | "nodemailer": "6.7.0", 373 | "tlds": "1.224.0" 374 | } 375 | }, 376 | "mailsplit": { 377 | "version": "5.3.1", 378 | "resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-5.3.1.tgz", 379 | "integrity": "sha512-o6R6HCzqWYmI2/IYlB+v2IMPgYqC2EynmagZQICAhR7zAq0CO6fPcsO6CrYmVuYT+SSwvLAEZR5WniohBELcAA==", 380 | "requires": { 381 | "libbase64": "1.2.1", 382 | "libmime": "5.0.0", 383 | "libqp": "1.1.0" 384 | } 385 | }, 386 | "mime-db": { 387 | "version": "1.50.0", 388 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", 389 | "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==" 390 | }, 391 | "mime-types": { 392 | "version": "2.1.33", 393 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", 394 | "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", 395 | "requires": { 396 | "mime-db": "1.50.0" 397 | } 398 | }, 399 | "minimist": { 400 | "version": "1.2.5", 401 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 402 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 403 | }, 404 | "moo": { 405 | "version": "0.5.1", 406 | "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", 407 | "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" 408 | }, 409 | "nearley": { 410 | "version": "2.20.1", 411 | "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", 412 | "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", 413 | "requires": { 414 | "commander": "^2.19.0", 415 | "moo": "^0.5.0", 416 | "railroad-diagrams": "^1.0.0", 417 | "randexp": "0.4.6" 418 | } 419 | }, 420 | "nodemailer": { 421 | "version": "6.7.0", 422 | "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.0.tgz", 423 | "integrity": "sha512-AtiTVUFHLiiDnMQ43zi0YgkzHOEWUkhDgPlBXrsDzJiJvB29Alo4OKxHQ0ugF3gRqRQIneCLtZU3yiUo7pItZw==" 424 | }, 425 | "oauth-sign": { 426 | "version": "0.9.0", 427 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 428 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 429 | }, 430 | "parseley": { 431 | "version": "0.7.0", 432 | "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", 433 | "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", 434 | "requires": { 435 | "moo": "^0.5.1", 436 | "nearley": "^2.20.1" 437 | } 438 | }, 439 | "performance-now": { 440 | "version": "2.1.0", 441 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 442 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 443 | }, 444 | "psl": { 445 | "version": "1.8.0", 446 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 447 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" 448 | }, 449 | "punycode": { 450 | "version": "2.1.1", 451 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 452 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 453 | }, 454 | "qs": { 455 | "version": "6.5.2", 456 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 457 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 458 | }, 459 | "railroad-diagrams": { 460 | "version": "1.0.0", 461 | "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", 462 | "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=" 463 | }, 464 | "randexp": { 465 | "version": "0.4.6", 466 | "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", 467 | "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", 468 | "requires": { 469 | "discontinuous-range": "1.0.0", 470 | "ret": "~0.1.10" 471 | } 472 | }, 473 | "readable-stream": { 474 | "version": "1.1.14", 475 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 476 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 477 | "requires": { 478 | "core-util-is": "~1.0.0", 479 | "inherits": "~2.0.1", 480 | "isarray": "0.0.1", 481 | "string_decoder": "~0.10.x" 482 | } 483 | }, 484 | "request": { 485 | "version": "2.88.2", 486 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 487 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 488 | "requires": { 489 | "aws-sign2": "~0.7.0", 490 | "aws4": "^1.8.0", 491 | "caseless": "~0.12.0", 492 | "combined-stream": "~1.0.6", 493 | "extend": "~3.0.2", 494 | "forever-agent": "~0.6.1", 495 | "form-data": "~2.3.2", 496 | "har-validator": "~5.1.3", 497 | "http-signature": "~1.2.0", 498 | "is-typedarray": "~1.0.0", 499 | "isstream": "~0.1.2", 500 | "json-stringify-safe": "~5.0.1", 501 | "mime-types": "~2.1.19", 502 | "oauth-sign": "~0.9.0", 503 | "performance-now": "^2.1.0", 504 | "qs": "~6.5.2", 505 | "safe-buffer": "^5.1.2", 506 | "tough-cookie": "~2.5.0", 507 | "tunnel-agent": "^0.6.0", 508 | "uuid": "^3.3.2" 509 | } 510 | }, 511 | "ret": { 512 | "version": "0.1.15", 513 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", 514 | "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" 515 | }, 516 | "safe-buffer": { 517 | "version": "5.2.1", 518 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 519 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 520 | }, 521 | "safer-buffer": { 522 | "version": "2.1.2", 523 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 524 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 525 | }, 526 | "selderee": { 527 | "version": "0.6.0", 528 | "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", 529 | "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", 530 | "requires": { 531 | "parseley": "^0.7.0" 532 | } 533 | }, 534 | "shallow-copy": { 535 | "version": "0.0.1", 536 | "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", 537 | "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" 538 | }, 539 | "smtp-protocol": { 540 | "version": "2.4.7", 541 | "resolved": "https://registry.npmjs.org/smtp-protocol/-/smtp-protocol-2.4.7.tgz", 542 | "integrity": "sha1-mQAAXj138MgzirAd5islvTrf2oM=", 543 | "requires": { 544 | "shallow-copy": "~0.0.1", 545 | "stream-combiner": "~0.0.2", 546 | "through": "^2.3.4", 547 | "through2": "^1.0.0" 548 | } 549 | }, 550 | "sshpk": { 551 | "version": "1.16.1", 552 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 553 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 554 | "requires": { 555 | "asn1": "~0.2.3", 556 | "assert-plus": "^1.0.0", 557 | "bcrypt-pbkdf": "^1.0.0", 558 | "dashdash": "^1.12.0", 559 | "ecc-jsbn": "~0.1.1", 560 | "getpass": "^0.1.1", 561 | "jsbn": "~0.1.0", 562 | "safer-buffer": "^2.0.2", 563 | "tweetnacl": "~0.14.0" 564 | } 565 | }, 566 | "stream-combiner": { 567 | "version": "0.0.4", 568 | "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", 569 | "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", 570 | "requires": { 571 | "duplexer": "~0.1.1" 572 | } 573 | }, 574 | "string_decoder": { 575 | "version": "0.10.31", 576 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 577 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 578 | }, 579 | "through": { 580 | "version": "2.3.8", 581 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 582 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 583 | }, 584 | "through2": { 585 | "version": "1.1.1", 586 | "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", 587 | "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", 588 | "requires": { 589 | "readable-stream": ">=1.1.13-1 <1.2.0-0", 590 | "xtend": ">=4.0.0 <4.1.0-0" 591 | } 592 | }, 593 | "tlds": { 594 | "version": "1.224.0", 595 | "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.224.0.tgz", 596 | "integrity": "sha512-Jgdc8SEijbDFUsmCn6Wk/f7E6jBLFZOG3U1xK0amGSfEH55Xx97ItUS/d2NngsuApjn11UeWCWj8Um3VRhseZQ==" 597 | }, 598 | "tough-cookie": { 599 | "version": "2.5.0", 600 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 601 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 602 | "requires": { 603 | "psl": "^1.1.28", 604 | "punycode": "^2.1.1" 605 | } 606 | }, 607 | "tunnel-agent": { 608 | "version": "0.6.0", 609 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 610 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 611 | "requires": { 612 | "safe-buffer": "^5.0.1" 613 | } 614 | }, 615 | "tweetnacl": { 616 | "version": "0.14.5", 617 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 618 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 619 | }, 620 | "uc.micro": { 621 | "version": "1.0.6", 622 | "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", 623 | "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" 624 | }, 625 | "uri-js": { 626 | "version": "4.4.1", 627 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 628 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 629 | "requires": { 630 | "punycode": "^2.1.0" 631 | } 632 | }, 633 | "uuid": { 634 | "version": "3.4.0", 635 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 636 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 637 | }, 638 | "verror": { 639 | "version": "1.10.0", 640 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 641 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 642 | "requires": { 643 | "assert-plus": "^1.0.0", 644 | "core-util-is": "1.0.2", 645 | "extsprintf": "^1.2.0" 646 | }, 647 | "dependencies": { 648 | "core-util-is": { 649 | "version": "1.0.2", 650 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 651 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 652 | } 653 | } 654 | }, 655 | "xtend": { 656 | "version": "4.0.2", 657 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 658 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 659 | } 660 | } 661 | } 662 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mail_to_gitlab_issues", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mailparser": "^3.4.0", 13 | "request": "^2.88.2", 14 | "smtp-protocol": "^2.4.7" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /startup.sh: -------------------------------------------------------------------------------- 1 | if [ `whoami` != "root" ];then 2 | echo "请使用root用户!" 3 | exit; 4 | fi 5 | nohup node ./index.js >> ./output_mail.log 2>&1 & echo $! > .mail_to_gitlab_issues.pid -------------------------------------------------------------------------------- /stop.sh: -------------------------------------------------------------------------------- 1 | if [ `whoami` != "root" ];then 2 | echo "请使用root用户!" 3 | exit; 4 | fi 5 | 6 | echo "停止中..." 7 | mail_to_gitlab_issues=$(cat .mail_to_gitlab_issues.pid) 8 | 9 | kill -9 $mail_to_gitlab_issues 10 | 11 | rm -rf .mail_to_gitlab_issues.pid 12 | echo "已停止" --------------------------------------------------------------------------------